简体   繁体   English

将提交从一个分支移动到另一个分支,然后将它们合并回来

[英]Move commits from one branch to another and then merge them back in

I have a tree: 我有一棵树:

       /--b1---b2 <-- topic b
      /    
a1---a2 <-- topic a

where 'b' depends on 'a'. 其中'b'取决于'a'。 Then I realize I need to do some changes related to topic 'a' in order to continue with 'b', but i'd like to do them on 'b' as a normal development course of 'b': 然后我意识到我需要做一些与主题'a'相关的更改以继续'b',但我想在'b'上做它们作为'b'的正常开发过程:

       /--b1---b2---a3---a4---b3---b4---a5---b5 <-- topic b
      /    
a1---a2 <-- topic a

Then, when the thing I want to accomplish on 'b' is done, I'd like my tree to look like this: 然后,当我想在'b'上完成的事情完成时,我希望我的树看起来像这样:

       /--b1---b2--------m---b3'---b4'---b5' <-- topic b
      /                 /
a1---a2---a3'---a4'---a5' <-- topic a

as if I actually did all the changes on 'a', then merged them on 'b' and then continued on 'b'. 好像我实际上对'a'进行了所有更改,然后将它们合并在'b'上,然后继续'b'。

I know I can do this manually doing: 我知道我可以手动执行此操作:

1- rebase/cherry-pick 'a' commits from branch 'b' to 'a' 1- rebase / cherry-pick'a'从分支'b'提交到'a'
2- create a temporal branch 'b-tmp' on 'b'. 2-在'b'上创建一个时间分支'b-tmp'。
3- reset branch 'b' to 'b2'. 3-将分支'b'重置为'b2'。
4- merge 'a' onto 'b'. 4-将'a'合并到'b'上。
5- rebase/cherry-pick 'b' commits from 'b-tmp' onto 'b'. 5- rebase / cherry-pick'b'从'b-tmp'提交到'b'。
6- delete branch 'b-tmp'. 6-删除分支'b-tmp'。

I can create some script to do this, I'd just like to know if there are better ways/ideas to do this, other than this 6 steps. 我可以创建一些脚本来执行此操作,我只想知道是否有更好的方法/想法来执行此操作,除了这6个步骤。

Let me start out with saying that I'd rather integrate the topic branches often (Integrate Early, Build Often ... rings a bell?). 让我先说我宁愿经常整合主题分支(早期整合,经常构建......敲响钟声?)。 So in fact, when there are changes that should go onto a eventually, I'd go back, do the changes on a , and rebase b on top of a . 所以,事实上,当有应该去到最终的变化,我会回去,做一个的变化,变基B关于顶部。

If a needs to be stable for some other purpose, I'd make a a-for-b branch to contain the work temporarily, and rebase b on top of that. 如果需要其他一些目的是稳定的,我会成为一个一个换乙支路包含的工作暂时和变基B关于最重要的是。

If you really must work with 'topic- a ' changes inside branch ' b ', Here's what i'd do. 如果你真的必须使用分支' b '内的'topic- a '变化,那就是我要做的。

Note: screencasts included 注意: 包括截屏视频


Getting to the starting point 到达起点

This is a simple working tree with the layout from the question: 这是一个简单的工作树,其中包含以下问题的布局:

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 

See screencast here 在这里截屏


Reorganizing commits onto their topic branches 将提交重新组织到其主题分支上

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

Again, see screencast 再次, 请参阅截屏视频


Inspecting results 检查结果

We can now do a before/after tree comparison: 我们现在可以进行前/后树比较:

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

Making it permanent: 永久化:

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

Notes 笔记

I have deliberately chosen to make non-conflicting changes for the demo. 我故意选择对演示进行非冲突的更改。 Of course in real life you'll get merge conflicts. 当然,在现实生活中,你会遇到合并冲突。 Use git mergetool and git rebase --continue . 使用git mergetoolgit rebase --continue

If your changes are hygienic and really belong on their respective topic branches, chances are that conflicts should be few and easily resolved. 如果您的更改是卫生的并且确实属于各自的主题分支,那么冲突可能很少并且很容易解决。 Otherwise, it is time to revise your branching scheme (see Martin Fowler ea) 否则,是时候修改你的分支方案了 (参见Martin Fowler ea)

