使用rebase合并commit

日常开发中,使用rebase之后再进行merge操作会让git分支的流程更加清晰。

  1. A---B---C dev
  2. /
  3. D---E---F---G master

在dev分支执行命令

  1. git rebase master

结果

  1. A'--B'--C' dev
  2. /
  3. D---E---F---G master

合并到master上的原来的A,B,C会变成新的A’,B‘,C’。

操作阶段,在commit之后,在push 之前。 commit多次之后,执行rebase master。 合并多次提交记录,然后再进行pr合并

压缩x个commit,只保留一个commit

  1. git rebase -i HEAD~x

git log查看分支
image.png

进行rebase操作

执行git rebase -i HEAD~2,然后会自动进入vi界面。
image.png

把pick改成s即可合并

只保留一个pick,其余全改成s(quash)。
image.png
修改完成之后保存退出,会自动进入确认页面,再次保存退出即可.
image.png
提交推送到远程之后再去git上提交merge request。这个在master分支上就会保持一条清晰的流程记录

解决冲突

rebase过程出现冲突的话,解决冲突之后不要用git commit,而是使用git rebase —continue

停止rebase

git rebase -abort
参考链接:https://git-scm.com/docs/git-rebase

rebase简介

rebase是一个非常强大的操作,可以实现一些神奇的功能,但是强大也意味着有隐患,因为如果使用得不好可能给团队的代码造成非常大的问题,成为团队当中被无情指责的背锅侠。所以我们在使用之前一定要先了解清楚原理,之后再小心谨慎地使用,否则很有可能会产生问题。

首先说说rebase的功能,rebase的功能说白了可以提取我们在A分支上的改动,然后应用在B分支的代码上,完成类似于补丁的功能。从learngitbranching.js.org网站上截取了一些图,会清晰一些
image.png
这张图非常经典,是很多场景下的常态。C1是线上的版本,在C1的代码上线了之后发现了一个bug,于是我们checkout一个叫做bugFix的分支。与此同时还有新的功能在开发,新的功能提交到了master之后形成了节点C2。这个时候我们在bugFix分支当然可以merge master这没有什么问题,但是也可以rebase master,rebase之后整棵git树会变成这样:
image.png

这个结果就好像是我们先到了C2然后checkout出了bugFix分支,然后在bugFix分支上将之前写过的代码重新写了一遍。这样的操作就是变基,当我们rebase了之后再提交合并请求我们的合并记录里面会非常干净,没有多余merge的信息。对于多人协同开发的场景非常有帮助。

rebase实战1

使用rebase将多个分支合并为一个分支。

  1. * 6ed3c75 (HEAD -> test) test2
  2. * ddc07d4 test1
  3. | * 94f451d (dev) dev2
  4. | * 3036534 dev1
  5. |/
  6. * 5385f77 (master) init

创建3个分支,master默认的主分支,创建dev分支,并且进行2次提交。创建出test分支,并进行2次提交;
rebase合并提交记录 - 图7

  • 接下来要对test分支进行变基,现在test的根基是从master的init提交记录开始向后发展,我们的目的是,将test分支的根基变为从dev分支的dev2提交记录开始。这样将test分支合并到dev分支后,分支的流程会非常清晰。
  • 对test分支进行变基,需要先切换到test分支
  • 在test分支执行git rebase dev 命令
  • 执行命令的意思是,test分支变更基准点,用dev分支的dev2提交作为新的基准点

    变基分支,解决冲突

    将test分支上的提交test1应用到新的基准点dev2尾部,出现了合并冲突。
    image.png
    查看状态发现test分支变基过程中新的基准点,正是dev2的提交记录。
    image.png
    处理冲突有3种方式:如上图所示
  1. git rebase —continue 解决冲突,继续变基
  2. git rebase —skip 丢弃test分支的提交记录,如果一直使用skip操作,变基完成后,则test1和test2的提交记录被丢弃,test分支和dev分支完全相同
  3. git rebase —abort 表示终止rebase操作,恢复到之前。

    操作一:解决冲突

    解决冲突,都使用传入的值。手动合并提交,继续变基。完成后就如下图。
    image.png
    此时的分支状态
    rebase合并提交记录 - 图11

    操作二:skip表示丢弃当前test分支的提交记录。

    操作完成后,分支状态如下:
    rebase合并提交记录 - 图12
    test分支指向了dev分支的提交记录。 ```git
  • 94f451d (HEAD -> dev, test) dev2
  • 3036534 dev1
  • 5385f77 (master) init ```

    操作三:abort,表示终止rebase操作,恢复到操作之前。

    更新dev分支,再进行变基合并

    在执行完操作一后,已经完成了test的变基为dev分支。
    接下来更新dev提交记录,增加2次新的提交dev3和dev4
    image.png
    分支状态如下:
    rebase合并提交记录 - 图14

切换到dev分支,再次执行 git rebase dev,变基test分支到dev

  1. * 8a15044 (dev) dev4
  2. * ea979f8 dev3
  3. | * 587ae1d (HEAD -> test) test2
  4. | * 9d792da test1
  5. |/
  6. * 94f451d dev2
  7. * 3036534 dev1
  8. * 5385f77 (master) init

image.png
执行rebase之后

  1. * 4ca8bde (HEAD -> test) test2
  2. * 118688d test1
  3. * 8a15044 (dev) dev4
  4. * ea979f8 dev3
  5. * 94f451d dev2
  6. * 3036534 dev1
  7. * 5385f77 (master) init

image.png
此时的分支状态
rebase合并提交记录 - 图17

实战2

对2个分支进行变基时,2个分支生成提交记录并不一定要在目标分支上应用。
如下图,

  • 创建一个主分支master,提交c1和c2,
  • 然后从c2切出一个server分支来,增加c3和c4,c10提交记录。
  • 从c3提交记录切出来一个client分支,并提交c8和c9记录

rebase合并提交记录 - 图18

  1. * 4ecb8e9 (HEAD -> master) c6
  2. * 3aa47c1 c5
  3. | * 0654c5e (server) c10
  4. | * 5ec5b18 c4
  5. | | * 39bcfd9 (client) c9
  6. | | * 8830b89 c8
  7. | |/
  8. | * 8e9d273 c3
  9. |/
  10. * 2ce4be6 c2
  11. * 1ccced1 c1

合并分支client

第一次想合并client分支,但是并不能合并server分支,server还正在开发中。
这时就可以使用git rebase命令的 --onto 选项,选中在client分支里,但是不在server分支里的提交记录(即c8和c9),将他们在master分支上重放。
在master分支执行以下命令
git rebase --onto master server client
这条命令的意思:取出client分支,找出从server分支分叉的提交,然后把这些提交记录在master分支上重放一遍,让client分支看起来像直接基于master分支的修改一样。
执行过命令之后,分支状态如下:
rebase合并提交记录 - 图19

  1. * b1432fc (HEAD -> client) c9
  2. * 3a69cbb c8
  3. * 4ecb8e9 (master) c6
  4. * 3aa47c1 c5
  5. | * 0654c5e (server) c10
  6. | * 5ec5b18 c4
  7. | * 8e9d273 c3
  8. |/
  9. * 2ce4be6 c2
  10. * 1ccced1 c1

现在就可以快速合并master分支。

  1. # 切换到master分支
  2. git checkout master
  3. # 把client分支merge到master分支
  4. git merge client

操作完成后,分支状态如下
rebase合并提交记录 - 图20

  1. * b1432fc (HEAD -> master, client) c9
  2. * 3a69cbb c8
  3. * 4ecb8e9 c6
  4. * 3aa47c1 c5
  5. | * 0654c5e (server) c10
  6. | * 5ec5b18 c4
  7. | * 8e9d273 c3
  8. |/
  9. * 2ce4be6 c2
  10. * 1ccced1 c1

合并分支server

server开发完成,现在决定合并server分支。
在master分支中,直接使用git rebase master server命令;可以直接将server分支变基到master分支。

  1. # 在master分支下
  2. git rebase master server

这样操作省去了先切换到server分支,然后在对server进行变基的多个命令步骤。
之后server的代码就加到了master分支的后面。分支状态如下图
rebase合并提交记录 - 图21

  1. * 861ea8a (HEAD -> server) c10
  2. * b2733e7 c4
  3. * 52b7336 c3
  4. * b1432fc (master, client) c9
  5. * 3a69cbb c8
  6. * 4ecb8e9 c6
  7. * 3aa47c1 c5
  8. * 2ce4be6 c2
  9. * 1ccced1 c1

之后就可以把server分支快速合并到master分支

  1. git checkout master
  2. git checkout server
  1. * 861ea8a (HEAD -> master, server) c10
  2. * b2733e7 c4
  3. * 52b7336 c3
  4. * b1432fc (client) c9
  5. * 3a69cbb c8
  6. * 4ecb8e9 c6
  7. * 3aa47c1 c5
  8. * 2ce4be6 c2
  9. * 1ccced1 c1

合并过client和server分支,就可以将它们删除

  1. git branch -d client
  2. git branch -d server