首先让我说我宁愿经常集成主题分支(早期集成,经常构建......敲响了警钟?)。所以事实上,当最终应该进行更改时,我会返回,在 a 上进行更改,然后在 之上重新设置 b一个。
如果 a 需要稳定以用于其他目的,我会创建一个 a-for-b 分支来临时包含工作,然后重新设置 b 最重要的是。
如果您真的必须处理分支“b”内的“topic-a”更改,我会这样做。
注意:包括截屏
到达起点
这是一个带有问题布局的简单工作树:
mkdir /tmp/q
cd /tmp/q
git init .
touch f
git add f
git commit -am initial
git checkout -b a; for a in a{1,2}; do echo $a>$a; git add $a; git commit -am $a; git tag $a; done
git checkout -b b; for a in b{1,2} a{3,4} b{3,4} a5 b5; do echo $a>$a; git add $a; git commit -am $a; git tag $a; done
git show-branch
见screencast here
将提交重新组织到他们的主题分支上
git checkout -b a_new a # for safety, work on a clone of branch a
git reset --hard b # start by moving it to the end of the b branch
git status # (just show where we are)
git log --oneline
git rebase -i a # rebase it on top of the original branch a
# not shown: delete every line with non-branch-a commits (b1-b5)
# see screencast
git log --oneline # (just show where we are again)
git checkout -b b_new b # for safety, work on a clone of branch b
git log --oneline # (just show where we are again: the end of branch b)
git rebase -i a_new # this time, rebase it on top of the new branch a_new
git log --oneline # (check results)
git show-branch b_new a_new
再说一遍,see screencast
检查结果
我们现在可以进行之前/之后的树比较:
sehe@natty:/tmp/q$ git show-branch a b
! [a] a2
! [b] b5
--
+ [b] b5
+ [b^] a5
+ [b~2] b4
+ [b~3] b3
+ [b~4] a4
+ [b~5] a3
+ [b~6] b2
+ [b~7] b1
++ [a] a2
sehe@natty:/tmp/q$ git show-branch a_new b_new
! [a_new] a5
* [b_new] b5
--
* [b_new] b5
* [b_new^] b4
* [b_new~2] b3
* [b_new~3] b2
* [b_new~4] b1
+* [a_new] a5
使其永久化:
for name in a b;
do
git branch -m $name ${name}_old &&
git branch -m ${name}_new $name
done
git branch -D a_old b_old # when sure
注意事项
我特意选择对演示进行不冲突的更改。当然,在现实生活中,您会遇到合并冲突。使用git mergetool 和git rebase --continue。
如果您的更改是卫生的并且确实属于它们各自的主题分支,那么冲突应该很少并且很容易解决。 否则,是时候修改您的分支方案了(参见 Martin Fowler 等)
讨论
回应
您还说“当最终应该对 'a' 进行更改时,我会返回,在 'a' 上进行更改,然后在 'a' 之上重新设置 'b'”。我不确定我是否也理解这一点。你能解释一下吗?
我的意思是,无论如何我都会尝试在 a 分支上进行 a3、a4、a5 修订,然后将 b 重新设置为基础,所以
- 进行合并的人与进行提交的人是同一个人
- 你连续提交和合并(这意味着你不会因为短期记忆丢失而搞砸)
<-- this is theMerge Early/Soon/Frequently mantra支持>
- 您可以避免不必要的合并冲突
- 您不必稍后“回到过去”并重写原始提交:a3、a4、a5 只会被合并,而不是复制(请参阅Git Cherry-pick vs Merge Workflow)
这是“开始”的起点,但适合我理想化的工作流程。请注意,这种替代结果的最终结果已经完全在上面“将提交重新组织到他们的主题分支”下显示的所有杂耍之后结束!
mkdir /tmp/q
cd /tmp/q
git init .
touch f
git add f
git commit -am initial
git checkout -b a; # no change
echo a1>a1; git add a1; git commit -am a1
echo a2>a2; git add a2; git commit -am a2
git checkout -b b; # start off the a branch
echo b1>b1; git add b1; git commit -am b1
echo b2>b2; git add b2; git commit -am b2
git checkout a # go back to the a branch for a3 and a4
echo a3>a3; git add a3; git commit -am a3
echo a4>a4; git add a4; git commit -am a4
git checkout b
git rebase a # here is the magic: rebase early
echo b3>b3; git add b3; git commit -am b3
echo b4>b4; git add b4; git commit -am b4
git checkout a # go back to the a branch for a5
echo a5>a5; git add a5; git commit -am a5
git checkout b
git rebase a # again: rebase early
echo b5>b5; git add b5; git commit -am b5
git show-branch
注意实际上返回到 a 分支来提交你的 a3/a4/a5 提交并不难:
- 如果您只意识到您触摸了属于该分支的东西,您可以切换到 a 分支等待本地更改 2
- 然后您有选择地 (!!) 将需要进入 a 分支的部分暂存(
git add -i 或 git guis 中的类似内容或例如 vim fugitive)
- 提交 a
- 切换回 b 分支 (
git checkout b)
- 提交剩余的位
- 将 b 重新定位到 a 中的最新版本
2 只要它们不与 a..b 的其他更改发生冲突;在这种情况下,您首先 git stash 和 git stash apply 在 a 分支上时