git merge的用法

git一般有以下三种 merge 方式:

  • fast-forward
  • no fast forward
  • squash

git merge 默认使用的 fast-forward 的合并方式。下面图片是三种合并方式的区别:

fast-forward 

fast-forward方式就是当条件允许的时候,git直接把HEAD指针指向合并分支的头,完成合并。属于“快进方式”,不过这种情况如果删除分支,则会丢失分支信息,因为在这个过程中没有创建commit。

--no-ff

指的是强行关闭fast-forward方式,会创建一个新的commit。

squash

用来把一些不必要commit进行压缩,比如说,你的feature在开发的时候写的commit很乱,那么我们合并的时候不希望把这些历史commit带过来,于是使用--squash进行合并,此时文件已经同合并后一样了,但不移动HEAD,不提交。需要进行一次额外的commit来“总结”一下,然后完成最终的合并。

实战详解

在master上拉一条dev分支,不做任何修改,dev分支的git log如下,与master一样,只有一次commit信息。

$ git log
commit da487ec6f73886a52f4dc3ebc6c7c77b63fda4b7 (HEAD -> dev, master)
Author: crazyboy 
Date:   Tue Oct 6 22:32:57 2020 +0800

    初始化

在dev分支执行两次commit,此时dev分支的git log如下:

$ git log
commit e695f8684772e79b5146f55f2203f9e3b4750823 (HEAD -> dev)
Author: crazyboy 
Date:   Tue Oct 6 22:36:38 2020 +0800

    commit 2

commit 9bdfa619268a00898b472f40ef519d9cf0212acd
Author: crazyboy
Date:   Tue Oct 6 22:36:05 2020 +0800

    commit 1

commit da487ec6f73886a52f4dc3ebc6c7c77b63fda4b7 (master)
Author: crazyboy 
Date:   Tue Oct 6 22:32:57 2020 +0800

    初始化

切换回master,执行git merge dev,可以看到提示了Fast-forward

$ git merge dev
Updating da487ec..e695f86
Fast-forward
 Hello.java | 2 ++
 1 file changed, 2 insertions(+)

此时,master分支git log如下,可以看到,master的HEAD指针与dev的HEAD指针,指向的是同一个commit,说明git merge --ff仅仅是移动了master的HEAD指针,并且可以看到dev的提交历史

$ git log
commit e695f8684772e79b5146f55f2203f9e3b4750823 (HEAD -> master, dev)
Author: crazyboy <15813514053@163.com>
Date:   Tue Oct 6 22:36:38 2020 +0800

    commit 2

commit 9bdfa619268a00898b472f40ef519d9cf0212acd
Author: crazyboy <15813514053@163.com>
Date:   Tue Oct 6 22:36:05 2020 +0800

    commit 1

commit da487ec6f73886a52f4dc3ebc6c7c77b63fda4b7
Author: crazyboy <15813514053@163.com>
Date:   Tue Oct 6 22:32:57 2020 +0800

    初始化

在master执行git reset HEAD^^ --hard,回退到master最初的版本。

注: 需要回退两次,才能回到最初的版本。

$ git log
commit da487ec6f73886a52f4dc3ebc6c7c77b63fda4b7 (HEAD -> master)
Author: crazyboy <15813514053@163.com>
Date:   Tue Oct 6 22:32:57 2020 +0800

    初始化

在master分支执行git merge --no-ff dev,会要求输入commit备注,git log如下,可以看到,除了dev的两次commit,还有一次merge的commit信息

$ git log
commit b5444f26db3fdcd44041828f850ee25897c69555 (HEAD -> master)
Merge: da487ec e695f86
Author: crazyboy <15813514053@163.com>
Date:   Tue Oct 6 23:05:47 2020 +0800

    Merge branch 'dev'

commit e695f8684772e79b5146f55f2203f9e3b4750823 (dev)
Author: crazyboy <15813514053@163.com>
Date:   Tue Oct 6 22:36:38 2020 +0800

    commit 2

commit 9bdfa619268a00898b472f40ef519d9cf0212acd
Author: crazyboy <15813514053@163.com>
Date:   Tue Oct 6 22:36:05 2020 +0800

    commit 1

commit da487ec6f73886a52f4dc3ebc6c7c77b63fda4b7
Author: crazyboy <15813514053@163.com>
Date:   Tue Oct 6 22:32:57 2020 +0800

    初始化

执行git reset HEAD^ --hard,git log如下

$ git log
commit da487ec6f73886a52f4dc3ebc6c7c77b63fda4b7 (HEAD -> master)
Author: crazyboy <15813514053@163.com>
Date:   Tue Oct 6 22:32:57 2020 +0800

    初始化

执行

$ git merge --squash dev
$ git commit -m "message here"

看不到dev的两次commit信息,也没有merge的commit信息,master的HEAD指针并没有变化,但是确实把dev的内容合并过来。

--squash选项的含义是:本地文件内容与不使用该选项的合并结果相同,但是不提交、不移动HEAD,因此需要一条额外的commit命令。其效果相当于将dev分支上的多个commit合并成一个,放在当前分支上,原来的commit历史则没有拿过来

判断是否使用--squash选项最根本的标准是,待合并分支上的历史是否有意义。

如果在开发分支上提交非常随意,那么一定要使用--squash选项,版本历史记录的应该是代码的发展,而不是开发者在编码时的活动。

只有在开发分支上每个commit都有其独自存在的意义,并且能够编译通过的情况下(能够通过测试就更完美了),才应该选择缺省的合并方式来保留commit历史。

posted @ 2024-10-20 00:13  李小菜丶  阅读(336)  评论(0)    收藏  举报