(or emacs irrelevant)

Setting up Ediff

Once you make Ediff bearable, it becomes wonderful. At least this was my experience. It's a very good tool, but some of the defaults look very poor to me.

Customizing the customize

First of all, I'll list a macro that I've started to use for setting custom variables:

(defmacro csetq (variable value)
  `(funcall (or (get ',variable 'custom-set)
                'set-default)
            ',variable ,value))

This macro I've put together myself after searching though the code base and not finding something similar; custom-set-variables comes close to what I want, or maybe custom-initialize-changed. Basically all I want is a setq that is aware of the custom-set property of a variable. If you know such a macro, please let me know.

Changing some Ediff options

Now, that I've explained the custom setter (by the way, using custom-set-variables is absolutely equivalent to csetq), here are my changes:

  1. Don't use the weird setup with the control panel in a separate frame. I can manage windows in Emacs much better than my desktop (Unity or Gnome Shell) can manage the Emacs frames.

    (csetq ediff-window-setup-function 'ediff-setup-windows-plain)
    
  2. Split the windows horizontally instead of vertically. This way, it's much easier to follow the changes.

    (csetq ediff-split-window-function 'split-window-horizontally)
    
  3. Ignore white space. I don't write a lot of Python, so I don't care about the white space in the diffs. At the same time, I re-format any LISP code that I edit to my liking, and I want to see only the important changes in the diff, and not the whitespace nonsense.

    (csetq ediff-diff-options "-w")
    

Changing some Ediff key bindings

This is just the standard stuff that I like to do for each mode that does not self-insert: assign j to move down, and k to move up.

(defun ora-ediff-hook ()
  (ediff-setup-keymap)
  (define-key ediff-mode-map "j" 'ediff-next-difference)
  (define-key ediff-mode-map "k" 'ediff-previous-difference))

(add-hook 'ediff-mode-hook 'ora-ediff-hook)

Restoring the windows after Ediff quits

When you quit an Ediff session with q, it just leaves the two diff windows around, instead of restoring the window configuration from when Ediff was started. Here's the (slightly hacky) code to restore the old window configuration:

(winner-mode)
(add-hook 'ediff-after-quit-hook-internal 'winner-undo)

List of ways that I use to invoke Ediff

from magit

In 80% of the cases, I call Ediff with e (magit-ediff) from magit-status-mode. This gives me a better overview of the changes, especially when I want to revert stuff with either a (ediff-copy-A-to-B) or b (ediff-copy-B-to-A). Probably with a, since magit seems to consistently put the @{index} file into the A diff window, and the current file into the B window.

So if I'm looking at a diff (to which I navigated with j/k), I can revert it with a. At this point, the diff region in the current file will become equal to that of the index file. But it will not be saved yet. If I want to save the current file in the B window, I can do it with wb (ediff-save-buffer). After a revert, it's also useful to call !(ediff-update-diffs), which will remove the zero-length diffs and update the diff-count in the mode-line.

other methods

  1. ediff-buffers will diff two (different) buffers. If you happen to have only two windows open with the appropriate buffers, you get them as defaults and can choose them quickly with RET RET.
  2. ediff-files is similar, but works on files instead. I like to just mark the appropriate files in dired with m, then they also get auto-selected by ediff-files.
  3. ediff-current-file is useful to see the unsaved changes to the current file. I rarely use it, since I have a compulsion to save every file every chance I get. There is little hope to recover from this addiction, unless someone implements an analogue of guru-mode that annoys you when you try to save a file. Actually, it's not a bad idea - C-x C-s:

Oleh, you have saved this file 40 times in the last hour; the last save was 0 minutes 34 seconds ago; since then, you've changed 27 bytes of information. Are you sure you want to save [y/N]?