Git 的常用方法简介

来源:互联网 发布:抢商品软件 编辑:程序博客网 时间:2024/06/05 15:15

Git 的常用方法简介--主体是从网上抄来的,进行了些整编修改,向原作者致敬

 

使用git参与kernel开发

 

$ gitclone git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git

 

其他的git trees可以在http://git.kernel.org/找到,点击进去就能看到GIT URL


使用git

自从git-1.5.4'git-xyz'这种用法就不提倡了,而推荐'git xyz'风格。 git的后续版本中将在make install

时不再安装'git-xyz'这些hardlinks

当如果执行git --exec-path输出的目录中依然有git-xyz这些脚本,你还是可以把这个路径加到PATH环境变量中,

这样还能够使用git-xyz形式的脚本。

config

   ------

   我的一些简单的配置:

 

   $ git-config user.name "Jike Song"

   $ git-config user.email [email]albcamus@gmail.com[/email]

   $ git-config core.editor vim

   $ git-config core.pager "less -N"

   $ git-config color.diff true //显示diff时色彩高亮

   $ git-config alias.co checkout //git checkout取个别名,这样只输入git co即可

   $ git-config sendemail.smtpserver /usr/bin/msmtp

 

   注意,这会在当前repository目录下的.git/config中写入配置信息。 如果git-config加了--global

   选项,配置信息就会写入到~/.gitconfig文件中。 因为你可能用不同的身份参与不同的项目,而多个

   项目都用git管理,所以建议不用--global配置。

 

  $ git-val -l //列出git变量

 

 

   init

   ----

 

   $ git-init-db //创建一个.git/目录,初始化一个空的git仓库

//这个目录在git-clone时也会创建。也就是说clone时会自动初始化git

//仓库里需要的东西

 

   clone

   -----

 

   $ git-clone git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git [dir name]

   [dir name]是你想让这个仓库叫什么名字。 如果不指定,就会等同于目标仓库的名字。

 

   注意,这种git server形式的repository,都有一个filename.git文件; 而对于*.git的操作,也可以

   针对.git所在的目录:

 

$ mkdir tmp/

$ cd tmp/

$ git-clone ~/Sources/linux-2.6

 

   或者通过ssh

 

$ git-clone [email]arc@host.xyz.com[/email]:/home/arc/Sources/linux-2.6

 

   此时当前目录下有一个.git/目录以下我们都在linux-2.6/下演示:

 

   pull

   ----

   $ git-pull //更新本地的git tree 如果自从你clonelinus tree之后,linus tree

//有新的改动,那么把这些更改更新到你的本地tree中

//类似于cvs update

 

  FYI:  git-clonegit-pull都会默认调用git-merge

 

  FYI: 每天git-pull更新技巧:

1) git-describe,例如目前是v2.6.26-rc8-12

2) git-pull -v

3) git-describe,例如是v2.6.26-rc8-22

4) git-log -p -10查看变化

 

   diff

   ----

   $ git-diff /*列出自己本地的tree中已修改、但却未commit的改动

  这也是产生patch的方式(用来提交的patch需要先commit到自己的tree里,

  然后git-format-patch) 注意,使用git-diff产生的patch都应该在

  patch(1)时指定-p1,或者直接使用git-apply打补丁

 */

   选项:

     --color diff语法高亮(可以git-config color.diff true)

     --ignore-space-at-eol  忽略行尾的whitespace

     -b

     --ignore-space-change  忽略行尾的whitespace,并且认为所有的whitespace都是一样的

     -w

     --ignore-all-space 比较两行的时候,完全忽略whitespace。这样,即使是一行有很多

     whitespaces,另一行文字一样但是没有whitespacegit也认为这两

行内容一致。

 

 

   FYI: diff不同的branches

 

    /* 下面这两种写法是一样的,都是列出:与jike分支相比,master分支有哪些不同 */

    $ git-diff jike..master

    $ git-diff jike master

 

    /* 列出自从jike分支从master分支脱离以来,master分支又有过哪些改动 */

    $ git-diff jike...master

 