Discussion 讨论

In response to 回应

You also say that "when there are changes that should go onto 'a' eventually, I'd go back, do the changes on 'a', and rebase 'b' on top of 'a'". 你还说“当最终会有'a'的变化时,我会回去,对'a'进行更改,然后在'a'之上'b''。 I'm not sure I understand this also. 我也不确定我是否理解这一点。 Could you explain? 你能解释一下吗?

I mean that I would try to make the a3,a4,a5 revisions on the a branch anyway, and rebase b onto that, so 我的意思是,我会尽量让A3,A4,A5的一个分支版本,无论如何,和变基b到这一点,所以

  • the person doing the merge is the same person doing the commits 进行合并的人是进行提交的同一个人
  • you do the commit and merge in succession (meaning you don't mess things up due to short-term-memory loss) <-- this is the Merge Early/Soon/Frequently mantra 你连续进行提交和合并(这意味着你不会因为短期内存丢失而搞乱) <-- this is the Merge Early/Soon/Frequently mantra
  • you avoid unnecessary merge conflicts 你避免不必要的合并冲突
  • you don't have to 'go back in time' later and rewrite the original commits: a3, a4, a5 would just be merged, not copied (see Git Cherry-pick vs Merge Workflow ) 你不必在以后“回到过去”并重写原始提交:a3,a4,a5将被合并,而不是被复制(参见Git Cherry-pick vs Merge Workflow

Here is the 'Getting to the starting' point, but adapted to my idealized workflow. 这是“走向起点”,但适应了我理想化的工作流程。 Note that the end-result of this alternative result is already exactly what you end up after all the juggling shown under 'Reorganizing commits onto their topic branches' above! 请注意,这个替代结果的最终结果已经完全是您在上面的“重组提交到他们的主题分支”下显示的所有杂耍之后结束的!

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

Note that it is in practice not hard to go back to the a branch to commit your a3/a4/a5 commits: 请注意 ,实际上回到a分支提交a3 / a4 / a5提交并不困难:

  • in case you only realized you touched things that belong on that branch, you can just switch to the a branch with pending local changes 2 如果您只是意识到触摸了属于该分支的内容,您可以切换具有待定本地更改 分支2
  • you then selectively (!!) stage the parts that needed to go onto the a branch ( git add -i or similar in git guis or eg vim fugitive ) 你再选择 (!!)第一阶段是需要去到一个分支部分( git add -i或Git的图形用户界面相似或如vim fugitive
  • commit on a 提交
  • switch back to the b branch ( git checkout b ) 切换回b分支( git checkout b
  • commit the remaining bits 提交其余的位
  • rebase b onto the latest revision in a 变基b最新修订版

2 as long as they don't conflict with other changes from a..b ; 2只要它们不与a..b的其他变化发生冲突; in that case you'd git stash first and git stash apply when on the a branch 在这种情况下你git stash第一和git stash apply一个分支时

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何将一个分支从分支的头提交到新分支中,而合并后又不丢弃它们呢? - How does one Move Commits from the Head of a Branch into a New Branch and not have them be Discarded when Merged back in? 将提交从一个分支合并到另一个分支 - merge commits from one branch into another one 将多个提交从一个分支移动到另一个分支? - Move several commits from one branch to another? 如何将一些已发布的提交(包括合并)移动到分支并在以后合并回去 - How to move some published commits including a merge to a branch and merge them back later 将提交从一个分支移动到 GitHub 中的另一个分支? - Move Commits from One Branch to Another Branch in GitHub? 将某些文件(不提交)从一个分支合并到另一个分支 - Merge Certain Files (not commits) From One Branch to Another Branch 将一系列提交从一个(本地)分支移至另一个 - Move a sequential set of commits from one (local) branch to another 如何将未发布的提交从一个分支移动到另一个分支? - How to move unpublished commits from one branch to another? git move / migrate从一个分支提交到另一个分支 - git move/migrate commits from one branch to another 如何将所有提交从一个分支合并到另一个分支? - How to merge all commits from one branch to another?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM