使用rebase合并commit
日常开发中,使用rebase之后再进行merge操作会让git分支的流程更加清晰。
A---B---C dev
/
D---E---F---G master
在dev分支执行命令
git rebase master
结果
A'--B'--C' dev
/
D---E---F---G master
合并到master上的原来的A,B,C会变成新的A’,B‘,C’。
操作阶段,在commit之后,在push 之前。 commit多次之后,执行rebase master。 合并多次提交记录,然后再进行pr合并
压缩x个commit,只保留一个commit
git rebase -i HEAD~x
进行rebase操作
执行git rebase -i HEAD~2,然后会自动进入vi界面。
把pick改成s即可合并
只保留一个pick,其余全改成s(quash)。
修改完成之后保存退出,会自动进入确认页面,再次保存退出即可.
提交推送到远程之后再去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网站上截取了一些图,会清晰一些
这张图非常经典,是很多场景下的常态。C1是线上的版本,在C1的代码上线了之后发现了一个bug,于是我们checkout一个叫做bugFix的分支。与此同时还有新的功能在开发,新的功能提交到了master之后形成了节点C2。这个时候我们在bugFix分支当然可以merge master这没有什么问题,但是也可以rebase master,rebase之后整棵git树会变成这样:
这个结果就好像是我们先到了C2然后checkout出了bugFix分支,然后在bugFix分支上将之前写过的代码重新写了一遍。这样的操作就是变基,当我们rebase了之后再提交合并请求我们的合并记录里面会非常干净,没有多余merge的信息。对于多人协同开发的场景非常有帮助。
rebase实战1
使用rebase将多个分支合并为一个分支。
* 6ed3c75 (HEAD -> test) test2
* ddc07d4 test1
| * 94f451d (dev) dev2
| * 3036534 dev1
|/
* 5385f77 (master) init
创建3个分支,master默认的主分支,创建dev分支,并且进行2次提交。创建出test分支,并进行2次提交;
- 接下来要对test分支进行变基,现在test的根基是从master的init提交记录开始向后发展,我们的目的是,将test分支的根基变为从dev分支的dev2提交记录开始。这样将test分支合并到dev分支后,分支的流程会非常清晰。
- 对test分支进行变基,需要先切换到test分支中
- 在test分支执行
git rebase dev
命令 - 执行命令的意思是,test分支变更基准点,用dev分支的dev2提交作为新的基准点
变基分支,解决冲突
将test分支上的提交test1应用到新的基准点dev2尾部,出现了合并冲突。
查看状态发现test分支变基过程中新的基准点,正是dev2的提交记录。
处理冲突有3种方式:如上图所示
- git rebase —continue 解决冲突,继续变基
- git rebase —skip 丢弃test分支的提交记录,如果一直使用skip操作,变基完成后,则test1和test2的提交记录被丢弃,test分支和dev分支完全相同
- git rebase —abort 表示终止rebase操作,恢复到之前。
操作一:解决冲突
解决冲突,都使用传入的值。手动合并提交,继续变基。完成后就如下图。
此时的分支状态
操作二:skip表示丢弃当前test分支的提交记录。
操作完成后,分支状态如下:
test分支指向了dev分支的提交记录。 ```git
- 94f451d (HEAD -> dev, test) dev2
- 3036534 dev1
- 5385f77 (master) init
```
操作三:abort,表示终止rebase操作,恢复到操作之前。
更新dev分支,再进行变基合并
在执行完操作一后,已经完成了test的变基为dev分支。
接下来更新dev提交记录,增加2次新的提交dev3和dev4
分支状态如下:
切换到dev分支,再次执行 git rebase dev,变基test分支到dev
* 8a15044 (dev) dev4
* ea979f8 dev3
| * 587ae1d (HEAD -> test) test2
| * 9d792da test1
|/
* 94f451d dev2
* 3036534 dev1
* 5385f77 (master) init
执行rebase之后
* 4ca8bde (HEAD -> test) test2
* 118688d test1
* 8a15044 (dev) dev4
* ea979f8 dev3
* 94f451d dev2
* 3036534 dev1
* 5385f77 (master) init
实战2
对2个分支进行变基时,2个分支生成提交记录并不一定要在目标分支上应用。
如下图,
- 创建一个主分支master,提交c1和c2,
- 然后从c2切出一个server分支来,增加c3和c4,c10提交记录。
- 从c3提交记录切出来一个client分支,并提交c8和c9记录
* 4ecb8e9 (HEAD -> master) c6
* 3aa47c1 c5
| * 0654c5e (server) c10
| * 5ec5b18 c4
| | * 39bcfd9 (client) c9
| | * 8830b89 c8
| |/
| * 8e9d273 c3
|/
* 2ce4be6 c2
* 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分支的修改一样。
执行过命令之后,分支状态如下:
* b1432fc (HEAD -> client) c9
* 3a69cbb c8
* 4ecb8e9 (master) c6
* 3aa47c1 c5
| * 0654c5e (server) c10
| * 5ec5b18 c4
| * 8e9d273 c3
|/
* 2ce4be6 c2
* 1ccced1 c1
现在就可以快速合并master分支。
# 切换到master分支
git checkout master
# 把client分支merge到master分支
git merge client
操作完成后,分支状态如下
* b1432fc (HEAD -> master, client) c9
* 3a69cbb c8
* 4ecb8e9 c6
* 3aa47c1 c5
| * 0654c5e (server) c10
| * 5ec5b18 c4
| * 8e9d273 c3
|/
* 2ce4be6 c2
* 1ccced1 c1
合并分支server
server开发完成,现在决定合并server分支。
在master分支中,直接使用git rebase master server
命令;可以直接将server分支变基到master分支。
# 在master分支下
git rebase master server
这样操作省去了先切换到server分支,然后在对server进行变基的多个命令步骤。
之后server的代码就加到了master分支的后面。分支状态如下图
* 861ea8a (HEAD -> server) c10
* b2733e7 c4
* 52b7336 c3
* b1432fc (master, client) c9
* 3a69cbb c8
* 4ecb8e9 c6
* 3aa47c1 c5
* 2ce4be6 c2
* 1ccced1 c1
之后就可以把server分支快速合并到master分支
git checkout master
git checkout server
* 861ea8a (HEAD -> master, server) c10
* b2733e7 c4
* 52b7336 c3
* b1432fc (client) c9
* 3a69cbb c8
* 4ecb8e9 c6
* 3aa47c1 c5
* 2ce4be6 c2
* 1ccced1 c1
合并过client和server分支,就可以将它们删除
git branch -d client
git branch -d server