最近项目新功能在 feature 分支开发中,突然要修复一些 bug,所以开了 fixbug 分支
请问修复之后的 commit 如何 rebase 到 feature 分支保持干净?
1 -> 2 -> 3 -> 6 -> 7 feature 分支
1 -> 2 -> 3 -> 4 -> 5 fixbug 分支
理想中 rebase 之后的 commit
1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7
1
dsdisenc 2020-08-05 15:40:09 +08:00
git checkout feature
git rebase fixbug 这样顺序就是 1234567 了 |
2
353943780 OP |
3
gesse 2020-08-05 15:50:19 +08:00
feature 上的 4-5 和 fixbug 上 6-7 并没有严格的先后顺序
不管是 rebase 还是 merge,其实都是“合并代码”的过程 |
4
rproud 2020-08-05 15:50:49 +08:00 14
来玩个游戏你就会了。https://learngitbranching.js.org
|
6
gesse 2020-08-05 16:15:30 +08:00
rebase 怎么理解呢?
比如 分支 a 是 1-2-3 分支 b 是 1-2-4-5 在分支 b 上 rebase a 分支的意思是: 以 a 分支为"base",然后把“相对于 a 分支不同的 commit (也就是 4-5 )”加到 a 分支的后面,然后合并后( rebase 也要合并,因为在 a 分支上创建 b 分支后,a 分支也有修改的内容)的这个 branch 重新定义为 b,且 a 分支不变 |
7
353943780 OP |
9
luxinfl 2020-08-05 17:13:11 +08:00
小小的吐个槽,feature 分支的数字应该比 fixbug 分支小才对。。
|
10
fan123199 2020-08-05 17:17:10 +08:00 via Android
如果 featuea 的 commoit 数已经特别多了,可以考虑用 cherry pick 。不然有冲突就难受了。
|
12
353943780 OP @fan123199 请问如果 feature commit 多,而且 commit 时间点与 fixbug 交错,例如
feature 1-2-3-4-6-8-9-10 fixbug 1-2-5-7 是不是无法 rebase 为单条时间线呢? |
13
JJstyle 2020-08-05 17:48:05 +08:00
用 cherry-pick,简单易用:
```bash git checkout -b feature_tmp 3 git cherry-pick 4^..5 git cherry-pick 6^..7 git branch -d feature git branch -m feature ``` 虽然操作步骤多一点,但是更易于常人理解! |
14
GeruzoniAnsasu 2020-08-05 17:48:47 +08:00
跟时间没关系
checkout feature, rebase bug ==> 125734689 checkout fixbug, rebase feature ==> 12346891057 |
15
JJstyle 2020-08-05 17:54:39 +08:00
#13 cherry-pick 也能只 copy 一个 commit,上面的例子没显示出来,比如:
```bash git cherry-pick 7 ``` 这样就把 commit 7 copy 到当前分支了,如果多个就是 a..b,前开后必区间,所以如果 copy a 到 b,且包含 a 和 b,那就用 a^..b |
17
353943780 OP @GeruzoniAnsasu 大佬,刚刚试了一下,rebase 之后确实跟时间没有关系 👍,但是发现 rebase 之后 push,有提示 pull,但是 pull 之后会自动产生一个 commit 是 merge fixbug 分支的,请问这样的情况怎么处理呢?
|
20
ScepterZ 2020-08-05 18:56:16 +08:00
按理说你的 fixbug 应该要 merge 到 master 吧
mrege 之后 git checkout feature git rebase master 然后变成 1 2 3 4 5 6new 7 new |
21
GeruzoniAnsasu 2020-08-05 18:56:23 +08:00
@353943780 我们假设一个场景是 checkout fixbug 然后 rebase 了 feature
照之前的例子,本地历史被改成了 1-2-3-4-6-8-9-10-5-7 但此时远程的 fixbug 历史还是 1-2-5-7,两边不一致 所以你想直接推的时候会提示要合并远程 如果此时你先 pull 的话就会变成 1-2-3-4-6-8-9-10-5-7-merge,然后 merge commit 的两个 parent 分别是远程的 7 和你本地的 7,原本单历史线就会不必要地变成双线+合并历史,比较混乱 所以此时不要管远程,直接 force push 让你本地的单线历史覆盖远程的就行,反正远程的 5 和 7 两个 commit 在你准备推的历史线里都是有的 rebase 完经常是要 force push 的,确认本地 rebase 前已经完全同步了远程并且 rebase 后远程没有新 commit 就行 force push 用 git push --force-with-lease |
22
353943780 OP @GeruzoniAnsasu 👍👍 学习了,牛皮啊大佬
|
24
HangoX 2020-08-05 19:42:49 +08:00
我一般都是
```bash git checkout feature git merge --squash fixbug ``` 直接把 bug 那个变成一条提交加到 feature 上来就好了 |
25
fan123199 2020-08-05 20:34:23 +08:00
@GeruzoniAnsasu #21 。有个前提,这个是 fixbug 是你一个人使用的分支的情况下才可以这么用。其实 force 操作总归是危险的。
|
26
johnsona 2020-08-05 20:53:23 +08:00
结合 pycharm 的 git rebase 可视化解决冲突食用,更加愉快
|
28
365473321 2020-08-05 22:14:26 +08:00
我的理解:其实 rebase 就是修改 commit 记录,还没提交到 remote 的 commit 在本地怎么折腾都行,squash 、fixup 、cherrypick,甚至 force push,怎么舒服怎么来,无非就是让历史记录看起来舒服一些。如果是多人开发,本地的 commit 又在 remote 上,老老实实用 merge 。
|
29
no1xsyzy 2020-08-06 10:08:38 +08:00
同上,而且 Github 工作流的类比,任何 bugfix 的分支最后也应该是 merge 进主线的。
|
30
julyclyde 2020-08-06 10:09:32 +08:00
rebase 就是把 merge-base 点向前推进了
|
31
raysonlu 2020-08-06 10:40:38 +08:00
之前我也在纠结这个 rebase 功能,但我发现很难把控这个(或者我未理解透彻其背后运作)。最后还是决定用回 merge,在处理类似 fixbug 分支,我心目中是要保留这个分支信息的,就是要看到:在某一点另辟蹊径,修复了问题,然后合并回归到主线。merge 的时候加上--no-ff 就好了。
|
32
GeruzoniAnsasu 2020-08-06 10:58:08 +08:00
@raysonlu rebase 这个命令其实意义有点误导,它应该叫 git modify-history
移动 commit 到其它分支,调整 commit 顺序,修改 commit 信息,修改 commit 作者,修改内容 全都可以借助 rebase 个人感觉 rebase 的本意是调整当前分支的 base,像拉拉链一样移动缝合点,但实现这个效果得把当前 base 后的所有 commit 都接到另一个地方去,相当于一次性移动修改多个 commit,然后又因为反正都要修改,不如顺便能修改 commit 历史……结果就变成了一个啥都能干的命令 git reset 和 git rebase 是 git 里最意义不明的两个 sub command |
33
johnsona 2020-08-06 11:13:38 +08:00
1.git rebase 是变基操作,feature 1-2,bugfix 从 feature 分出来,提交是 1-2-3,这时候切换回 feature,再提交一个,变成 feature 1-2-4
这时候如果在 feature 合并 bugfix 会变成 1-2-( 3,4 )-5,提交历史是双线,不是很清晰,怎么办呢,我们可以让 feature 分支基于 bugfix 分支,这就是 git rebase,过程是首先找到两个分支的共同祖先 1-2,然后再 feature 分支上 copy3 提交,然后提交 4`这 4‘和 4 的 hash 值不一样了,只是修改一样而已。然后当然如果 3-4 冲突了,还是要解决冲突,但最后的结果还是 1-2-3-4`,就是一条直线了,而且和提交时间无关,就是把 bugfix 的不同提交插入 feature 分支的 2 后面 2.解决冲突可配合 pycharm 使用,可视化更加方便,否则文件中一堆》》》 |
34
johnsona 2020-08-06 11:25:52 +08:00
我的应用场景是这样。我们不允许本地直接提交 develop 分支,都是拉下来 develop 分支,创建 feature 分支,然后 push 到远程 feature 分支,然后远程提 pr 要求合并到 develop,给别人 review 。这时候就有个问题了,我不能在别人 review 的时候 block 在那里啊,如果幸运的话,我的 feature 分支通过了,会合并到 develop 分支,所以我本地得从 feature 分支 checkout 一个 feature2,然后继续开发。
问题来了,如果我的远程的 feature 分支要修改,比如 feature 现在是 1-2,远程也是 1-2,但我要修改本地变成 1-2-3,但是这个 feature 就变成了 2-3 两次提交,一次任务两次提交,不好在 web 界面对比和 develop 的变化,所以我要在本地合并 2 、3 提交,变成 4,就是 1-4 了,这时候远程还是 1-2,没办法,git push origin feature -f 强制提交。 又有问题来了,feature2 刚刚还是切换过来还是 1-2 呀,这可怎么办,如果 git merge feature 就分叉了,这时候就可以用 git rebase 让 feature2 以 feature 为基,变成 1-4-2’,看起来就像是从最新的本地 feature 分支切换过来,又加了一次提交,当然这个 2‘已经不是原来的 2’了,hash 值也不一样了。这样的好处是,如果 feature 远程合并到了 develop 远程,develop 提交记录就是 1-4,你的 feature2 再合过去就不会有冲突了 |
35
johnsona 2020-08-06 11:31:08 +08:00
git rebase 的应用场景还包括,合并提交,比如我的 feature 变成了 1-2-3,2-3 是一次任务的两次提交,要合并成一个,怎么办,可以先 git reset soft 到 1 这个位置,然后把暂存区的 commit 一次,变成 4,就合并成功了。也可以 git rebase 。
至于 bug,一般是先从 develop 分出来一个 bug 分支,然后修改,一次提交,合到 develop,这时候 feature 分支原来也是从 develop 分出来的,肯定也有这个 bug,所以要把这个 bug 的提交也再 feature 上面重放一次,记住是重放,提交哈希值是不一样的,一般用 cherry-pick 。当然你也可以 git rebase 基于最新的 develop,让那个 bug 的提交插入到 develop 的提交和你的 feature 提交之间 |