概念

git rebase也是一种合并分支的方法,它类似于git merge。可以这样简单理解:git rebase可以将具有共同祖先的其中一条分支上的提交依次应用到另外一条分支上,并将该分支上原来的提交追加到新的提交之后,从提交轨迹上来看就好像发生在一条直线上。(估计看完这句话有点蒙圈,那就接着往下看)

深入理解合并操作

当Git执行合并时,实际上会查找3个提交:

(1)共同的原始提交

(2)+(3)两个分支的最终点

快进和合并提交

如果一个分支上没有新的改动提交发生,那么他之前的最后一次提交仍然是那个共同的原始提交。此时如果执行整合操作,Git仅仅需要添加所有那些在另外一个分支上新的提交就可以了。这种最简单的整合操作称为‘快进(fast-forward)’.之后两个分支拥有完全相同的历史。

before: 

C1(分支A上的最后一次提交)..........................>>(分支A)
  \
    \
      C2.....C3(分支B上的最后一次提交).............>>(分支B)

after:

C1......C2.....C3(分支A和分支B)

但实际情况中,两个分支都会有自己不同的发展轨迹

C1...........C3(分支A上的最后一次提交)..............>>(分支A)
  \
    \
      C2.....C4(分支B上的最后一次提交).............>>(分支B)

当我们merge的时候,Git会创建一个新的提交来包含他们之间的差异。假如我们切换至branch-A,然后merge

$ git checkout branch-A
$ git merge branch-B

C1...........C3(分支A上的最后一次提交).........C5(合并提交).....>>(分支A)
  \                                         /
    \                                     /
      C2.................C4(分支B上的最后一次提交)............>>(分支B)

Rebase整合

回看上面的示例,分支出现了分叉但有人不喜欢这种轨迹,他希望项目拥有一个单一的历史轨迹,类似于一条直线。

C1......C2......C4(分支B)....C3(分支A).....>>

下面我们用Rebase合并分支B到分支A

C1...............C3.............>>(分支A)
  \
   \
    C2.............C4............>>(分支B)

我们先切换至分支A,然后使用以下命令

$ git rebase branch-B

首先,git会撤销所有分支A上的那些与分支B共同提交后发生的提交,你可以想象git把这些撤销的提交暂时存储在了另外一个地方。

Step【1】
        (C3)
C1.................................>>(分支A)
 \
  \
   C2.............C4...............>>(分支B)

接下来整合那些在分支B上还未整合的提交到分支A中。在这个时间点,这两个分支看起来是一模一样的。

Step【2】
        (C3)
C1....C2......C4.............>>(分支A)
 \
  \
   C2.........C4.............>>(分支B)

最后,那些在分支A的新的提交(也就是第一步中自动撤销的那些提交,如C3)会被重新应用的当前分支(A)上,但是在不同的位置上。

Step【3】
C1....C2......C4(分支B)........C3(分支A).....

此时整个项目开发轨迹就像发生在一条直线上(而且你会发现所有的分支都位于一条直线)。相对于合并提交,rebase包括了所有的组合变化,最原始的提交结构会被保留下来。 以下是我本地通过SoureThree看到的merge和rebase的分支图对比:

Rebase使用注意

一定要记住Rebase会改写历史记录

当Rebase后,分支A上的C3提交其实已经不是原来的那个C3了,他们只不过提交的内容相同而已。一个提交仅仅包括很少的属性,比如作者,日期,变动和谁是它的父提交。如果改变其中任何一个信息,就必须创建一个全新的提交。当然,新的提交也会拥有一个新的 hash ID 。 建议是:你应该只使用 rebase 来清理你的本地工作,千万不要尝试着对那些已经被发布的提交进行这个操作。

参考: https://www.git-tower.com/learn/git/ebook/cn/command-line/advanced-topics/rebase

  1. 寻寻觅觅 -- Christine Welch
  2. Just the Way You Are -- Bruno Mars
  3. Despacito(Remix) -- Luis Fonsi;Daddy Yankee;Justin Bieber
  4. 没有什么不同 -- 曲婉婷
  5. 故乡--许巍
  6. Jar Of Love -- 曲婉婷
  7. I Really Like You -- Carly Rae Jepsen