简体   繁体   English

恢复合并到主,保持功能分支的变化,不改变历史

[英]revert merge to master, keep feature branch changes, without changing history

I had a feature branch and a master branch.我有一个功能分支和一个主分支。 I did some work on the feature, merged into master, pushed the changes, and then deleted the feature branch, both remotely and locally.我对该功能做了一些工作,合并到 master 中,推送更改,然后远程和本地删除功能分支。 So far, so good.到现在为止还挺好。

After merging, I realized there was a problem with my feature changes.合并后,我意识到我的功能更改存在问题。 I'd like to undo the merge on master, but still keep the feature changes so I can work on them again.我想撤消对 master 的合并,但仍保留功能更改,以便我可以再次处理它们。 I don't want to rewrite the history of master because other people are working on it too.我不想重写master的历史,因为其他人也在努力。 I think my best bet is to use revert to make new commits that undo the problem?我认为我最好的选择是使用revert进行新的提交来解决问题?

What I had originally:我原来的:

A---B---C---D   [master]
     \      
      E----F    [feature]

What I have now:我现在所拥有的:

A---B---C---D---E'---F' [master]

What I want:我想要的是:

A---B---C---D---E'---F'---RE'---RF'        [master]
                                 \
                                  E"---F"  [feature]

RE' reverts E' and RF' reverts F'. RE' 还原 E',RF' 还原 F'。 Meanwhile E" contains the same content as the original E and F" contains the same content as the original F.同时E”包含与原始E相同的内容,F”包含与原始F相同的内容。

How do I accomplish this?我该如何实现?

Again, there are a lot of ways to do this.同样,有很多方法可以做到这一点。 Here is the command sequence I would most likley use given your desired final state—it ends up being just a hair different than what you drew:考虑到您想要的最终状态,这是我最喜欢使用的命令序列 - 它最终只是与您绘制的头发不同:

  1. git checkout master if needed, then git revert HEAD~2..HEAD to get: git checkout master如果需要,然后git revert HEAD~2..HEAD得到:

     A--B--C--D--E'--F'--RF'--RE' <-- master (HEAD)

    Note that git revert with a range backs commits out in reverse order.请注意,带有范围的git revert以相反的顺序提交。

  2. git checkout -b feature : git checkout -b feature

     A--B--C--D--E'--F'--RF'--RE' <-- master, feature (HEAD)
  3. git cherry-pick HEAD~4..HEAD~2 , to copy E--F again: git cherry-pick HEAD~4..HEAD~2 ,再次复制E--F

     A--B--C--D--E'--F'--RF'--RE' <-- master \\ E"--F" <-- feature (HEAD)

If it helps—with longer commit chains, it might—you can add temporary tags to various commits.如果它有帮助——使用更长的提交链,它可能——你可以为各种提交添加临时标签。 For instance, if you start with:例如,如果您从以下内容开始:

A--B--C--D--E'--F'   <-- master

and run:并运行:

git tag T1 HEAD~2; git tag T2 HEAD

you get:你得到:

        T1     T2
         |      |
         v      v
A--B--C--D--E'--F'   <-- master

So now you can use T1..T2 everywhere to mean "commits E' and F' , so that the revert command becomes:所以现在你可以在任何地方使用T1..T2来表示“提交E'F' ,这样 revert 命令变成:

git revert T1..T2

and the cherry-pick becomes:樱桃选择变成:

git cherry-pick T1..T2

Once you're done, you can delete the two temporary tags:完成后,您可以删除两个临时标签:

git tag -d T1 T2

as they were only there to remember the hash IDs of the two specific commits that delimit the range of "interesting" commits.因为他们只是在那里记住两个特定提交的哈希 ID,这些提交划定了“有趣”提交的范围。 The relative names ( HEAD~2..HEAD or master~2..master ) change their numbering as you add more commits and cause the names to move as well.相对名称( HEAD~2..HEADmaster~2..master )随着您添加更多提交并导致名称移动而更改其编号。

I would:我会:

  1. Add revert commits to master将还原提交添加到master
git checkout master
git revert HEAD~2..HEAD
git push
  1. Re-create the feature branch重新创建feature分支
git checkout -b feature
  1. Cherry-pick feature commits樱桃挑选feature提交
git cherry-pick HEAD~4..HEAD~2
git push

You could do你可以做

# make sure you're working from master
git checkout master

# revert commits E and F
# (but in reverse chronological order is better to avoid unnecessary conflicts)
git revert F E

At this point your tree looks like此时你的树看起来像

A---B---C---D---E---F---F'---E'        [master]

# then create your new branch
git checkout -b feature

# and here you might as well revert the reverts
git revert E' F'

to finally obtain最终获得

A---B---C---D---E---F---F'---E'        [master]
                              \
                               E''---F''   [feature]

But I'd suggest grouping E and F by using -n during the first revert (then you'll have to commit afterwards), it'll be easier at the next stages to revert the revert, and history will be much more readable.但是我建议在第一次还原期间使用-nEF进行分组(然后您必须在之后提交),在下一阶段还原还原会更容易,并且历史记录将更具可读性。 Like this :像这样 :

git checkout master
git revert -n F E
# (at this point, if you had to resolve conflicts, don't forget to add them)
git commit
git checkout -b feature
git revert E'

and the final tree :最后一棵树:

A---B---C---D---E---F---E'        [master]
                         \
                          E''     [feature]

(where in that last schema E' is the revertion of E and F ) (其中最后一个模式E'EF的还原)

Push all this only when you're satisfied with the whole situation.仅当您对整个情况感到满意时才推动所有这些。

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

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM