Blog Of Leung

personal blog & work notes

View project onGitHub
 

git的随笔

现在越来越发现自己的笔记太零散了,想整理简直是对自己耐心的挑战......

杂项

  • 在内部服务器中,如果需要知道在git服务器上存在哪些项目,可以使用ssh命令,该命令会尝试登录git服务器,服务器会返回一个git仓库的列表,这样就可以获取到所有的项目名称.

    $ ssh git@192.168.xxx.xxx

  • 在某个分支的基础上新建一个分支,如在master分支的基础上新建dev分支,并自动切换到新分支上工作,可以使用-b参数.

    $ git checkout -b dev master

  • 把dev合并到master分支,可以先checkout到master分支中,然后使用merge命令及参数--no-ff,如果不使用no-ff参数,git会执行快进式合并,会直接将master分支指向dev分支,加上参数之后则会生成一个新的节点.

    $ git checkout master $ git merge --no-ff dev

  • 删除分支,使用branch -d命令,但是如果分支没有被完全合并到主分支,git是会拒绝删除的,如果经过检查确认某个分支中的代码不被需要,可以使用-D参数,强制删除.

    $ git branch -d xxx

  • 查看代码的最后修改者,blame命令可以标注出一个指定文件里每一行的最后修改者,和最后修改时间,可以很快找出问题代码的提交者是谁.

    $ git blame filename

  • diff命令可以看出两次提交的差异,但是包含了具体内容,篇幅太长,可以使用name-only参数,仅显示有差异的文件名,不显示差异内容.

    $ git diff --name-only commit1 commit2

  • 修改提交信息,amend参数可以修改最后一次提交的信息,假如某次本地提交发现有遗漏或者修改错误,可以直接修改源文件,然后继续执行add命令,最后使用amend参数,这样就不会产生新的提交,而是在最后一次提交中修改.

    $ git commit --amend

  • git cherry-pick命令可以单独从某个远程分支上拉取某次提交的内容到本地分支上,而不需要使用补丁或者全部拉取的方式来获取代码

    分支的合并与冲突解决

分支的合并,使用的命令就是merge命令,上面已经有写到. 很多情况下合并会产生冲突,所谓的冲突可以理解为:分支1想把分支2中的修改合并进来,分支1中对某些文件的某些行做了修改,而dev2中也有人对那些文件的同一行做了修改,所以合并的时候git无法自动取舍.这时候就需要人工参与了.

git会给出冲突的文件列表,打开发生冲突的文件之后,会看到git打上的冲突标记,如下:

aaaa
<<<<<<< HEAD
bbbb
=======
bbbc
>>>>>>> 4u8905f6789e63333a6c02d5678183b5ff330df4

在这次冲突中,代码aaaa的下一行,在本地分支中被修改为bbbb,但是在即将合并进来的dev2中却有人改成了bbbc,这时候git是无法替你选择的,所以需要手动修改,进行人工的判断和取舍.假如dev2分支上的修改更合理,那么就应该只保留dev2上的修改;假如这两个修改其实是属于不同的功能,且互相不产生影响,只是凑巧改到了同一行,那么就应该同时保留;修改完毕的同时,git添加的那些标志也必须要清除干净.like this:

aaaa
bbbc

生成补丁&打补丁

git可以用两种方法生成补丁,最灵活的方法应该是diff命令,git diff对比的对象,可以是当前修改的文件与服务器上的同一文件之间的差异,可以是git提交历史里的两次提交记录之间的差异,可以是本地分支与服务器分支之间的差异,可以是今天与昨天的差异,等等. 这绝对可以应付大多数的需求了.

$ git diff A B
# A和B就是git diff对比的对象(对比本地文件与服务器上文件的差异不需要输入B对象),生成的补丁一般是类似下面这样子

index 6c8f795..d855c54 100644
--- a/Makefile
+++ b/Makefile
@@ -1,3 +1,4 @@
 ### DO NOT EDIT THIS FILE ###
 include build/core/main.mk
 + just make a test
 ### DO NOT EDIT THIS FILE ###

这个补丁显示的信息是,我在Makefile这个文件的第3跟第4行之间写入了一句话"just make a test". 对于git diff生成的补丁,可以使用git apply命令进行打补丁工作,同样,补丁与合并其实本质上没有区别,因此打补丁也存在冲突的情况,git apply命令如果出现冲突,也会返回一个冲突的文件列表,这时候只能手动对比修改了.

第二种生成补丁的方法,相对git diff来说没那么灵活,但是某种程度上更强大. 它是可以生成git专用的补丁形式,使用的是git format-patch命令. 这个命令可以直接根据两个分支之间的差异,以一次提交为单位,生成一系列的补丁,并自动编号.虽然git diff也可以根据两个分支来产生补丁,但是只能重定向到单个补丁文件,对于修改数量比较多的情况就显得不太合适,另外format-patch比diff更强大的地方是,它还可以把git的commit信息原封不动地保留下来,在打完补丁后也不会丢失.最后format-patch生成的补丁是带邮件地址的,你可以直接把附件以邮件形式发送出去,为某个项目贡献代码.它生成的补丁一般是类似下面这样子

$ git format-patch dev
# 0001-make-a-test.patch 这个就是生成的补丁的其中一个,补丁形式如下:

From d533109142504bedd0799454b63f10a5ead460c4 Mon Sep 17 00:00:00 2001
From: leung <leung@leung-pc.(none)>
Date: Thu, 26 Dec 2013 00:47:02 +0800
Subject: [PATCH] make a test

---
 Makefile |    1 + 
  1 file changed, 1 insertion(+)

diff --git a/Makefile b/Makefile
index 6c8f795..d855c54 100644
--- a/Makefile
+++ b/Makefile
@@ -1,3 +1,4 @@
 ### DO NOT EDIT THIS FILE ### 
 include build/core/main.mk
 + just make a test
  ### DO NOT EDIT THIS FILE ### 
 -- 
 1.7.9.5

对于用format-patch生成的补丁,可以使用git am 命令来打补丁,git会按照编号依次打上补丁.

$ git am *.patch

当然,比较理想的状态是一次通过,但是通常情况是有冲突的,出现冲突之后am命令可能并不会返回太多的冲突信息,这时候先手动apply;

$ git apply --reject xxxx.patch

apply命令会返回冲突的具体信息,可以看到冲突发生的文件,具体在什么行数,文件是否存在等等,同时它还会生成一个xxxx.rej文件,在冲突文件所在的同一目录下,里面是发生冲突的代码块,利用这个rej文件手动修改冲突文件,修改完毕之后,使用git status查看本次apply修改过的文件,然后执行 git add 添加这些文件

$ git add xxx

最后,使用resolved告诉git服务器,本次合并已经完成,它会自动提交到服务器上,无需再push

$ git am --resolved

如果中间有出现失误或者其他问题,都可以通过git reset --hard命令恢复代码

如果使用git am命令提示类似"/.git/rebase-apply still exists but mbox given"错误,可以执行git am --abort将git恢复

$ git am --abort

如果合并的patch中存在当前分支没有的文件,可以手动拷贝文件过来,最后add上就好了

Author:leung

05 Dec 2013

← Home

comments powered by Disqus