如何使 Git 接受未要求的已取消合并?

How to make Git honor a cancelled merge that was not asked for?

我已经 运行 遇到这种情况大约 3 到 4 次了。有时,Git 会想要执行合并。它发生在响应 git commit <filename> -m <message> 后跟 git push.

我知道合并即将发生,因为 Git 启动了消息的编辑器。所以我执行 CTRL + C 试图阻止它。

我真的不在乎为什么或是什么让我进入了这个州。当事情必须合并时,我只想停下来。我希望它发生,因为它会污染签到,污染历史记录,有时还会添加尚未准备好的内容。

但是,我看到 Git 仍在执行合并。授予:Merge branch 'master' of https://github.com/weidai11/cryptopp.

一旦我 CTRL + C,合并应该 而不是 继续。如何使 Git 接受未要求的已取消合并?

git push 如果远程上有任何新的提交,但您的本地分支上还没有,通常应该会失败。

为了推送,你不能错过服务器的任何提交。

在您发布的示例中,您似乎在两台不同的机器或两个不同的本地副本上提交了 d091b80217cb1f

当您尝试推送 217cb1f 时,服务器已经有 d091b80,而您的本地分支中没有。

在 git 可以推送到服务器之前,您需要从服务器拉取其他提交。

通常这是您手动执行的操作。出于某种原因,您的 git push 似乎以某种方式调用了 git pull.

虽然我找不到启用这种行为的特定选项(也不建议这样做),但我可以看到有些人希望 git 以这种方式行事。
如果您正在为 git 或您的 shell 使用其他人的配置文件,我会看看是否有任何可能导致这种奇怪行为的东西。

那么合并提交一般是怎么产生的呢?抛开 push 命令的奇怪行为,假设你手动完成了 pull:

Git 拉取导致意外的合并提交

Git pull 做两件事:

  • 它获取遥控器
  • 它将远程分支合并到您的本地分支

如果您的本地机器上没有新的提交,那么您有一个线性历史记录,来自服务器的更改将通过快进包含在内。这意味着您的本地分支将简单地设置为与远程分支相同的版本(想象一下只需要在一条路上走得更远一点)。

假设您在本地分支上进行了提交,而同事(或您自己在另一台机器上)将另一个更改推送到服务器上的远程分支:
这两个分支现在已经分道扬镳(想象一条道路在这里一分为二)。当 git pull 尝试将它们合并在一起时,它需要进行合并提交(可视化两条道路合并为一条)。

或者您可以 git pull --rebase 或在 git 配置中设置相应的设置。这将告诉 git 将您的本地更改应用到服务器的“路的尽头”。
但请注意,变基会使冲突解决变得更加困难,并且通常比合并更复杂。


尽早推送可以最大限度地减少分支转移。 如果您还没有进行任何新的本地提交,那么在您进行提交之前 pull 从服务器 进行更改也是一个好主意。这样,您就可以防止您的分支转移。

一个好的方法是:

git stash       # This saves your uncommitted changes away as a draft
git pull        # Gets new commits from the remote
git stash pop   # Restores your uncommitted changes

中止合并,同时已经编辑了提交消息

  1. 清空编辑器缓冲区中的提交消息,保存并退出。
    任何评论(以 # 为前缀)都可以保留,因为它们在评估之前被 git 删除(尽管可以在配置中更改此行为)。
    如果您是 vim 用户,我相信 dG:x 是最快的方法。
  2. 运行 git merge --abort
    这将使 git 尝试恢复工作副本的合并前状态。
    此命令在 git 1.7.4 或更高版本中可用。有关详细信息,请查看 man entry for git-merge.

为什么 Ctrl+C 没有达到预期效果

简单地按下 Ctrl+C 将(在大多数情况下,如果不是所有情况下)不会按照您的预期进行。当 git 启动命令行编辑器(例如 vim、emacs 或 nano)时,该编辑器成为 shell.

的 active/current 进程

Ctrl+C会向当前进程发送一个SIGINT信号。意思是,将 SIGINT 发送给您的编辑而不是 git.

如果您使用的编辑器在接收到该信号时失败(退出并且 returns 退出代码不是 0),那可能(尽管我没有测试过)中止提交。
与编辑器一样,它会保存一个空缓冲区并退出。
如果您配置 git 以启动 GUI 编辑器,它将保留在最前面的进程并且 SIGINT 仍应中止提交。

请注意,在所有这三种情况下,您的工作副本中可能会有来自其他分支的更改,您需要清理它们(请参阅第 2 步)。


就我个人而言(以及大量 git 用户),这种行为是我希望 git 得到的。如果您有不同的看法,您可以提交错误报告或功能请求 here.