我有一棵树:
/--b1---b2 <-- topic b
/
a1---a2 <-- topic a
其中'b'取决于'a'。然后我意识到我需要做一些与主题'a'相关的更改才能继续使用'b',但是我想在'b'上做它们作为'b'的正常开发过程:
/--b1---b2---a3---a4---b3---b4---a5---b5 <-- topic b
/
a1---a2 <-- topic a
然后,当我想在'b'上完成的事情完成时,我希望我的树看起来像这样:
/--b1---b2--------m---b3'---b4'---b5' <-- topic b
/ /
a1---a2---a3'---a4'---a5' <-- topic a
好像我实际上对'a'进行了所有更改,然后将它们合并在'b'上,然后继续'b'。
我知道我可以手动执行此操作:
1 rebase / cherry-pick'a'从分支'b'提交到'a'
2-在'b'上创建一个时间分支'b-tmp'
3-将分支'b'重置为'b2'。
4-将'a'合并到'b'。
5- rebase / cherry-pick'b'从'b-tmp'提交到'b'
6-删除分支'b-tmp'。
我可以创建一些脚本来执行此操作,我只想知道是否有更好的方法/想法来执行此操作,除了这6个步骤。
答案 0 :(得分:8)
让我首先说我宁愿经常整合主题分支(早期整合,经常构建......敲响钟声?)。事实上,当有最终应该进行的更改时,我会回去,对 a 进行更改,并在上重新设置 b 一个
如果 需要为某些其他目的而保持稳定,我会创建一个 a-for-b 分支暂时包含该工作,并重新定义 b 就在那之上。
如果你真的必须使用分支' b '中的'topic- a '更改,这就是我要做的事情。< / p>
注:包含 截屏视频
这是一个简单的工作树,其中包含问题的布局:
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
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
我们现在可以进行前/后树比较:
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 e.a。)
回应
你还说“当最终有变化应该进入'a'时,我会回去,对'a'进行更改,并在'a'之上进行'b'变更。”我也不确定我是否理解这一点。你能解释一下吗?
我的意思是我会尝试在 a 分支上制作a3,a4,a5版本,并将 b 重新定义到其上,所以
<-- this is the
Merge Early/Soon/Frequently
{ {1}} 这是“前往起点”,但适应了我理想化的工作流程。请注意,这个替代结果的最终结果是已经完全您在上面的“重组提交到他们的主题分支”下显示的所有杂耍之后结束了什么!
mantra
注意实际上回到a分支提交你的a3 / a4 / a5提交并不难:
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
或类似的git guis或例如{{} 3}})git add -i
) 2 只要它们与 a..b 的其他变化不冲突;在这种情况下,当您在 a 分支时,您首先git checkout b
和git stash