【问题标题】:Re-doing a reverted merge in Git在 Git 中重新进行还原合并
【发布时间】:2021-09-03 22:56:45
【问题描述】:

我在这里遇到了一点问题:我在 Git 中有一个特定于问题的分支 28s,我将它合并到一般的 develop 分支中。原来我做得太快了,所以我使用 git-revert 撤消合并。然而,现在是时候将28s 合并到develop 中了,但是 git-merge 命令看到了原来的合并,并高兴地宣布一切都很好,分支已经合并了。现在我该怎么做?创建一个'Revert "Revert "28s -> develop""' 提交?这似乎不是一个好方法,但我目前无法想象其他任何方法。

树结构是什么样子的:

【问题讨论】:

标签: git git-merge git-revert


【解决方案1】:

您必须“还原还原”。取决于您如何还原原始版本,它可能不像听起来那么容易。看official document on this topic

---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 会不假思索地做到这一点。

所以从技术角度来看,还原合并并没有错, 但是从工作流程的角度来看,您通常应该尝试这样做 避免

如果可能的话,例如,如果您发现一个已合并的问题 进入主树,而不是恢复合并,尝试真的努力

  • 将问题分成你合并的分支,然后修复它,
  • 或尝试恢复导致它的单个提交。

是的,它更复杂,不,它并不总是有效(有时 答案是:“哎呀,我真的不应该合并它,因为它不是 准备好了,我真的需要撤消所有的合并”)。那么你 确实应该恢复合并,但是当您想重新进行合并时,您 现在需要通过还原还原来做到这一点。

【讨论】:

  • 良好的链接 (+1)。我冒昧地复制了您回答中的部分文件,以便让读者立即看到这种情况下的相关选项。如果您不同意,请随时回复。
  • 我们刚刚遇到了一个需要这样做的案例,发现乐趣还不止于此。这是一个长期运行的分支,被合并了,所以我们需要继续更新它。我的方法是:tech.patientslikeme.com/2010/09/29/…
  • @jdwyah 这似乎是一个断开的链接,但听起来很有趣。这是一个 archive.org 镜像,但缺少图像:web.archive.org/web/20111229193713/http://…
  • 我也关注了@jdwyah 的帖子。效果很好,我只会将 'git revert SHA_OF_THE_MERGE_REVERSION' 更改为 'SHA_OF_THE_REVERT_MERGE' 或类似的东西。
【解决方案2】:

假设你有这样的历史

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

其中 A、B 提交失败,W - 是 M 的恢复

所以在我开始修复发现的问题之前,我会挑选 W 提交到我的分支

git cherry-pick -x W

然后我在我的分支上恢复 W 提交

git revert W 

之后我可以继续修复。

最终的历史可能如下所示:

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

当我发送 PR 时,它会清楚地显示 PR 是 undo revert 并添加一些新的提交。

【讨论】:

  • 这看起来可能会有所帮助,但在细节上非常稀疏(最后一张图中的 C、D 是什么),这比有用更令人沮丧
  • @Isochronous C 和 D 似乎是修复 A 和 B 引入的问题的提交。
  • @Thomas 完全正确
  • 在这种情况下使用 PR 突出显示是很好的,因为它可以在合并回 master 之前提供最终的“健全性检查”。
  • 使用你为什么要从原来的 W 重启你的分支?即,让您的主题从 W 继续,W` 后跟 C 和 D?这消除了一些重复
【解决方案3】:

要在不过多破坏您的工作流程的情况下还原还原:

  • 创建本地垃圾副本开发
  • 在本地开发副本上恢复恢复提交
  • 将该副本合并到您的功能分支中,并将您的功能分支推送到您的 git 服务器。

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

【讨论】:

  • 为了防止进一步混淆,我还创建了我的功能分支的“垃圾”副本,并将恢复的开发合并到其中。
  • 谢谢!这是唯一真正解释如何做而不是说你不应该这样做的答案。真的很有帮助。
  • 谢谢,这对我很有帮助。 :)
  • 这是一个非常直接的答案。
  • 谢谢,我的情况很简单,所以这完全为我完成了工作。如果您处于更复杂的情况,其他答案也很棒。
【解决方案4】:

要在 GIT 中恢复还原:

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

【讨论】:

  • 在我的工作分支中使用它来还原还原,然后开发新的 PR。现在 git 会看到先前 PR 中已恢复的所有更改。谢谢。
【解决方案5】:

您可以在devel 分支中使用此命令来丢弃(撤消)错误的合并提交(而不仅仅是恢复它),而不是使用git-revert

git checkout devel
git reset --hard COMMIT_BEFORE_WRONG_MERGE

这也会相应​​地调整工作目录的内容。 小心

  • 保存您的更改在开发分支(因为错误的合并),因为他们 也将被git-reset 删除。在您指定为之后的所有提交 git reset 参数将消失!
  • 另外,如果您的更改已从其他存储库中提取,请不要这样做 因为重置会重写历史记录。

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

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

git checkout devel
git merge 28s

这将是从 28sdevel 的真正合并,就像最初的那样(现在是 从 git 的历史中删除)。

【讨论】:

  • 对于不太熟悉 git 并且可能想要遵循这些说明的任何人:小心结合 reset --hardpush origin。另请注意,强制推送到原点可能真的会破坏 GitHub 上的开放 PR。
  • 对于修复私有 git 服务器上的一些合并问题非常有帮助。谢谢!
  • 这项技术+1。具有潜在的破坏性,但如果应用得当,可以为您省去很多麻烦(以及混乱的历史记录)。
【解决方案6】:

我建议您按照以下步骤还原还原,例如 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

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

【讨论】:

    【解决方案7】:

    我刚刚在遇到同样的问题时发现了这篇文章。我发现上面的方式让我害怕做重置困难等。我最终会删除我不想删除的东西,并且无法取回它。

    相反,我检查了我希望分支返回到的提交,例如git checkout 123466t7632723。然后转换为分支git checkout my-new-branch。然后我删除了我不再想要的分支。当然,这只有在你能够扔掉你搞砸的分支时才有效。

    【讨论】:

    • git reflog 将在几个月的硬重置中保护您,以防您以后发现需要丢失的提交。 reflog 仅限于您的本地存储库。
    【解决方案8】:
    1. 在原始合并之前在提交时创建新分支 - 将其称为“develop-base”
    2. 在“develop-base”之上执行“develop”的交互式变基(即使它已经在顶部)。在交互式 rebase 期间,您将有机会同时删除合并提交和反转合并的提交,即从 git 历史记录中删除这两个事件

    此时,您将拥有一个干净的“开发”分支,您可以像往常一样将您的功能分支合并到该分支。

    【讨论】:

    • 如果develop分支与其他人共享,这种方法会产生问题。
    • 这可能会通过翻转它并强制 rebase 在相反方向来改善。从已恢复的分支中获取更改并在恢复的顶部重播它们以生成一个可以在合并下游合并的新分支,您将获得一个看起来稍微干净的历史记录,而不是相当难以遵循的恢复恢复。
    猜你喜欢
    • 1970-01-01
    • 2022-12-01
    • 2021-10-02
    • 1970-01-01
    • 2012-06-06
    相关资源
    最近更新 更多