有没有一种方法可以干净、轻松地撤消 git 合并?

Is there a way to cleanly and easily undo a git merge?

我读过 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 恢复 4pm -m 1,但是根据 manual:

这有问题

Usually you cannot revert a merge because you do not know which side of the merge should be considered the mainline. This option specifies the parent number (starting from 1) of the mainline and allows revert to reverse the change relative to the specified parent.

Reverting a merge commit declares that you will never want the tree changes brought in by the merge. As a result, later merges will only bring in tree changes introduced by commits that are not ancestors of the previously reverted merge. This may or may not be what you want.

那么,有没有一种方法可以彻底轻松地撤消 git 合并?

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

合并后:

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

myBranch 到 master 的合并应该给出:

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

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

如果您 reset --hard emaster 上,您将取回原始历史记录(上面的第一个)

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

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

I've read that doing git reset commitBeforeDoingMerge --hard would no undo the merge

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

假设您要将 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)

这是一个完美的撤消。

我仍然不确定你在做什么,但这不是 git merge 的工作方式。我会尝试重新创建您所做的,也许您可​​以发现不同之处。

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

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

正在将母版合并到测试中。 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

现在我们看到下午 2 点提交仅在 master 中,以确认仅测试的日志

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

这就是我合并和撤消合并的方式,请随时告诉我您所做的不同之处或我没有重新创建的地方,例如您需要它的方式。