/*{{{*/   git-diff的详细用法:

 

   列出自己的tree HEAD和某一个tag的不同:

   $ git-diff v2.6.22

 

   列出某一个文件,和以前某个tag的该文件的不同:

   $ git diff v2.6.20 init/main.c

   注意结果中+表示自己的tree-表示2.6.20的。

 

   列出两个tags之间的不同:

   $ git-diff v2.6.20..v2.6.21-rc1

 

   列出两个commits之间的不同(Notes,是这两次commits之间的commits引入的所有改动):

      $ git-diff 2a062ab483f5afd764fb20631ee960672946a4be..a44008f2372684bacfab03de5039f68b613c5b53

 

   列出两个tags的某一文件的不同:

   $ git-diff v2.6.23 v2.6.24-rc1 init/main.c

 

   or:

 

   $ git-diff v2.6.25-rc3:kernel/module.c v2.6.25-rc4:kernel/module.c

 

   or:

 

   $ git-diff v2.6.25-rc3:kernel/module.c HEAD:kernel/module.c

 

 

   事实上,git-loggit-whatchanged等命令都可以这么用。

/*}}}*/

 

   apply

   -----

 

   $ git-apply 相当于patch(1)命令,不过git-apply专门用来apply那些用git-diff生成的补丁

   --check //不真正打补丁,而只是检查补丁是否能完美的打上

   -v      //verbose模式

   -R //reverse模式,也就是拉出这个补丁来(而不是打进去)

 

   gui

   ---

   $ git-gui

 

or:

 

   $ gitk //GUI模式。还有一些不在git包中的git GUI前端。 我觉得基于Qtqgit最好用

 

 

 

  revision list

  -------------

 

   $ git-rev-list <ID>以时间为顺序,反向列出revision ID 也就是先列最新的commit ID

   也可以指定列出的数目,例如:

 

   $ git-rev-list -2 971a71bdc9b42e74a5a8ed0433ac27ae92291024

  log

  ---

 

   查看某一文件都被哪些补丁改动过:

 

   $ git-whatchanged -p security/Kconfig

 

   查看某一文件的每一行的作者和Revision ID

 

   $ git-blame  security/Kconfig

 

     or:

 

   $ git-annotate security/Kconfig

 

   查看某一版本的某一文件:

 

   $ git-show v2.6.22:init/main.c

 

   查看两个tags之间的log(git-shortlog也可以这么用)

 

   $ git-log v2.6.25-rc3..v2.6.25-rc4

   :

   $ git-log -p v2.6.24..v2.6.25-rc1 arch/x86/kernel/smp_64.c

   :

   $ git-whatchanged v2.6.24..v2.6.25-rc1 arch/x86/kernel/smp_64.c

 

   查看某版本之后的log

 

   $ git-log v2.6.25-rc4..HEAD  //HEAD可以省略,直接写成git-log v2.6.25-rc4..

 

 

  撤销最近的commit

  ----------------

 

   $ git-reset HEAD~1 //HEAD~1这种方式也可以表示为HEAD^

   $ git-diff |git-apply -R -v

 

   注意:1) git-resetgit-revert不同,后者是把补丁作为另一个commit反向打入tree中,而reset

     是真正的撤销; 2) 如果撤销最近的ncommits,就用git-reset HEAD~<n>,例如HEAD~2

 

 

  回退到某个tagcommit

  --------------------

  例如目前我的linux-2.6里是:

 

$ git-desribe 

v2.6.26-3465-g5b664cb

 

我想让它回退到v2.6.26时的状态(程序和ref log一起回退) git-log搜索"Linux 2.6.26"commit ID为:

 

bce7f793daec3e65ec5c5705d2457b81fe7b5725

 

那么:

 

$ git-reset --hard bce7f793daec3e65ec5c5705d2457b81fe7b5725

--hard不但会reset你的working tree,而且联index files一起reset:整个回到你指定的commit状态。

 

 

   reset/reflog

   ------------

        举例来说,reset你的当前branchtip(HEAD所在的那个commit)

 

$ git-reset HEAD^

 

选项:

 

--mixed  只撤销掉index中的commit,却保留那个commit对应的内容

--hard  indexworking dir全撤销,也就是commit消失,并且其内容也消失

