简体   繁体   English

无意中合并了大师进入开发和推动

[英]Accidentally merged master into develop and pushed

I work in a git repo where we maintain a master and a develop branch. 我在一个git仓库工作,我们维护一个主人和一个开发分支。 Changes are made in develop and merged into master before releases. 在开发之前进行更改并在发布之前合并到master中。 Today I accidentally merged master into develop and pushed the result to develop. 今天我不小心把大师合并到了开发中并推动了结果的发展。 A git log in develop now shows the merge develop into master commits. 现在开发的git log显示merge develop into master提交。 I need to fix this somehow. 我需要以某种方式解决这个问题。 I found the most recent good commit using git reflog . 我使用git reflog找到了最近的好提交。 What is the correct approach to revert to it? 恢复它的正确方法是什么?

Since I have already pushed, I would like to avoid rewriting history. 由于我已经推,我想避免重写历史。 However, I'm not sure that I can use git revert . 但是,我不确定我是否可以使用git revert I'm not convinced that the "revert a faulty merge" howto and other SO questions apply since the commits that I want to revert are merges themselves ( https://www.kernel.org/pub/software/scm/git/docs/howto/revert-a-faulty-merge.txt ). 我不相信“恢复错误的合并”howto和其他SO问题适用,因为我想要恢复的提交是自己合并的( https://www.kernel.org/pub/software/scm/git/docs /howto/revert-a-faulty-merge.txt )。

You can use git revert to revert the merge. 可以使用git revert还原合并。 Just be aware that when you do that, you make a future "re-merge" more difficult. 请注意,当您这样做时,您将使未来“重新合并”变得更加困难。 Read that message you linked closely—it says a lot about how to make the future "re-merge" work—but be aware that it's talking about merging develop into master , and you said you did the opposite, merged master into develop : 阅读你密切关注的那条消息 - 它说了很多关于如何使未来“重新合并”的工作 - 但要注意它正在谈论将develop合并到master ,你说你做了相反的,合并的master进入develop

A -- B -- C -- D -- E          <-- master
      \          \
       F - G - H - M           <-- develop

In this case (having merged master into develop instead of the other way around) you can choose a number of different options, all with advantages and drawbacks... 在这种情况下(将master合并为develop而不是相反)你可以选择许多不同的选项,所有选项都有优点和缺点......

The easiest method, which I prefer if it's an option 最简单的方法,如果它是一个选项,我更喜欢

(0) Do nothing. (0)什么都不做。 If merging in C and D doesn't break the develop branch, just leave it that way. 如果在CD中合并不会破坏develop分支,那么就这样离开。 Later, someone will git checkout master and git merge --no-ff develop and get this (let's say one more commit I got added to develop first): 后来,有人会git checkout mastergit merge --no-ff develop并得到这个(假设I再加入一个提交以进行develop ):

A -- B -- C -- D -- E -- M2    <-- master
      \          \      /
       F - G - H - M - I       <-- develop

Here merge finds what's been done in develop since it split off from master , which was at B . 这里merge找到了develop已经完成的工作,因为它从master处分离出来,这是在B So it puts in F , G , and H , skips any parts of M that came off master (probably all of it), and finally puts in I and makes merge-commit M2 (because of commit E ; but if E were not there, it would be because I used --no-ff too). 所以它把在FG ,而H ,跳过的任何部分M是来到了master (可能是所有的话),最后提出在I ,使合并提交M2 (因为提交的E ;但如果E不存在,那是因为我使用了--no-ff )。

Some easy methods with obvious drawbacks 一些简单的方法有明显的缺点

(1) Just "rewrite history": erase commit M from branch develop . (1)只是“重写历史”:从分支develop擦除提交M Alert everyone else who uses the branch that this is about to happen: that commit M is going away and they should take whatever measures they must, to handle this. 警告使用该分支即将发生的所有其他人:提交M即将离开,他们应该采取他们必须采取的任何措施来处理这个问题。

(2) Stop using the old name develop , make a new branch name develop1 or whatever: (2)停止使用旧名称develop ,创建一个新的分支名称develop1或者其他:

A -- B -- C -- D -- E          <-- master
     |           \
     |             M           <-- develop
      \          /
       F - G - H               <-- develop1

This is the same as option (1) except that the commit M is still there, along with the branch label on it, and you have a new/different branch label pointing to commit H . 这与选项(1)相同,除了提交M仍然存在,连同其上的分支标签,并且您有一个指向提交H的新/不同分支标签。 You still need to alert everyone, but it might make their jobs easier. 您仍需要提醒所有人,但这可能会使他们的工作更轻松。 You can delete develop later, when everyone is good with that. 您可以稍后删除develop ,当每个人都很好。

The revert and its drawbacks 还原及其缺点

(3) Revert the merge. (3)恢复合并。 As in the linked article, let's use W to represent the new revert commit: 与链接文章一样,让我们​​使用W来表示新的还原提交:

A -- B -- C -- D -- E          <-- master
      \          \
       F - G - H - M - W       <-- develop

What's in W ? 什么在W Whatever it takes to "erase the effect" of the merge. 无论如何“消除合并的效果”。 In this case, that means, changes that un-do whatever was done in C and D . 在这种情况下,这意味着,在CD执行的任何操作均无法执行。 So far so good, develop has just the changes from F , G , and H , again. 到目前为止, develop只有FGH的变化。 The problem occurs later , if/when someone does: 如果/有人这样做,问题会在以后发生:

git checkout master
git merge develop

