My recent Git merge has resulted in a large number of conflicts. My current approach is to search for the next occurence of '<<<' and then perform the merge by standard text editing.

Question: is there a way Emacs can support merging using the information availabe in Git about my version, their version and the base version of the file?


Edit: This question has a different scope than this related question, since it is not limited to invoking ediff.

  • 5
    If you were to use Magit, you could load up the status buffer and then press e on files shown as conflicting. Magit would launch ediff to do the merging and prompt you afterwards to confirm your changes, then you could stage the merged file. – wvxvw Sep 9 '15 at 8:27
  • @Beginner: 3 other people thought it was a duplicate, and I was the last vote. Why: the other thread cited gives the same answers (smerge and vc-resolve-conflict, as well as one on ediff) and has been around longer. I agree that the first thread could use a better title, though. – Dan Sep 10 '15 at 11:35
  • @Dan I disagree: it is a different question and that the answer are similar does not change that. – Beginner Sep 10 '15 at 11:59
  • 1
    @IqbalAnsari: I think the other thread needs a better title so people can find it more easily. In fact, I think Beginner's thread title would be great for it. However, let's wait just a little bit to see if people want to reopen this thread. If not, I'd be in favor of renaming the first thread with Beginner's title. – Dan Sep 10 '15 at 13:57
  • 1
    And for what it's worth, I think this is a good question with good answers. It's just that I also think it's a duplicate -- but others may not share that opinion (about the duplication, that is). – Dan Sep 10 '15 at 13:58
up vote 70 down vote accepted
+50

You might want to try out smerge-mode just open the conflicted file and do M-xsmerge-modeRET. It will highlight all the conflicted regions. It also adds keybindings to easily resolve the conflicts, consult its documenation C-hfsmerge-modeRET to know them.

Default prefix

I find the default prefix for smerge-mode C-c^ cumbersome so I have changed it to C-cv

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

Important keybindings

For me the most important bindings are:

smerge-next bound to smerge-command-prefixn to move to next conflict.

smerge-previous bound to smerge-command-prefixp to move to previous conflict.

smerge-keep-current bound to smerge-command-prefixRET to keep the version the cursor is on.

smerge-keep-mine bound to smerge-command-prefixm to keep your changes.

smerge-keep-other bound to smerge-command-prefixo to keep other changes.

smerge-ediff bound to smerge-command-prefixE to start an ediff session to merge the conflicts. This is same as vc-resolve-conflicts (thanks @phils and @Malabarba for pointing this out).

Enabling smerge-mode automatically

Additionally you might be interested in automatically enabling smerge-mode when visiting a file/buffer with conflict markers you can use something like the following to achieve this

(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)

Note that I am using buffer-list-update-hook and not find-file-hook since most of the times I get conflicts in a buffer which is already open in emacs in which case find-file-hook is of no help.

Also check other methods mentioned in this answer

  • 1
    (1) Don't forget smerge-ediff. (2) What Emacs version are you on? On the current emacs master branch, smerge turns on automatically. (3) Why are you using buffer-list-update-hook instead of find-file-hook? – Malabarba Sep 9 '15 at 11:32
  • For added clarification, note that smerge-ediff and vc-resolve-conflicts are the same thing. – phils Sep 9 '15 at 11:55
  • @Malabarba 1) I did mention that smerge-mode's keybindings are documented in, its documentation. Maybe I can quote the manual here for completeness. Thanks for the feedback. 2) I am on v24.5, though I do try out master branch sometimes, I do not remember smerge being turned automatically (is it a recent change?). 3) That is because most of the times I get conflicts in already open buffers, in which case I would need to explicitly turn on smerge-mode – Iqbal Ansari Sep 11 '15 at 3:01
  • @IqbalAnsari is there any reason to not have smerge-mode enabled all the time? Perhaps it doesn't do much until invoked. – PythonNut Sep 14 '15 at 3:45
  • @PythonNut Good question, unfortunately I don't have an answer since I never tried keeping it enabled all the time, its worth trying out though – Iqbal Ansari Sep 14 '15 at 4:47

Edit: since this answer got more upvotes than I expected, I expanded it a bit.

To supplement the answer by @IqbalAnsari, you could also use vc-resolve-conflicts (as mentioned by others, it is an alias to smerge-ediff). This will start the ediff interface. On the left will be the first merge parent, and the second merge parent on the right. They are labelled on the modeline with MINE and OTHER respectively. The merged buffer is shown below (see screenshot).

A screenshot of the <code>ediff</code> interface

Keybindings

  • Navigate through the conflicts with n and p.
  • Accept versions with a or b.
  • Look at the ancestor with /!
  • Quit the ediff session with q.

You can also navigate to the merged buffer with other-window and hand-edit in case resolving a conflict is more complicated than accepting a version. When you are done, you can save the buffer and quit Emacs as usual. For more help, just use ? during the ediff session, there are a whole bunch of very useful commands in there. I still don't know what half of them do!

  • 2
    This is the nicest method IMO. I have it bound to C-x v < , although in practice I'm more likely to be invoking it with Magit (as per wvxvw's comment). – phils Sep 9 '15 at 8:53
  • 1
    Since the year 2000 vc-resolve-conflict is an alias for smerge-ediff, which as the name suggests starts an Ediff session, not an Emerge session. By the way, the library header of ediff.el acknowledges emerge.els influence and then goes on saying " The present version of Ediff supersedes Emerge. It provides a superior user interface and has numerous major features not found in Emerge. In particular, it can do patching, and 2-way and 3-way file comparison, merging, and directory operations." – tarsius Sep 11 '15 at 13:06
  • 6
    Also note that magit-ediff-resolve (Em or e on a file with conflicts) uses smerge-ediff internally. It does however override the ediff-quit-hook to provide a slightly better session finishing experience. Instead of telling you that you could save "the buffer" (there are several buffers), it asks you whether you want to save the buffer (while showing you its name). – tarsius Sep 11 '15 at 13:15
  • Is there a way to show 4 windows (ours, parent, theirs, workspace) like vimdiff? – user1133275 Jan 18 '17 at 9:20

If you happen to use Spacemacs, I'd recommend activating "smerge-transient-mode", which brings up a hydra menu with all possible smerge commands.

To do that, simply call M-x spacemacs/smerge-transient-state/body, which is per default assigned to SPC-g-r.

Here's a screenshot:

enter image description here

Editing your file should then be intuitive:

  1. Press n to go to the next hunk.
  2. Choose a merge action.
  3. Repeat until done.

Your Answer

 
discard

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Not the answer you're looking for? Browse other questions tagged or ask your own question.