--soft  indexworking dir都不动,只"require them to be in a good order" (

这是man git-reset中的话,什么意思?。这会让该commit修改的文件变

成"dded but not yet committed"的状态。

 

如果不加这3个参数之一,那git-reset默认就是--mixed方式。

 

 

/*{{{*/[FYI] git-reset --hard之后又想恢复

 

      git中,除非你运行了git-gc --prune,否则历史是永远不会被擦除的,你可以随意恢复到任何历史状态。 下面就是

      一个恢复被git-reset --hard擦除了的commit的例子:

 

//reset最近的commit

$ git-reset --hard HEAD^

HEAD is now at bc45eb8 Merge git://git.kernel.org/pub/scm/linux/kernel/git/herbert/crypto-2.6

 

//查看reflog

$ git-reflog

bc45eb8... HEAD@{0}: HEAD^: updating HEAD

a7dc750... HEAD@{1}: commit: [PCI] code cleanup : remove dead pci_remove_device_safe()

bc45eb8... HEAD@{2}: checkout: moving from jike to bc45eb8950b8c14487385cfd2bda1613ca8d9703

 

//reset回去

$ git-reset --hard HEAD@{1}  //注意,HEAD@{1}就是我们要恢复的那个状态

HEAD is now at a7dc750 [PCI] code cleanup : remove dead pci_remove_device_safe()

 

注意也可以把reflog列出来的历史状态checkout出来:

 

$ git-checkout HEAD@{30} -b new_branch

/*}}}*/

 

 

 

stash

-----

git-stash是个很有趣的功能,它可以让你把目前的dirty内容"隐藏"起来,使得你的仓库看起来是干净的。

这在两种情况下很有用:

 

1,修改了一个文件,尚未commit,此时又想去修改别的文件;

2,切换到别的branch之前,把尚未commit的改动stash一下,以防git-checkout命令丢弃了你的

   未提交的修改。

 

 

用法:

 

$ git-stash

 

参数:

list  //列出所有stash了的项目,注意会显示stashID

show [-p] [stash@{<id>}] //查看某个stash-p会显示补丁。 如果不指定id,则show最近stash的那个

apply [stash@{<id>}]  //恢复某个stash 如果不指定id,则apply最近stash的那个

save  //stash当前的未提交的改动

clear  //销毁所有stash了的未提交改动

 

不加参数的话,默认行为就是save。

 

 

例如:

$ git-stash list

stash@{0}: WIP on test: 42bb109... a commit to fix. --fixed in git-rebase, "edit"

stash@{1}: WIP on test2: 10253e6... Merge branch 'test' into test2

stash@{2}: WIP on test2: 10253e6... Merge branch 'test' into test2

 

注意'test'和'test2'都是branch。

 

$ git-stash show -p stash@{2}

 

$ git-stash apply stash@{2}

 

注意,$ git-stash pop相当于从stash 栈里头apply一个stash,亦即:git-stash apply stash@{0}

 

可以把任一分支的stash给apply到当前分支上。

 

 

 

 

 

 

 

 add

 ---

 新加文件到index中,使得git可以跟踪它:

 

   $ git-add <filename>  //类似于cvs add <filename> 如果<filename>是目录,那么git-add

   //会自动去递归地添加该目录下的所有文件和子目录

   $ git-add -a //本目录下所有文件和子目录

 

   git-add 实际上是对git-update-index的调用,git-add hello.c就相当于:

 

$ git-update-index --add hello.c

 

commit

------

 

   $ git-commit -e -s -a

       -s   增加Signed-off-by

   -e 调用vim(我在.git/config里制定的editor)进行编辑 commit message

   -a all

   -v vim中编辑commit msg时,连补丁本身也显示在其中

 

delete

------

删除文件:

 

   $ git-rm aa.c 

   $ git-commit 

 

 

撤销一次commit

--------------

 

   $ git-log  /* 找到要撤销的commit ID */

   $ git-revert adb2f08089edac8bf1912a618a74485ab42f2b86 //指定导致删除操作的commit ID,进行撤消

 

 

列出某一个commit ID对应的补丁

-----------------------------

 

   $ git-log -1 -p 721151d004dcf01a71b12bb6b893f9160284cf6e

   -1的意思是只显示一个commit。如果你想显示5个,就-5。不指定的话,git log会从该commit一直往后显示。

 

   选项:

   --color  diff语法高亮

 

or:

 

   $ git-format-patch --stdout -1 721151d004dcf01a71b12bb6b893f9160284cf6e

   --stdout指定git写到标准输出,否则会写入到磁盘中。

 

or:

 

   $ git-show 721151d004dcf01a71b12bb6b893f9160284cf6e

 

 

git-shortlog

------------

 

类似于git-log,只是简略。

 

 

git-bisect的用法

----------------

/*{{{*/   $ git-bisect start

   $ git-bisect bad    //该版本的kernel标记为bad

 

   或者有针对性的:

 

   /* 只对2.6.22-rc1之后、2.6.22-rc2之间的commits进行bisect */

   $ git-bisect bad v2.6.22-rc1

   $ git-bisect good v2.6.22-rc2

 

 

LABEL:   在你指定了badgood之后,如果这两个版本之间有1000revisionsgit就默认剔除了500个,你应该在此时测试该版本:

 

   创建一个临时性的output目录:

 

   $ make ../git_bisect_output/

   编译:

 

   $ make O=../git_bisect_output/ menuconfig 

   $ make O=../git_bisect_output/ V=1 -j4 

   $ sudo make O=../git_bisect_output/ V=1 modules_install install

   注意,最好在menuconfig时,给local version加上一个string,例如take1take2等。

 

   启动新编译的kernel,如果还有BUG

 

   $ git-bisect bad

 

   如果没有BUG了:

 

   $ git-bisect good

 

   goto LABEL;

 

 

   直到某个时候,只剩下一个revision可以怀疑,那时候就可以确认是它引入了BUG 

 

   bisect结束,恢复到master版本:

 

# git-bisect reset

 

 

   [注意]

   git bisect是一个漫长而痛苦的过程。我在Dell Optiplex745(2G内存/Core2双核2G)机器上足足做了一天,才定位到一个BUG

 

   [replay的用法]

   如果应该输入git-bisect good的时候,不小心输入了git-bisect bad 或者本应该输入git-bisect bad的时候不小心写成了

git-bisect good 则可以这样回退:

 

1) git-bisect log | tee ../git.bisect.log

