使用git参与kernel开发

 

87, git & kernel notes
(
[FYI]
a> Google Talk: Linus Torvalds on git
   http://www.youtube.com/watch?v=4XpnKHJAok8
b> Google Talk: Randal Schwartz on git
   http://www.youtube.com/watch?v=8dhZ9BXQgc4
b> git
中文教程(写于2006年,内容还适用)
   http://www.bitsun.com/documents/gittutorcn.htm
)
   
    1, Linus
git treeAKA 'mainline kernel':

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

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


   
    2,
安装git docs
   
      
要有asciidocwish命令,安装tcl/tkasciidoc.  wish命令在tk-x.xx.xx包中。

        $ sudo make install-doc
   

    3, TERMs in git

           SHA1 ID      :
由一个commit的内容和msg共同产生的一个全局唯一的ID
                      
用前5个字母就够了,git-describe列出来的就是。
           HEAD         :
当前branchlastest commit,也叫tip (remember 'hg tip'?)
                      HEAD
SHA1 ID可以用git-show HEAD来产看
           ORIG_HEAD        :
原来的HEAD。 可以用git-show ORIG_HEAD来查看其SHA1 ID
                      /* FIXME:
我觉得这个"原来",是针对那些可能导致HEAD移动的操作而言,
                       *
例如mergepullreset --hard等。
                       */


    4,
使用git
    [FYI]
自从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 albcamus@gmail.com
           $ 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

 

差异分析工具

 

git config --global merge.tool vimdiff
http://progit.chunzi.me/zh/ch1-5.html

 


       注意,这会在当前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 arc@host.xyz.com:/home/arc/Sources/linux-2.6

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

       pull
       ----
           $ git-pull       //
更新本地的git tree。 如果自从你clonelinus tree之后,linus tree
                    //
有新的改动,那么把这些更改更新到你的本地tree
                    //
类似于cvs update

          FYI:  git-clone
git-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..

Log过滤方法:

git log --stat --grep="usb gadget"

     
撤销最近的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      index
working dir全撤销,也就是commit消失,并且其内容也消失
                --soft      index
working 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}

           
可以把任一分支的stashapply到当前分支上。





      
   
     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'
    /*}}}*/
      
      
   
修改上次commitlog 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

   
   
修改某个commitmsg和内容!!
    ---------------------------

    [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"

           
假设其ID12345

        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,就开始把i386x86-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
/*}}}*/

       
注意,有了masterjike两个分支之后,所有的修改、commitrevert工作,都在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的例子:

        //
目前有masterjike两个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 <albcamus@gmail.com>
                  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 <albcamus@gmail.com>

        //
jike分支里执行git-rebase-i表示interactive
            [arc@localhost linux-2.6]$ git-rebase -i master
            Successfully rebased and updated refs/heads/jike.

        //
已经rebasemaster分支,现在jike分支除了作为HEADlocal 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 <albcamus@gmail.com>
                  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 <albcamus@gmail.com>
/*}}}*/

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

        pull
某一个分支:
       
       
例如我想在/mnt/usb3/linux-2.6master分支上,来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 root@myhost.xyz.com:/export/home/Sources/linux-2.6 master:master

       
把同一仓库中的master分支pulljike分支:

           $ 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-pushrefspec,告诉git把我这里的master分支push<url>指定
       
的仓库(这里是~/Sources/linux-2.6)jike分支上。

       
然后,并不是说在~/Sources/linux-2.6上的jike分支已经merge/mnt/usb3/linux-2.6master分支了,还
       
需要这样:
          
           $ 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.cnSMTP server), 有时出现错误:

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

       
这说明需要安装MIME::Base64Authen::SASL两个包:

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

       
然后:

            $ git-send-email --to someone@somewhare.com --compose /
            --smtp-server 202.118.224.153 --smtp-server-port 25 /
            --smtp-user albcamus /
            /path/to/your/filename.patch

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

   
   
gmailsmtp账户发邮件
    -----------------------
        1.
安装msmtp
        2.
建立~/.msmtprc文件,chmod0600,内容为:

           //
一种配置。 已验证此~/.msmtprc文件在公司内网可用,但Linux上不行
            defaults
            tls on
            account gmail
            host smtp.gmail.com
            from albcamus@gmail.com
            auth on
            user albcamus@gmail.com
            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 albcamus@gmail.com
               auth on
               user albcamus@gmail.com
               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 <someone@xx.com> --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 Morton
git 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
             
一些漏洞修正等补丁。 (stable@kernel.org)

        -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...

 

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值