The second command goes rooting around to find where master and develop were split, ie, commit B , so it picks up all the changes since then. 第二个命令根深蒂固地查找masterdevelop被拆分的位置,即提交B ,因此它会从那时起获取所有更改。 Which at this point include those in W , which will un -do C and D , not at all what you wanted. 在这一点上,包括W那些,它们将取消 CD ,而不是你想要的。 It can be fixed-up afterward, but whoever does the merge has to know about this "delete C and D " time-bomb waiting for them. 它可以在之后修复,但是合并的人必须知道这个“删除CD ”定时炸弹等待它们。

Note that this is the same merge as in the "do nothing" option (0). 请注意,这与“不执行任何操作”选项(0)中的合并相同。 The issue here is the contents of W . 这里的问题是W内容 In case (0), you want the contents of commit I , but here you don't want the contents of W . 在case(0)中,你想要 commit I的内容,但是在这里你不需要 W的内容。

One more option 还有一个选择

This is arguably the worst option of all, given what's shown above, but I'll list it anyway: 考虑到上面显示的内容,这可以说是最糟糕的选择,但无论如何我都会列出它:

(4) make an all-new branch with copies of the commits you want to keep, and name it develop . (4)创建一个包含您要保留的提交副本的全新分支,并将其命名为develop (Or name it something else, but then we're back to the develop1 -like situation above, and you should probably just use that one.) Whether you keep the old-develop branch, or just abandon it (by not labeling it), is up to you, but I will draw it in: (或者将其命名为其他内容,但之后我们又回到了develop1的情况,你应该只使用那个。)无论你是保留old-develop分支,还是放弃它(通过不标记它) ,由你决定,但我会把它画进去:

       F' - G' - H'            <-- develop
      /
A -- B -- C -- D -- E          <-- master
      \          \
       F - G - H - M           <-- old-develop

This is described in the link you included. 这包含在您包含的链接中。 It's only really useful in more complex cases. 它只适用于更复杂的情况。

You can fix this by resetting your local branch back to the last good commit, then pushing that: 您可以通过将本地分支重置为上一次良好提交来解决此问题,然后推送:

git checkout develop
git reset --hard lastgoodcommit
git push origin develop

Note that your upstream repository may disallow non-fast-forward merges by default. 请注意,默认情况下,您的上游存储库可能会禁止非快进合并。 If so, you will need to modify that option on your upstream, do the above push, and then restore the original setting. 如果是这样,您将需要在上游修改该选项,执行上述操作,然后恢复原始设置。

I use GIT Extensions. 我使用GIT Extensions。 There is a feature to right click a revision in the UI and revert back to it. 有一个功能可以右键单击UI中的修订并还原为它。

Yes, you can revert a merge, but you need to specify which parent is the mainline. 是的,您可以还原合并,但您需要指定哪个父级是主线。 Since you merged develop into master, this should do the trick: 既然你将开发合并为master,那么这应该可以解决问题:

git revert --mainline 1 HEAD

To make sure you have exactly what you want, you should do a diff with $lastgoodcommit, however, $lastgoodcommit should be HEAD^. 为了确保你有你想要的东西,你应该用$ lastgoodcommit做差异,但是,$ lastgoodcommit应该是HEAD ^。 This is of course, if you haven't made commits on top of the merge, if you have, then you need to replace HEAD with the merge commit. 这当然是,如果你没有在合并之上进行提交,如果你有,那么你需要用合并提交替换HEAD。

Finally, you can also do the revert manually, by checking out the code on top of the current commit: 最后,您还可以通过检查当前提交之上的代码来手动还原:

git checkout $lastgoodcommit -- .

The '-- .' ' - 。' is there to differentiate from a normal checkout, where HEAD is switched to the specified commit, in the command here, all the files in the working directory, and the staging area, are going to be exactly the same as they were in $lastgoodcommit. 有没有区别于正常结账,其中HEAD切换到指定的提交,在此处的命令中,工作目录中的所有文件和暂存区域将与$ lastgoodcommit中的完全相同。 If you do a diff with $lastgoodcommit, you should see, again, no changes. 如果你用$ lastgoodcommit做差异,你应该再次看到没有变化。 Essentially it's a revert. 基本上它是一个恢复。

You could also try ' git checkout --patch ' to selectively revert chunks of code. 您还可以尝试' git checkout --patch '来有选择地还原代码块。

暂无
暂无

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

相关问题 git:我不小心将功能分支合并到master中,而不是进行合并 - git: I accidentally merged feature branch into master instead of develop 我将分支开发合并到主分支,但在主分支上,开发没有变化 - I merged branches develop into master but on master branch no changes from develop git:我将master合并为development,现在呢? - git: I merged master into develop, now what? 如何停止与开发分支合并的分支与主分支合并? - How to stop a branch merged with develop branch to be merged with master branch? pull而不是fetch - 意外地将远程master合并到本地分支 - pull instead of fetch - accidentally merged remote master into local branch 使用git merge --squash将master先前合并到dev中时将development合并到master中? - Using git merge --squash to merge develop into master when master was previously merged into develop? Sourcetree显示原始开发者和母版,但是bitbucket仅显示合并的母版和母版,如何解决? - Sourcetree shows develop and master in origin, but bitbucket shows only master and develop merged, how to fix it? 仅获取已合并到master / develop中的远程分支 - Get only remote branches that have already been merged into master/develop 当它们合并在一起时如何解开 master/develop - How to untangle master / develop when they've been merged together Git:如何删除所有本地分支(合并与否),除了master和develop - Git : How to delete all local branches (merged or not), except master and develop
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM