tags:

views:

939

answers:

3
+6  Q: 

ediff as mergetool

I would like to be able to use ediff with "git mergetool".

I found some patches that alter the source code, which I don't want to do. Instead, I'd like to add ediff support with my .gitconfig.

I know git has builtin support for emerge, but I prefer ediff.

I attempted to add these lines to my .gitconfig:

[mergetool "ediff"]
    cmd = emacs --eval "(ediff-merge-files-with-ancestor \"$LOCAL\" \"$REMOTE\" \"$BASE\" nil \"$MERGED\")"

But when I try to run this with "git mergetool --tool=ediff", I get this:

eval: 1: Syntax error: "(" unexpected

What am I doing wrong?

+4  A: 

Aside from the git vs bzr issue I identified in my comment above, I was able to confirm that you need to escape the parens as in

 cmd = emacs --eval "\\(ediff-merge-files-with-ancestor \"$LOCAL\" \"$REMOTE\" \"$BASE\" nil \"$MERGED\"\\)"

Note the double backslash characters. I kind of understand that they are needed (rather than a single one) to get through both the sh/bash quoting AND the emacs startup quoting mechanisms. I'll leave it to someone with a better grasp of Emacs and shell quoting to explain the gory details.

-pmr

pajato0
+5  A: 

I use a a more complicated command. As far as I remember I got it from this thread http://kerneltrap.org/mailarchive/git/2007/6/28/250230 (probably the same as what you are revering to).

[mergetool.ediff]
    cmd = emacs --eval \"
(progn
  (defun ediff-write-merge-buffer ()
    (let ((file ediff-merge-store-file))
      (set-buffer ediff-buffer-C)
      (write-region (point-min) (point-max) file)
      (message \\\"Merge buffer saved in: %s\\\" file)
      (set-buffer-modified-p nil)
      (sit-for 1)))
  (setq ediff-quit-hook 'kill-emacs
        ediff-quit-merge-hook 'ediff-write-merge-buffer) 
  (ediff-merge-files-with-ancestor \\\"$LOCAL\\\" \\\"$REMOTE\\\"
                                   \\\"$BASE\\\" nil \\\"$MERGED\\\"))\"

Note that I have split this across several lines to increase readability. In practice you have the whole argument to the --eval option on one line.

I usually use emacsclient to edit e.g. commit messages. The above mergetool configuration unfortunately does not use emacsclient, and when I tried to get it to work with emacsclient I ran in to various problems including the fact that emacsclient returned right away.

But you just reminded me of that issue, so I might work on fixing that problem soon. However if someone else already found a solution that would be great of course ;-)

tarsius
This worked perfectly. Thanks.
mathepic
+1  A: 

Here's a variant of tarsius's setup. It handles when the ancestor file $BASE doesn't exist, and it allows you to abort the merge without trashing git's state about the conflict (by not automatically saving on exit). It also has newlines backslashed so that you can keep the formatting.

[mergetool.ediff]
    cmd = emacs --eval \" \
(progn \
  (setq ediff-quit-hook 'kill-emacs) \
  (if (file-readable-p \\\"$BASE\\\") \
      (ediff-merge-files-with-ancestor \\\"$LOCAL\\\" \\\"$REMOTE\\\" \
                                       \\\"$BASE\\\" nil \\\"$MERGED\\\") \
      (ediff-merge-files \\\"$LOCAL\\\" \\\"$REMOTE\\\" nil \\\"$MERGED\\\")))\"
tresi