2) 修改../git.bisect.log,删掉最后两行 -- 也就是回退1步。 如果需要回退N步,那就删掉N个最后两行

3) git-bisect replay ../git.bisect.log

 

   [visualize的用法]

   git-bisect的时间很长,因为可能需要编译N次内核。 在此期间,可以用:

 

$ git-bisect visualize

 

来在gitk中查看目前还待检验的那些Revs。 

FYI: 如果你象我一样更喜欢qgit,可以修改`which git-bisect`脚本,将'gitk'字样替换成'qgit'

/*}}}*/

 

 

修改上次commit的log message

---------------------------

 

   //下面这个方法真土..事实上,git-citool只是git-commitGUI形式

   $ git-citool GUI界面的git-commit 不但可以提交,而且可以编辑上次commit的信息。

 

or:

 

   //修改

   $ git-commit --amend

 

同理,使用git-commit的--amend模式还可以修改last commit *内容*.

 

-> git-stash    //藏起未提交的工作,make your branch looks `clean'

-> 修改文件,直到你满意

-> git-commit -a --amend  //编辑msg

-> git-stash apply  //undo the stash

 

 

修改某个commit的msg和内容!!

---------------------------

 

[WARNING] 修改一个已经不在HEAD位置的commit,无论是修改其msg还是内容,都必须发生在 *commit尚未被

  2人看到的情况下,也就是说,没有push给别人,也没有被别人pull过。

  否则,这种修改会造成开发社区的混乱(think about that...)

 

 

假定我们同时修改msg和内容:

[FYI] 对于只修改msg的情形,也走这个步骤,但是注意"5, rebase"的时候,选edit(而不是squash)即可。

 

1, 记住那个要修改的commit IDSHA1串的前5个字母即可。 例如它是27675

 

2, 记住27675的前一个commit,例如它是534e3

 

3, git-show 27675看看它的内容,并用Vim修改相应的文件,改到自己满意为止;

 

4, 提交改动

 

$ git-commit -a -m "a new commit, just to be combined with 27675"

 

假设其ID是12345。

 

5, rebase

 

$ git-rebase -i 534e3

 

   这时git会调用vim来让你编辑,你会看到一行行"pick 1acb3e <commit msg>",这些commits都是发生在

   我们要在git-rebase 指定的534e3之后的。 此时:

 

-> 如果你删除一行,那么git-rebase就会让这个commit消失;

-> 如果你删除所有行,那么git-rebase就放弃这次操作;

-> 如果你把某一行的"pick"改成了"squash",那么git-rebase就会把这个commit *合并到它的上一行

   commit里,并再次调用Vim让你编辑合并后的commit msg

-> 如果你把某一行的"pick"改成"edit",那么git就会让你执行: a) git-commit --amend b) git-rebase

   --continue,这样可以修改其msg 注意SHA1 ID会改变。

 

   我们需要的就是上面的第3种情形。 找到12345那行,把pick改成squash,然后dd删除该行,p命令粘贴在27675

   那行的下面,:wq退出Vim

 

   马上Git会再次调用Vim,让你编辑合并后的commitmsg  编辑后保存退出。

 

6, 再次查看合并后的commit

 

$ git-log 查找msg 或者 git-whatchanged -p <file>查找补丁

 

   这时你发现新commitID变了,既不是27675也不是12345,而是一个新的SHA1 ID

 

 

 

 

desribe

