一、git merge 的流程
如下,首先在一个目录中初始化仓库,然后在master分支创建master_1和master_2两个文件,并两次提交,此时拉出dev分支,然后在master分支继续创建master_3和master_4,然后在dev分支创建dev_5和dev_6,每个文件分别提交,此时在dev分支中使用git merge master,把master分支的代码合入到dev分支,整个过程如下,最后可以看出使用merge合并分支,会在merge的时候,将master分支再在此期间的提交合并到当前分支的默认,然后再默认在增加一次merge的提交,在日常工作中,通常此时会继续将dev的分支merge到master分支,从而完成一次向主分支的提交,此时master分支合dev分支的提交顺序是完全一样了
hitre@iscas-redrose2100 MINGW64 /d/src/git_demo
$ git init
Initialized empty Git repository in D:/src/git_demo/.git/
hitre@iscas-redrose2100 MINGW64 /d/src/git_demo (master)
$ touch master_1
hitre@iscas-redrose2100 MINGW64 /d/src/git_demo (master)
$ git add .
hitre@iscas-redrose2100 MINGW64 /d/src/git_demo (master)
$ git commit -m "add master_1"
[master (root-commit) 9b881da] add master_1
1 file changed, 0 insertions(+), 0 deletions(-)
create mode 100644 master_1
hitre@iscas-redrose2100 MINGW64 /d/src/git_demo (master)
$ touch master_2
hitre@iscas-redrose2100 MINGW64 /d/src/git_demo (master)
$ git add .
hitre@iscas-redrose2100 MINGW64 /d/src/git_demo (master)
$ git commit -m "add master_2"
[master aeacaa2] add master_2
1 file changed, 0 insertions(+), 0 deletions(-)
create mode 100644 master_2
hitre@iscas-redrose2100 MINGW64 /d/src/git_demo (master)
$ git checkout -b dev
Switched to a new branch 'dev'
hitre@iscas-redrose2100 MINGW64 /d/src/git_demo (dev)
$ git checkout master
Switched to branch 'master'
hitre@iscas-redrose2100 MINGW64 /d/src/git_demo (master)
$ touch master_3
hitre@iscas-redrose2100 MINGW64 /d/src/git_demo (master)
$ git add .
hitre@iscas-redrose2100 MINGW64 /d/src/git_demo (master)
$ git commit -m "add master_3"
[master 11ec7c0] add master_3
1 file changed, 0 insertions(+), 0 deletions(-)
create mode 100644 master_3
hitre@iscas-redrose2100 MINGW64 /d/src/git_demo (master)
$ touch master_4
hitre@iscas-redrose2100 MINGW64 /d/src/git_demo (master)
$ git add .
hitre@iscas-redrose2100 MINGW64 /d/src/git_demo (master)
$ git commit -m "add master_4"
[master 62f1f81] add master_4
1 file changed, 0 insertions(+), 0 deletions(-)
create mode 100644 master_4
hitre@iscas-redrose2100 MINGW64 /d/src/git_demo (master)
$ git checkout dev
Switched to branch 'dev'
hitre@iscas-redrose2100 MINGW64 /d/src/git_demo (dev)
$ touch dev_5
hitre@iscas-redrose2100 MINGW64 /d/src/git_demo (dev)
$ git add .
hitre@iscas-redrose2100 MINGW64 /d/src/git_demo (dev)
$ git commit -m "add dev_5"
[dev 5610f83] add dev_5
1 file changed, 0 insertions(+), 0 deletions(-)
create mode 100644 dev_5
hitre@iscas-redrose2100 MINGW64 /d/src/git_demo (dev)
$ touch dev_6
hitre@iscas-redrose2100 MINGW64 /d/src/git_demo (dev)
$ git add .
hitre@iscas-redrose2100 MINGW64 /d/src/git_demo (dev)
$ git commit -m "add dev_6"
[dev d961705] add dev_6
1 file changed, 0 insertions(+), 0 deletions(-)
create mode 100644 dev_6
hitre@iscas-redrose2100 MINGW64 /d/src/git_demo (dev)
$ git log --graph --pretty=oneline --abbrev-commit
* d961705 (HEAD -> dev) add dev_6
* 5610f83 add dev_5
* aeacaa2 add master_2
* 9b881da add master_1
hitre@iscas-redrose2100 MINGW64 /d/src/git_demo (dev)
$ git merge master
Merge made by the 'ort' strategy.
master_3 | 0
master_4 | 0
2 files changed, 0 insertions(+), 0 deletions(-)
create mode 100644 master_3
create mode 100644 master_4
hitre@iscas-redrose2100 MINGW64 /d/src/git_demo (dev)
$ git log --graph --pretty=oneline --abbrev-commit
* 282d544 (HEAD -> dev) Merge branch 'master' into dev
|\
| * 62f1f81 (master) add master_4
| * 11ec7c0 add master_3
* | d961705 add dev_6
* | 5610f83 add dev_5
|/
* aeacaa2 add master_2
* 9b881da add master_1
hitre@iscas-redrose2100 MINGW64 /d/src/git_demo (dev)
$ git checkout master
Switched to branch 'master'
hitre@iscas-redrose2100 MINGW64 /d/src/git_demo (master)
$ git log --graph --pretty=oneline --abbrev-commit
* 62f1f81 (HEAD -> master) add master_4
* 11ec7c0 add master_3
* aeacaa2 add master_2
* 9b881da add master_1
hitre@iscas-redrose2100 MINGW64 /d/src/git_demo (master)
$ git merge dev
Updating 62f1f81..282d544
Fast-forward
dev_5 | 0
dev_6 | 0
2 files changed, 0 insertions(+), 0 deletions(-)
create mode 100644 dev_5
create mode 100644 dev_6
hitre@iscas-redrose2100 MINGW64 /d/src/git_demo (master)
$ git log --graph --pretty=oneline --abbrev-commit
* 282d544 (HEAD -> master, dev) Merge branch 'master' into dev
|\
| * 62f1f81 add master_4
| * 11ec7c0 add master_3
* | d961705 add dev_6
* | 5610f83 add dev_5
|/
* aeacaa2 add master_2
* 9b881da add master_1
hitre@iscas-redrose2100 MINGW64 /d/src/git_demo (master)
$
二、git rebase的流程
可以使用git reset 先将上述回退到merge之前,比如在master分支
$ git log --graph --pretty=oneline --abbrev-commit
* 282d544 (HEAD -> master, dev) Merge branch 'master' into dev
|\
| * 62f1f81 add master_4
| * 11ec7c0 add master_3
* | d961705 add dev_6
* | 5610f83 add dev_5
|/
* aeacaa2 add master_2
* 9b881da add master_1
hitre@iscas-redrose2100 MINGW64 /d/src/git_demo (master)
$ git reset --hard 62f1f81
HEAD is now at 62f1f81 add master_4
hitre@iscas-redrose2100 MINGW64 /d/src/git_demo (master)
$ git log --graph --pretty=oneline --abbrev-commit
* 62f1f81 (HEAD -> master) add master_4
* 11ec7c0 add master_3
* aeacaa2 add master_2
* 9b881da add master_1
在dev分支
$ git checkout dev
Switched to branch 'dev'
hitre@iscas-redrose2100 MINGW64 /d/src/git_demo (dev)
$ git log --graph --pretty=oneline --abbrev-commit
* 282d544 (HEAD -> dev) Merge branch 'master' into dev
|\
| * 62f1f81 (master) add master_4
| * 11ec7c0 add master_3
* | d961705 add dev_6
* | 5610f83 add dev_5
|/
* aeacaa2 add master_2
* 9b881da add master_1
hitre@iscas-redrose2100 MINGW64 /d/src/git_demo (dev)
$ git reset d961705 --hard
HEAD is now at d961705 add dev_6
hitre@iscas-redrose2100 MINGW64 /d/src/git_demo (dev)
$ git log --graph --pretty=oneline --abbrev-commit
* d961705 (HEAD -> dev) add dev_6
* 5610f83 add dev_5
* aeacaa2 add master_2
* 9b881da add master_1
此时在dev分支执行rebase命令,git rebase 是首先将master分支的合并进来,然后将本分支加到master分支提交记录的后面,此外可以看到此时提交记录就简洁的多了,则就是rebase和merge的主要优势
$ git rebase master
Successfully rebased and updated refs/heads/dev.
hitre@iscas-redrose2100 MINGW64 /d/src/git_demo (dev)
$ git log --graph --pretty=oneline --abbrev-commit
* 3e4ae24 (HEAD -> dev) add dev_6
* 9ac0d04 add dev_5
* 62f1f81 (master) add master_4
* 11ec7c0 add master_3
* aeacaa2 add master_2
* 9b881da add master_1
此时切回到master分支需要使用merge
hitre@iscas-redrose2100 MINGW64 /d/src/git_demo (dev)
$ git checkout master
Switched to branch 'master'
hitre@iscas-redrose2100 MINGW64 /d/src/git_demo (master)
$ git merge dev
Updating 62f1f81..3e4ae24
Fast-forward
dev_5 | 0
dev_6 | 0
2 files changed, 0 insertions(+), 0 deletions(-)
create mode 100644 dev_5
create mode 100644 dev_6
hitre@iscas-redrose2100 MINGW64 /d/src/git_demo (master)
$ git log --graph --pretty=oneline --abbrev-commit
* 3e4ae24 (HEAD -> master, dev) add dev_6
* 9ac0d04 add dev_5
* 62f1f81 add master_4
* 11ec7c0 add master_3
* aeacaa2 add master_2
* 9b881da add master_1
三、git rebase 和 git merge区别总结
(1)git meerge 是将当前分支的提交放在merge分支的前面,而git rebase是将当前分支的提交放到reabse分支的后面
(2)git merge 会在最后增加一个merge的提交记录,而git rebase 不会额外增加提交记录
(3)git merge 合并之后提交记录是非常复杂的,而使用git rebase合并之后提交记录是线性的
(4)使用git merge 合并之后就不能再回退自己的提交代码了,如果回退则会降merge的内容一同回退了,而git rebase在合并之后可以继续回退自己的提交,而从rebase合进来的代码不受影响
(4)很明显,dev开发分支适合使用git rebase,而master主分支则非常适合git merge
(5)master主分支如果使用git rebase的后果是改变了提交历史,比如多人合作时后使用rebase的必须将前面使用过rebase的代码合到自己的前面,导致跟拉出来分支的时候提交历史不一样了,从而会带来各种比较痛苦的提交体验