效果1: 使提交历史整洁(或者叫提前线下解决冲突)

master 分支有 c1, c2, c3, c4 四个提交,我们 c4 是最新的提交,但你现在正在一个基于 c3 的功能分支上进行开发:

                     <upstream/master,master>
              c3    /
    *----*----*----*
    c1   c2    \\   c4
                \\
                 *----*----*----* <feat1>
                 c5   c6   c7   c8

在提交到线上之前,我们希望提交历史变得整洁,具体来说,是希望提交历史像下图看起来这样:

                     <upstream/master,master>
                    /
    *----*----*----*----*----*----*----* <feat1>
    c1   c2   c3   c4   c5'  c6'  c7'  c8'

假如说提交历史看起来是这样子的话,当我们把 feat1 分支提交到线上之后,merge 过程将会是无冲突的。

要达到这样的效果,我们只需做:

git checkout master
git pull origin master
git checkout feat1
git rebase master feat1

敲完这些命令后,基于最新 master 分支的这四个新提交 c5', c6', c7', c8' 就会由 git 工具在本地自动帮你创建,并且 feat1 分支会指向 c8' 提交。

效果2: 让一个分支 A 不再是基于分支 B 而是基于分支 C

假设当前提交历史如下图所示:

c1   c2   c3   c4
*----*----*----* <dev>
      \\
       \\                    c9
        *----*----*----*----* <feat1>
        c5   c6   c7   c8    \\
                              \\
                               *----*----*----* <feat2>
                               c9   c10  c11  c12

由图可知,feat2 分支基于 feat1 分支,出于某种原因,我们希望 feat2 分支直接基于 dev 分支,也就是下图这样的效果:

                 <dev> c4
c1   c2   c3    /
*----*----*----*----*------*------*------* <feat2>
      \\             c9'    c10'   c11'   c12'
       \\
        \\                    
         *----*----*----*----* <feat1>
         c5   c6   c7   c8   c9

可以通过执行下列命令做到:

git rebase --onto dev feat1 feat2