有没有办法干净轻松地撤消 git 合并?

Posted

技术标签:

【中文标题】有没有办法干净轻松地撤消 git 合并?【英文标题】:Is there a way to cleanly and easily undo a git merge? 【发布时间】:2021-02-24 01:01:26 【问题描述】:

我读过 git reset commitBeforeDoingMerge --hard 不会撤消合并:

1pm-3pm This is my branch and I need to merge master into it
1pm-2pm This was master
1pm-2pm-3pm-4pm Merging ended up doing this, 4pm being the merge commit
1pm-2pm-3pm if This is the result if you do git reset 3pm --hard, because it does not undo the merge, it just goes back to that commit in the branch that was merged.

现在,另一个建议是做 git revert 4pm -m 1,但是根据manual 有问题:

通常您无法还原合并,因为您不知道哪一边 的合并应该被认为是主线。该选项指定 主线的父编号(从 1 开始)并允许还原 反转相对于指定父级的更改。

还原合并提交声明您永远不会想要树 合并带来的变化。结果,以后的合并只会 引入由非祖先的提交引入的树更改 先前还原的合并。这可能是也可能不是您想要的。

那么,有没有办法干净而轻松地撤消 git 合并?

【问题讨论】:

git reset --hard 将撤消合并。 (总是干净利落)但我认为你应该澄清你是如何得到“合并”的,因为合并应该至少有两个平行的分支而不是你的单行。 @ian 我更新了问题,也许现在更清楚了。 Git reset --hard 会将您带到该快照,但不会撤消对历史记录所做的更改。 【参考方案1】:

重置应该有效,但在 master 上,重置为 e:

合并后:

a-b-d  (mybranch)
  \
   c-e (master)

myBranch 到 master 的合并应该给出:

a-b---d  (mybranch)
  \    \
   c-e-f (master)

没有分支会列出 abcdef,只有 abcef (master)

如果您在masterreset --hard e,您将返回原始历史记录(上面的第一个)

如果您在 master 上 reset --hard d,则您已移动 master HEAD 但合并仍然存在:

a-b---d  (mybranch, master)
  \    \
   c-e-f

【讨论】:

我正在将 master 合并到我的分支中。我不明白你的答案,所以我更新了这个问题,也许它更清楚了。【参考方案2】:

我读过 git reset commitBeforeDoingMerge --hard 不会撤消合并

无论你在哪里读到,都是错误的。这正是撤消合并的方法。

假设您将branch 合并到master。所以我们在合并之前有这个:

A -- B -- C (master)
 \
  X -- Y (branch)

好的,所以我们 git checkout mastergit merge branch。结果是:

A -- B -- C -- D (master)
 \             |
  X -- Y (branch)

...其中 D 是合并提交,C 和 Y 作为其父项。

如果你现在说git reset --hard <SHA-of-C>,你又回到了这个:

A -- B -- C (master)
 \
  X -- Y (branch)

这是一个完美的撤消。

【讨论】:

【参考方案3】:

我仍然不确定你在做什么,但这不是git merge 的工作方式。我会尝试重现你所做的,也许你能发现其中的不同。

首先我创建了你的两个起始分支:

git log --oneline --graph --all
* 0593ba1 (HEAD -> test) 3pm
| * eba415c (master) 2pm
|/
* 7f9a804 1pm

将 master 合并到测试中。 git merge master -m "4pm"

git log --oneline --graph --all
*   6be609f (HEAD -> test) 4pm
|\
| * eba415c (master) 2pm
* | 0593ba1 3pm
|/
* 7f9a804 1pm

现在我们将测试重新设置为下午 3 点

git reset --hard 0593ba1
HEAD is now at 0593ba1 3pm
git log --oneline --graph --all
* 0593ba1 (HEAD -> test) 3pm
| * eba415c (master) 2pm
|/
* 7f9a804 1pm

现在我们看到 2pm commit 只在 master 中,确认一下 only test 的日志

git log --oneline
0593ba1 (HEAD -> test) 3pm
7f9a804 1pm

这就是我合并和撤消合并的方式,请随时告诉我你在做什么不同的地方,或者我没有重新创建你的例子,比如你需要它。

【讨论】:

我认为当我在脑海中混合撤消被推送的合并时,我感到困惑。所以我试图找到一种干净的方法来撤销它而不重写历史。 不用担心,很高兴为您提供帮助。如果您真的想在不重写历史记录的情况下撤消合并,您可以使用git revert -m <#parent> <sha> 来完成,但请注意阅读此内容,因为它有自己的pitfalls,我不确定这是一个更好的重写解决方案历史。

以上是关于有没有办法干净轻松地撤消 git 合并?的主要内容,如果未能解决你的问题,请参考以下文章

轻松清理 sinon 存根

text 边框的速记属性干净整洁,但是使用此边框SCSS Mixin,您可以轻松地向一侧添加边框或

如何在提交之前撤消“git add”?

优雅的使用git搭建项目环境教程--轻松拉取合并protected的分支

优雅的使用git搭建项目环境教程--轻松拉取合并protected的分支

如何使用Octoparse轻松抓取到网页数据