118

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.

8
  • 9
    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, 2015 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, 2015 at 11:35
  • 1
    @Dan I disagree: it is a different question and that the answer are similar does not change that.
    – Beginner
    Sep 10, 2015 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, 2015 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, 2015 at 13:58

3 Answers 3

130
+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

UPDATE: The following is relevant only on Emacs versions before 25.1, the following can cause problems on later versions, see https://github.com/magit/magit/issues/3897

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.

13
  • 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, 2015 at 11:32
  • 4
    For added clarification, note that smerge-ediff and vc-resolve-conflicts are the same thing.
    – phils
    Sep 9, 2015 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 Sep 11, 2015 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, 2015 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 Sep 14, 2015 at 4:47
52

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 (Edit: In newer Emacs, these are now labelled as UPPER=HEAD* and LOWER=<sha>*). The merged buffer is shown below (see screenshot).

A screenshot of the ediff 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!

5
  • 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, 2015 at 8:53
  • 2
    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, 2015 at 13:06
  • 7
    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, 2015 at 13:15
  • 1
    Is there a way to show 4 windows (ours, parent, theirs, workspace) like vimdiff? Jan 18, 2017 at 9:20
  • For me, the top two windows were labeled UPPER and LOWER rather than MINE and OTHER.
    – user650654
    Jul 9, 2020 at 5:33
14

If you happen to use Spacemacs, I'd recommend activating "smerge-transient-state", 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.

EDIT: Solution for those without Spacemacs, adapted from John Kitchin's scimax, which I take is based off of the spacemacs solution and Iqbal's accepted answer above.

(use-package hydra)
(use-package smerge
  :config
  (defhydra scimax-smerge (:color red :hint nil)
    "
Navigate       Keep               other
----------------------------------------
_p_: previous  _c_: current       _e_: ediff
_n_: next      _m_: mine  <<      _u_: undo
_j_: up        _o_: other >>      _r_: refine
_k_: down      _a_: combine       _q_: quit
               _b_: base
"
    ("n" smerge-next)
    ("p" smerge-prev)
    ("c" smerge-keep-current)
    ("m" smerge-keep-mine)
    ("o" smerge-keep-other)
    ("b" smerge-keep-base)
    ("a" smerge-keep-all)
    ("e" smerge-ediff)
    ("j" previous-line)
    ("k" forward-line)
    ("r" smerge-refine)
    ("u" undo)
    ("q" nil :exit t))

  (defun 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)
          (scimax-smerge/body))))))
4
  • How can I install smerge-transient-mode does it have an alternative for native emacs?
    – alper
    Mar 8, 2022 at 16:25
  • Sorry, it seems that was a typo. What you really wanted was smerge-transient-state, which is a hydra defined by spacemacs. But with that said, I've expanded the answer to include a non-spacemacs solution.
    – Daniel
    Mar 9, 2022 at 0:14
  • Thanks I was hoping to find a solution for native emacs, maybe this could help emacs.stackexchange.com/questions/20636/…
    – alper
    Mar 9, 2022 at 9:24
  • right, just substitute the hydra for custom keybindings
    – Daniel
    Mar 9, 2022 at 15:58

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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