-------

 

   $ git-describe

   v2.6.25-rc2-347-g97f7905

 

merge

-----

   git-pull/git-push会默认调用git-merge,一般会成功; 如果失败,那就要:

 

   1, 该命令必然失败,因为confilicts存在:

 

   $ git-merge

 

   2, 查看冲突(冲突的地方已经像CVS update冲突那样,在冲突文件中用>>>>和<<<<标记了):

 

$ git-diff

 

   3, 修改冲突文件,改成你想要的样子

 

   4, 更新index

 

$ git-update-index

 

   5, commit这次merge

 

$ git-commit -a -e -s

 

 

archive

-------

可以把当前版本(HEAD所处的位置)给export出来。 e.g.

 

   $ git-describe

   v2.6.25-rc4-155-g10c36be

 

   $ mkdir ../linux-2.6.25-rc2-347-g97f7905

   $ git-archive -v v2.6.25-rc2-347-g97f7905 | (cd ../linux-2.6.25-rc2-347-g97f7905/ && tar xf -)

   $ head -4 ../linux-2.6.25-rc2-347-g97f7905/Makefile

   VERSION = 2

   PATCHLEVEL = 6

   SUBLEVEL = 25

   EXTRAVERSION = -rc2

 

 

从本地git仓库中提取某个版本的kernel:

 

   $ git-archive -v v2.6.18 | (cd ../linux-2.6.18/ && tar xf -)

   -v表示--verbose,注意'v2.6.18'可以是git-tag -l列出来的tags中的一个,也可以是其他Rev ID例如HEAD等。

 

导出最新的kernel:

 

   $ git-archive -v HEAD | (cd ../linux-HEAD/ && tar xf -)

 

或者打成tarball:

 

   $ git-archive -v --format=tar v2.6.24 |bzip2 > ../linux-2.6.24.tar.bz2

 

tag

---

 

列出当前已有的tags:

 

   $ git-tag [-l]

 

添加tag:

 

   $ git-tag v2.6.26-test

 

删除:

 

   $ git-tag -d v2.6.26-test

 

 

branch/checkout

---------------

 

添加/删除分支:

 

添加一个叫jike的分支:

 

   $ git-branch jike

 

删除该branch:

 

   $ git-branch -d jike

 

列出所有分支:

 

   $ git-branch   //列出所有本地分支

   $ git-branch -a //列出所有分支,包括remote  local branches

   $ git-branch -r //列出remote branches

 

查看目前在哪个branch上

 

$ git-branch

jike

*master

 

切换到某个branch:

 

   $ git-checkout jike    /* 从当前分支(一般是master)checkout并切换到jike分支 */ 

   -f 表示覆盖jike分支里未提交的内容(FIXME:是不是连master分支里未提交的内容也都丢失了?)

 

/*{{{*/ 例子:从remote的分支checkout到一个新的本地branch

 

   例如我clone了一个远程的仓库,进入那个目录,看看有哪些branches

 

$ git-branch -a

* master

origin/multiple-msi-20080711

 

   这时候我有可能想把origin/multiple-msi-20080711这个remote branchcheckout出来,并

   为它新建一个叫做msi的本地branch

 

$ git-checkout origin/multiple-msi-20080711 -b msi

 

   再看看:

 

$ git-branch -a

master

* msi

origin/multiple-msi-20080711

 

/*}}}*/

 

/*{{{*/Linux自从2.6.24-rc1,就开始把i386和x86-64合并为x86的工作,有时候需要track旧的代码。

(say, 我不知道git-whatchanged -p arch/x86/kernel/apic_32.c怎么能够连以前的arch/i386/kernel/apic.c

也跟踪到) 这时候可以有一个workaround checkout v2.6.23这个tag

 

$ git-checkout v2.6.23

注意,只有在git 1.5.x以及更新的版本上才支持这个操作。 这样checkout之后,HEADdetach掉了,

亦即:你不在任何branch上。git-branch会告诉你你在(no branch)上。

那么,怎么切换到原来的状态? 再次git-checkout master即可。

 

在1.5之前,也包括现在,还可以为v2.6.23创建一个branch,用于查看i386或者x86-64的版本历史:

 

$ git-checkout v2.6.23 -b v2.6.23

/*}}}*/

 

注意,有了master和jike两个分支之后,所有的修改、commit、revert工作,都在jike这个branch

上进行;而master这个branch,只用来每天git pull保持和upstream的同步。

 

 

 

rebase

------

 

当jike这个分支有自己的commit、自己的改动,要重新和master分支同步一下

(将自己的local commits重新rebasemaster里新引入的改动之上)

 

$ git-checkout jike

$ git-rebase -i master 

-i,表示interactive

/* 如果rebase失败,说明有冲突(jikemaster冲突),修改,然后:

 *       $ git-rebase --continue

 */

 

/*{{{*/ 一个git-rebase的例子:

 

//目前有master和jike两个branches

[arc@localhost linux-2.6]$ git-branch

  jike

* master

 

//master分支比jike新

[arc@localhost linux-2.6]$ git-describe

v2.6.27-rc5-361-g82a28c7

[arc@localhost linux-2.6]$ git-checkout jike

Switched to branch "jike"

[arc@localhost linux-2.6]$ git-describe

v2.6.27-rc5-320-gf8a561a

 

//jike分支的HEAD位于一个local commit

[arc@localhost linux-2.6]$ git log -1

      1 commit f8a561aa5fef94becc76a5509a369b742f925058

      2 Author: Jike Song <[email]albcamus@gmail.com[/email]>

      3 Date:   Mon Sep 8 22:26:14 2008 +0800

      4

      5     PCI: utilize calculated results when detecting MSI features

      6

      7     in function msi_capability_init, we can make use of the calculated

      8     results instead of calling is_mask_bit_support and is_64bit_address

      9     twice, in spite of the fact that they are macros.

     10

     11     Signed-off-by: Jike Song <[email]albcamus@gmail.com[/email]>

 

//在jike分支里执行git-rebase,-i表示interactive

[arc@localhost linux-2.6]$ git-rebase -i master

Successfully rebased and updated refs/heads/jike.

 

//已经rebase了master分支,现在jike分支除了作为HEAD的local commit之外,和master一样了

//注意,这里jike分支是rc5-362,此时master分支是rc5-361,正好多一个commit,就是我本地的这个

[arc@localhost linux-2.6]$ git-describe

v2.6.27-rc5-362-gedaa7ca

[arc@localhost linux-2.6]$ git log -1

      1 commit edaa7ca47705cc6ca695e267f88f91dbe958da44

      2 Author: Jike Song <[email]albcamus@gmail.com[/email]>

      3 Date:   Mon Sep 8 22:26:14 2008 +0800

      4

      5     PCI: utilize calculated results when detecting MSI features

      6

      7     in function msi_capability_init, we can make use of the calculated

      8     results instead of calling is_mask_bit_support and is_64bit_address

      9     twice, in spite of the fact that they are macros.

     10

     11     Signed-off-by: Jike Song <[email]albcamus@gmail.com[/email]>

/*}}}*/

 

 

pull

----

(pull的访问方式也适用于clone)

 

pull某一个分支:

 

例如我想在/mnt/usb3/linux-2.6的master分支上,来pull ~/Sources/linux-2.6jike分支:

 

   $ cd /mnt/usb3/linux-2.6

   $ git-pull -v /home/arc/Sources/linux-2.6 jike:master

   --no-commit 告诉git不要真正commit,就像出现merge confilict了一样。 这样可以给执行

   git pull的用户一个机会来review他从别人那里pull来的这些代码。

 

FYI:通过SSH协议:

 

   $ git-pull [email]root@myhost.xyz.com[/email]:/export/home/Sources/linux-2.6 master:master

 

把同一仓库中的master分支pull到jike分支:

 

   $ git-pull -v . master:jike

 

 

pull request

------------

 

   $ git-request-pull <start commit> <url> [<end>]

 

   产生pull request信息,打印到标准输出。 其中<end>可以不指定,这样就默认为HEAD。 <url>应该是

   一个git url,例如"git://git.infradead.org/users/jaswinder/linux-2.6-tip.git",这个url会包含

   git-request-pull的输出中.

 

push

-----

例如我在/mnt/usb3/linux-2.6上,想把push到~/Sources/linux-2.6中:

 

   $ cd /mnt/usb3/linux-2.6

   $ git-push  ~/Sources/linux-2.6  master:refs/remotes/jike

 

"master:refs/remotes/master"是传给git-push的refspec,告诉git把我这里的master分支push到<url>指定

的仓库(这里是~/Sources/linux-2.6)的jike分支上。 

 

然后,并不是说在~/Sources/linux-2.6上的jike分支已经merge了/mnt/usb3/linux-2.6的master分支了,还

需要这样:

 

   $ cd ~/Sources/linux-2.6

 

   $ git-pull -v .  refs/remotes/jike:jike //真正pulljike分支上

 

grep

----

