git merge 和 git rebase两者的目的是一致的,都是用来整合多个分支的代码到一个分支中,只是所使用的方式不一样。
所有的纷争都源于认知不同
结果一样
git merge 将需要合并的分支的commit依次merge到当前分支,当前分支改变,被合并分支不变。
$ git checkout master # 切换到master branch
$ git merge develop # 合并develop到master
git rebase 将需要合并的分支的改动与当前分支的内容比较,产生一个临时的patch,然后将该patch作为一个commit放入当前分支。
$ git checkout feature
$ git rebase master # 将feature以master rebase
分支历史不一样
两者最后的结果是一致的,都是将分支的修改合并到了当前分支上,当由于方式不一样,导致分支历史不一样。
git merge 是通过依次整合commit
- 当前分支中会保留分支的commit
- 保留了历次的提交历史,但比较混乱
- revert和reset都比较麻烦(需要注意多个branch的commit)
git rebase 是通过patch整合内容
- 当前分支中形成一个提交的commit
- 提交历史干净、线性
- 方便执行revert、reset(每个commit都是一个commit或者一个branch的完成修改)
- 方便使用git bisect查问题(http://www.ruanyifeng.com/blog/2018/12/git-bisect.html)
常见使用场景
自己开发阶段:使用feature branch,建议在提pull request之前做一次git rebase
提pull request后:大家能看到你的提交了,这时候后续开发直接添加新的commit就好
pr accepted后:这时可以先git rebase master,然后git pull upstream master
最近事情多,几天没休息好,写代码有点神游物外,所有就遇到了git reset后,想再恢复的情况,只记得有这功能但不知道怎么操作,查了一番记录一下。
git reset
reset会修改HEAD的指向,但不会创建新的分支
--soft – 缓存区和工作目录都不会被改变
--mixed – 默认选项。缓存区和你指定的提交同步,但工作目录不受影响
--hard – 缓存区和工作目录都同步到你指定的提交
一旦reset HEAD~xxx,HEAD就会指向历史commit,之后的commit其实还在,但看不到了
如果在此基础上有新的提交,就真的丢弃了HEAD之后的提交
但万一不小心reset得过多了,或者手误了,如何恢复呢?
使用git relog
git relog类似于mysql的undolog,记录了本地所有分支的git操作记录,
git relog查看过往的reset命令
可以看到reset之前的提交commit log
如果要恢复,只需要再次git reset 4665343c就可以了