在Git中重新执行还原的合并


231

我在这里遇到了一个问题:我28s在Git中有一个特定于问题的分支,我将该develop分支合并到常规分支中。原来我做得太快了,所以我用git-revert撤消了合并。但是,现在已经到了合并的时候28sdevelop,但是git-merge命令看到了原始合并,并高兴地宣布一切顺利,分支已经合并。现在我该怎么做?创建一个“还原”,还原“ 28s->开发””提交?看来这不是一个好方法,但是我目前无法想象其他任何事情。

树形结构如下所示:

Git日志输出


4
它是GitX(gitx.frim.nl)。
Toms Mikoss,2009年

Answers:


169

您必须“还原还原”。取决于您如何还原原始内容,它可能听起来并不那么容易。查看有关此主题正式文档

---o---o---o---M---x---x---W---x---Y
              /
      ---A---B-------------------C---D

允许:

---o---o---o---M---x---x-------x-------*
              /                       /
      ---A---B-------------------C---D

但这一切有用吗?当然可以。您可以还原合并,从纯粹的技术角度来看,git很自然地做到了,并且没有真正的麻烦。
它只是认为它是从“合并前的状态”到“合并后的状态”的改变而已。
没什么复杂的,没有奇怪的,没有真正的危险。Git甚至不用考虑就可以做到。

因此,从技术角度来看,还原合并没有任何问题,但是从工作流程角度来看,通常应该避免这种情况

如果可能的话,例如,如果发现得到了合并到主树,出了问题,而不是撤销的合并,尽量真的很难

  • 将问题平分到合并的分支中,然后解决它,
  • 或尝试还原导致它的单个提交。

是的,它更复杂,不,它并不总是去上班(有时,答案是:“哎呀,我真不应该把它合并,因为当时还没有准备好,我真的需要撤消所有的合并”)。因此,您确实应该还原合并,但是当您要重新进行合并时,现在需要通过还原还原来进行合并。


10
友善连结(+1)。我自由地在您的答案中复制了文档的一部分,以使读者在这种情况下可以立即看到相关选项。如果您不同意,请随时还原。
VonC

5
我们只是遇到一个需要执行此操作的案例,发现乐趣并没有就此停止。这是一个长期运行的分支,已合并到其中,因此我们需要继续对其进行更新。我的做法在这里:tech.patientslikeme.com/2010/09/29/...
jdwyah

我关注了@jdwyah的博客文章,这很光荣(严重的是,它确实很不错)。
hellatan

2
@jdwyah似乎是一个损坏的链接,但这听起来像是一个有趣的阅读。这是一个archive.org镜像,但缺少图像:web.archive.org/web/20111229193713/http
//…


53

假设您有这样的历史

---o---o---o---M---W---x-------x-------*
              /                      
      ---A---B

其中A,B提交失败且W-是M的还原

因此,在开始修复发现的问题之前,我会先选择W提交给我的分支

git cherry-pick -x W

然后我在分支上还原W commit

git revert W 

之后,我可以继续修复。

最终历史可能如下所示:

---o---o---o---M---W---x-------x-------*
              /                       /     
      ---A---B---W---W`----------C---D

当我发送PR时,它将清楚地表明PR是撤消还原并添加了一些新的提交。


3
看来这可能会有所帮助,但细节如此稀疏(上图中的C,D是什么),以至于令人沮丧而不是有用
Isochronous

4
@等时的C和D似乎是可解决A和B引入的问题的提交。–
托马斯

@Thomas正好
Maksim Kotlyar

最好在这种情况下突出显示使用PR,因为它可以在合并回master之前提供最终的“健全性检查”。
Willem van Ketwich

使用为什么从原来的W重新启动分支?即,让您的话题从W继续,W`之后是C和D?这消除了一些重复
Erik Carstensen

12

要还原还原而又不会过多浪费您的工作流程,请执行以下操作:

  • 创建本地开发副本
  • 还原对本地开发副本的还原提交
  • 将该副本合并到功能分支中,然后将功能分支推送到git服务器。

现在,您的功能分支现在应该可以正常合并了。唯一的缺点是您的历史记录中会有一些额外的合并/还原提交。


为了防止进一步的混乱,我还创建了功能分支的“垃圾”副本,并将还原后的开发合并到其中。
jhhwilliams '19

谢谢!这是唯一真正说明如何做而不是说您不应该这样做的答案。真的很有帮助。
艾美奖

谢谢,这对我有很大帮助。:)
DanielStracaboško

11

要还原GIT中的还原,请执行以下操作:

git revert <commit-hash-of-previous-revert>

1
在我的工作分支中使用它还原还原,然后开发新的PR。现在,git可以查看先前还原的PR中的所有更改。谢谢。
丹斯坦

3

而不是使用的git-revert,你可以在已经使用这个命令devel分支扔掉(撤消)错误的合并提交(而不仅仅是恢复它)。

git checkout devel
git reset --hard COMMIT_BEFORE_WRONG_MERGE

这还将相应地调整工作目录的内容。注意

  • 将您的更改保存在development分支中(由于合并错误),因为它们也会被抹去git-reset。您指定为git reset参数的所有提交之后的所有提交都将消失!
  • 另外,如果您的更改已从其他存储库中提取,请不要执行此操作,因为重置将重写历史记录。

建议您git-reset在尝试此手册之前仔细研究手册页。

现在,重置后,您可以重新应用更改devel,然后执行

git checkout devel
git merge 28s

这将是一个真正的融合28sdevel像最初的一个(现在是从Git的历史擦除)。


8
对于不熟悉git并可能需要遵循以下说明的任何人:请谨慎组合reset --hardpush origin。另请注意,强行推入原籍可能会真正掩盖GitHub上的公开PR。
funroll

对于解决私有git服务器上的一些合并问题非常有用。谢谢!
mix3d

1
此技术+1。潜在地具有破坏性,但是如果明智地使用它可以为您省去很多头痛(和病史困扰)。
Siliconrockstar

1

当遇到相同的问题时,我才发现这篇文章。我发现上面的Wayyy有点令人恐惧,难以进行重设等。我最终将删除我不想要的内容,并且无法将其取回。

相反,我签出了我希望分支返回到例如的提交git checkout 123466t7632723。然后转换为分支git checkout my-new-branch。然后,我删除了我不再想要的分支。当然,这只有在您能够丢弃混乱的分支时才有效。


1
git reflog如果您稍后发现需要丢失的提交,则将在硬重置上为您提供几个月的保护。刷新日志仅限于您的本地存储库。
托德

1

我建议您按照以下步骤还原一个还原,例如SHA1。

git checkout develop #go to develop branch
git pull             #get the latest from remote/develop branch
git branch users/yourname/revertOfSHA1 #having HEAD referring to develop
git checkout users/yourname/revertOfSHA1 #checkout the newly created branch
git log --oneline --graph --decorate #find the SHA of the revert in the history, say SHA1
git revert SHA1
git push --set-upstream origin users/yourname/revertOfSHA1 #push the changes to remote

现在为分支创建PR users/yourname/revertOfSHA1


1
  1. 在原始合并之前的提交时创建新分支-称其为'develop-base'
  2. 在“开发基础”之上执行“开发”的交互式变基(即使它已经在最上面)。在交互式rebase期间,您将有机会删除合并提交和反转合并的提交,即从git历史记录中删除这两个事件

此时,您将拥有一个干净的'develop'分支,您可以像往常一样合并功能分支。


如果将开发分支与他人共享,则此方法将产生问题。
PSR
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.