例如我看到dmesg的一个报错:

evdev.c(EVIOCGBIT): Suspicious buffer size 511, limiting output to 64 bytes. 

See http://userweb.kernel.org/~dtor/eviocgbit-bug.html

想看看内核中哪里报的(当然这个例子都给出文件名了):

 

   $ git-grep "limiting output to"

         1 drivers/input/evdev.c:                          "limiting output to %zu bytes. See "

 

 

优化

----

git使用一段时间之后,仓库会越来越大,需要隔一段时间就手工执行命令来优化(FIXME: TBD)

 

   $ git-gc

   FYI: 'gc' stands for 'garbage collection'

 

   $ git-prune

 

   $ git-fsck

 

alias

-----

git允许自定义命令的alias,在.git/config中添加:

 

[alias]

co = checkout

 

那么执行git co就相当于git checkout

 

 

 

mailinfo & am

-------------

 

   $ git-mailinfo msg patch  <   /path/to/your/filename.eml

   分析邮件,把commit log写到msg文件,补丁写到patch文件。 其他信息打印到标准输出。

 

从mail文件中打补丁:

 

   $ git-am --utf8 -s  <  /path/to/your/filename.eml

   -s等价于--signoff

 

   git-am会在当前目录下产生一个.dotest/目录,如果成功apply,这个目录会消失;如果git-am失败,则需要手工

   解决冲突,修改到一个自己满意的状态,然后执行:

 

   $ git-am --resolved

 

   这时会继续尝试从.dotest目录中apply这个邮件中的补丁。 或者,作为maintainer,你认为这个补丁需要重写,

   现在放弃apply它:

 

   $ git-am --skip

 

 

send-email

----------

 

在普通的网络环境里(我用mail.hit.edu.cn的SMTP server) 有时出现错误:

 

Need MIME::Base64 and Authen::SASL todo auth

 

这说明需要安装MIME::Base64和Authen::SASL两个包:

 

$ sudo yum -y install perl-Email-MIME-Encodings perl-Authen-SASL

 

然后:

 

$ git-send-email --to [email]someone@somewhare.com[/email] --compose /

--smtp-server 202.118.224.153 --smtp-server-port 25 /

--smtp-user albcamus /

/path/to/your/filename.patch

 

只要指定了--smtp-user,如果需要密码,会在命令行提示输入(不回显).

 

 

用gmail的smtp账户发邮件

-----------------------

1. 安装msmtp

2. 建立~/.msmtprc文件,chmod0600,内容为:

 

   //一种配置。 已验证此~/.msmtprc文件在公司内网可用,但Linux上不行

defaults

tls on

account gmail

host smtp.gmail.com

from [email]albcamus@gmail.com[/email]

auth on

user [email]albcamus@gmail.com[/email]

password [mypasswd]

port 587

account default:gmail

 

   //另一种配置。 Linux上,公司里和家里都能用

   //注意/etc/pki/tls/certs/ca-bundle.crt在我的FC8上是openssl包中的

       defaults

       tls on

       tls_trust_file /etc/pki/tls/certs/ca-bundle.crt

       logfile ~/.msmtp.log

       # My email service

       account gmail

       host smtp.gmail.com

       port 587

       from [email]albcamus@gmail.com[/email]

       auth on

       user [email]albcamus@gmail.com[/email]

       password 

       # Set a default account

       account default : gmail

 

 

   注意上面的~/.msmtprc文件中,password命令后面,或者跟上真正的SMTP密码(只能以明文保存!),或者

   留空。 如果留空,而你的SMTP server要求一个密码,msmtp会去查询~/.netrc文件; 如果还找不到,那

   么就会在命令行(当然我们是在git-send-email的提示下,因为并不直接调用msmtp命令)提示你输入,并

   且不回显密码。

 

   FIXME: 为什么我用git-send-email发送补丁时,总是会发送两封邮件? 第一封是什么内容都没有的,

     (subject则是--subject指定的,或者--compose调用Vim编写的),第2封才是真正的补丁?

 

 

3. 发送

 

$ cd ~/Sources/linux-2.6

$ git-send-email --to <[email]someone@xx.com[/email]> --compose --smtp-server /usr/bin/msmtp  </path/to/your/patch/file>

 

   也可以把msmtp写到.git/config中去:

 

$ git-config sendemail.smtpserver /usr/bin/msmtp

 

   这样在调用git-send-email的时候默认就会以msmtp程序作为smtp server -- 当然如果你又指定了"--smtp-server"的话,就

   不会采用.git/config里的配置了。

 

 

 

 

使用git-tools来处理mbox里的patch:

---------------------------------

 

$ git clone git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/git-tools.git 

然后编译、安装。 

 

它提供了applypatch, cvs2git, dotest, mailinfo, mailsplit, stripspace这些工具。

 

 

email注意事项

-------------

 

1) 可以用xclip程序来复制补丁

 

  $ git-format-patch -1 --stdout <SHA1 ID> | xclip

  Note, xclip程序目前似乎不能处理UTF-8字符。

 

   然后鼠标中键粘贴。

 

2) 确认你的编辑器不wrap word

 

   如使用thunderbird的插件:External Editor指定Vim编辑器(say, "konsole -e vim")等,确认不wrap word

 

   FYI: 不知道为什么External Editor指定konsole -e vim,会自动set tw=72,即使是~/.vimrc设置了tw=0

   不行。 这时候给vim加上参数-c "set tw=0"就可以了,亦即告诉vimload完文件后执行"set tw=0"这个

命令。

 

   我是这么指定external editor的:

 

konsole --noframe --nomenubar --noscrollbar --notabbar -e vim -c "set tw=0"

 

3) thunderbird设置

 

   1, View > Sort by 选择Threaded,可以把同一主题的Re:xxx分层列出。

 

   2, View Settings for this account > composition & addressing,

 

uncheck "Compose messages in HTML format"

 

   3, 编辑~/.thunderbird/92r39mnp.default/prefs.js文件,加两行:

 

user_pref("mailnews.wraplength", 0);

user_pref("mailnews.send_plaintext_flowed", false);

 

      注意 92r39mnp.default ~/.thunderbird/profiles.ini中的Path字段的值。

 

 4) NOTE: 即使用了这些设置,用了Vim编辑邮件,使用thunderbird发补丁依然会遇到malformed问题:( 我真是

    没办法了,只好只用git-send-email...

 

 

 

 

 

使用free git hosting

--------------------

 

Internet上有很多免费的git hosting sites,你可以把自己的项目放在上边,以便和别人协同开发。 git官方站点

有一个页面列出了常用的站点:

 

http://git.or.cz/gitwiki/GitHosting

 

其中最老的site是:

 

http://repo.or.cz

 

该站点要求项目必须是*free software*

 

另一个现在最受欢迎(没用过,看别人的评论)的是:

 

http://github.com/

 

GITHUB把projects分为3种: a) opensource projects,免费; b) personal projects,收费; c) business projects

当然收费:)

 

 

 

 

 

 

 

 

 

88, AKA 2007 Linux内核开发者大会 Bryan Wu的演讲'living rules in kernel community'

 

    kernel.org 3方面重要功能: 1, git trees

        各个git trees的地址和说明:

        http://git.kernel.org/

     2, bugzilla

 3, LKML

    各个邮件列表的地址:

    http://vger.kernel.org/vger-lists.html

 

    一个lkml的归档下载:

    http://userweb.kernel.org/~akpm/lkml-mbox-archives/

    2000年的都有。

 

    TERM:

 

    mailine == linus tree

    vanilla == stable kernel

 

    rcX    == linus tree上的git tag,每个rc版本会持续1-2

 

    merge window  : 例如从2.6.222.6.23-rc1,此时称为merge window is open.

        一般情况下merge window2周时间。

    这时可以发有很大改动的patch(es).

    2.6.23-rc1开始,称做merge window is closed. 只有bugfix

    等,不接受大的改动。

 

    -mm   : Andrew Mortongit tree,实际上是patches的打包,每个rc版会有1-3

    mm trees

    http://www.kernel.org/pub/linux/kernel/people/akpm/patches/2.6/

 

    2.6.x.y : stable tree,由Greg KH维护的稳定版本,主要是引入对2.6.x

  一些漏洞修正等补丁。 ([email]stable@kernel.org[/email])

 

    -git<N> : 一些gitsnapshots,可以从这里下载:

http://www.kernel.org/pub/linux/kernel/v2.6/snapshots/

 

 

    补丁的注意事项:

    1, 一行不能超过80列,这是硬规定

2, scripts/checkpatch.pl检查自己的patch

3, 所有的patch都要通过LKML

 

 

    git及其他:

    1, quilt -mm tree用它管理patches

2, guilt quilt for git

http://www.kernel.org/pub/linux/kernel/people/jsipek/guilt/

3, git-gui, gitk, qgit, gitweb, etc...

 

Pastedfrom <http://www.chinaunix.net/jh/4/920610.html>

 

 

 

原创粉丝点击