如何在Emacs中合并Git冲突


84

我最近的Git合并导致了许​​多冲突。我当前的方法是搜索“ <<<”的下一次出现,然后通过标准文本编辑执行合并。

问题:Emacs是否可以使用Git中有关我的版本,其版本和文件基本版本的信息来支持合并?


编辑:此问题的范围不同于此相关问题的范围,因为它不仅限于调用ediff。


7
如果要使用Magit,可以加载状态缓冲区,然后按e显示为冲突的文件。Magit将启动ediff进行合并,然后提示您确认更改,然后可以暂存合并的文件。
wvxvw 2015年

@Beginner:另外3个人认为这是重复的,而我是最后一次投票。原因:引用的另一个线程给出了相同的答案(smergevc-resolve-conflict,以及on ediff),并且使用时间更长。我同意第一个线程可以使用更好的标题。

@丹我不同意:这是一个不同的问题,并且答案相似不会改变这一点。
初级

1
@IqbalAnsari:我认为另一个线程需要一个更好的标题,以便人们可以更轻松地找到它。实际上,我认为Beginner的主题名称将非常适合。但是,让我们稍等一下,看看人们是否要重新打开此线程。如果没有,我赞成将第一个线程重命名为Beginner的标题。

1
而且,就其价值而言,我认为这是一个具有良好答案的好问题。只是我也认为它是重复的-但其他人可能不同意(关于重复)。

Answers:


86

您可能只想尝试smerge-mode打开冲突的文件并尝试一下M-xsmerge-modeRET。它将突出显示所有冲突地区。它还添加了键绑定以轻松解决冲突,请查阅文档资料C-hfsmerge-modeRET以了解它们。

默认前缀

我找到了smerge-mode C-c^麻烦的默认前缀,所以我将其更改为 C-cv

(setq smerge-command-prefix "\C-cv")

重要的键绑定

对我而言,最重要的绑定是:

smerge-next势必会smerge-command-prefixn转移到下一个冲突。

smerge-previous势必会smerge-command-prefixp陷入先前的冲突。

smerge-keep-current一定要smerge-command-prefixRET保持光标所在的版本。

smerge-keep-mine一定要smerge-command-prefixm保留您的更改。

smerge-keep-other势必会smerge-command-prefixo保留其他更改。

smerge-ediff势必将smerge-command-prefixE启动ediff会话以合并冲突。这与vc-resolve-conflicts(感谢@phils和@Malabarba指出这一点)相同。

自动启用烟雾模式

更新: 以下内容仅与之前的Emacs版本相关25.1,以下内容可能在更高版本上引起问题,请参阅https://github.com/magit/magit/issues/3897

此外,smerge-mode当您访问带有冲突标记的文件/缓冲区时,您可能会对自动启用感兴趣,可以使用如下所示的方法来实现此目的

(defun my-enable-smerge-maybe ()
  (when (and buffer-file-name (vc-backend buffer-file-name))
    (save-excursion
      (goto-char (point-min))
      (when (re-search-forward "^<<<<<<< " nil t)
        (smerge-mode +1)))))

(add-hook 'buffer-list-update-hook #'my-enable-smerge-maybe)

请注意,我使用的buffer-list-update-hook不是,find-file-hook因为大多数情况下我不会在已经在emacs中打开的缓冲区中发生冲突,因此find-file-hook没有帮助。

还要检查此答案中提到的其他方法


1
(1)不要忘记smerge-ediff(2)您正在使用哪个Emacs版本?在当前的emacs master分支上,smerge自动打开。(3)为什么用buffer-list-update-hook代替find-file-hook
马拉巴巴

为了进一步说明,请注意smerge-ediffvc-resolve-conflicts是同一件事。
菲尔斯2015年

@Malabarba 1)我确实提到smerge-mode过,其键绑定已记录在其文档中。也许我可以在这里引用手册的完整性。感谢您的反馈。2)我使用的是v24.5,尽管有时我会尝试使用master分支,但是我不记得有自动被转过的信息(这是最近的变化吗?)。3)这是因为大多数时候我在已经打开的缓冲区中遇到冲突,在这种情况下,我需要显式打开smerge-mode
Iqbal Ansari 2015年

@IqbalAnsari是否有任何原因一直没有smerge-mode启用?直到被调用,它并不会做很多事情。
PythonNut

@PythonNut好问题,不幸的是我没有答案,因为我从未一直尝试保持启用状态,尽管值得一试
Iqbal Ansari 2015年

32

编辑:由于此答案获得的投票比我预期的要多,所以我扩大了一点。

为了补充@IqbalAnsari的答案,您还可以使用vc-resolve-conflicts(正如其他人所提到的,它是的别名smerge-ediff)。这将启动ediff界面。左边是第一个合并父对象,右边是第二个合并父对象。它们在modeline上分别用MINE和标记OTHER。合并的缓冲区如下所示(请参见屏幕截图)。

<code> ediff </ code>界面的屏幕截图

键绑定

  • 浏览n和之间的冲突p
  • a接受版本b
  • /看看祖先
  • 使用退出 ediff会话q

other-window如果解决冲突比接受版本更复杂,您还可以使用和手动编辑导航到合并的缓冲区。完成后,您可以照常保存缓冲区并退出Emacs。要获得更多帮助,只需?ediff会话期间使用,那里有一堆非常有用的命令。我仍然不知道他们一半会做什么!


2
这是IMO最好的方法。我将它绑定到C-x v <,尽管在实践中我更可能使用Magit调用它(根据wvxvw的评论)。
phils 2015年

1
由于2000年vc-resolve-conflict是的别名smerge-ediff,顾名思义,该别名开始了Ediff会话,而不是Emerge会话。顺便说一句,ediff.el承认emerge.el的影响的库标题然后继续说:“ Ediff的当前版本取代了Emerge。它提供了一个出色的用户界面,并具有Emerge中未发现的许多主要功能。特别是,它可以进行修补,以及2向和3向文件比较,合并和目录操作。”
tarsius

6
还要注意magit-ediff-resolveEme在有冲突的文件上)smerge-ediff内部使用。但是,它确实覆盖了,ediff-quit-hook以提供更好的会话完成体验。它没有告诉您可以保存“缓冲区”(有多个缓冲区),而是询问您是否要保存缓冲区(同时显示其名称)。
tarsius

有没有办法显示像vimdiff这样的4个窗口(我们的,父的,他们的,工作区)?
user1133275

9

如果您碰巧使用了Spacemacs,我建议您激活“ smerge-transient-mode”,它会弹出一个hydra菜单,其中包含所有可能的smerge命令。

为此,只需调用Mx spacemacs/smerge-transient-state/body,这是默认分配给的SPC-g-r

这是屏幕截图:

在此处输入图片说明

然后,编辑文件应该很直观:

  1. n转到下一个大块。
  2. 选择一个合并动作
  3. 重复直到完成。
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.