您的位置:首页 > 其它

git rebase 介绍

2015-12-18 15:41 351 查看
git rebase
是对commit history的改写。当你要改写的commit history还没有被提交到远程repo的时候,也就是说,还没有与他人共享之前,commit history是你私人所有的,那么想怎么改写都可以。

而一旦被提交到远程后,这时如果再改写history,那么势必和他人的history长的就不一样了。
git push
的时候,git会比较commit history,如果不一致,commit动作会被拒绝,唯一的办法就是带上
-f
参数,强制要求commit,这时git会以committer的history覆写远程repo,从而完成代码的提交。虽然代码提交上去了,但是这样可能会造成别人工作成果的丢失,所以使用
-f
参数要慎重。

要解决这个问题,就要从提交流程上做规范。

举个正确流程的栗子:

假设楼主的team中有两个developer:tom和jerry,他们共同使用一个远程repo,并各自clone到自己的机器上,为了简化描述,这里假设只有一个branch:
master


这时tom机器的repo有两个branch
master
,
origin/master


而jerry的机器上也是有两个branch
master
,
origin/master


均如下图所示



tom和jerry分别各自开发自己的新feature,不断有新的commit提交到他们各自私有的commit history中,所以他们的master指针不断的向前推移,分别指向不同的commit。而又由于他们都没有
git fetch
git push
,所以他们的
origin/master
都维持不变。

jerry的repo如下



tom的repo如下,注意
T1
和上图的
J1
,分别是两个不同的commit



这时Tom首先把他的commit提交的远程repo中,那么他本机
origin/master
指针则会前进,和
master
指针保持一致,如下



远程repo如下



现在jerry也想把他的commit提交到远程repo上去,运行
git push
,毫无意外的失败了,所以他
git fetch
了一下,把远程repo,也就是之前tom提交的
T1
给拉到了他本机repo中,如下



commit history出现了分叉,要想把tom之前提交的内容包含到自己的工作中来,有一个方法就是
git merge
,它会自动生成一个commit,既包含tom的提交,也包含jerry的提交,这样就把两个分叉的commit重新又合并在一起。但是这个自动生成的commit会有两个parent,review代码的时候必须要比较两次,很不方便。

jerry为了保证commit history的线性,决定采用另外一种方法,就是
git rebase
。jerry的提交
J1
这时还没有被提交到远程repo上去,也就是他完全私有的一个commit,所以使用
git rebase
改写
J1
的history完全没有问题,改写之后,如下



注意
J1
被改写到
T1
后面了,变成了
J1`


git push
后,本机repo



而远程repo



异常的轻松,一条直线,没有
-f


所以,在不用
-f
的前提下,想维持树的整洁,方法就是:在
git push
之前,先
git fetch
,再
git rebase


git fetch origin master
git rebase origin/master
git push

强烈推荐阅读

a successful git branching model

Git-分支-分支的衍合
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: