One of the more useful programs in the developer’s toolkit is diff. This little utility compares two files and gives you just the differences (what changed) between them. Evey version control system in the world is ultimately based on diffs.

One way I commonly use it, is to see what I’ve changed in a file or a set of files. Let me clarify. I put everything in version control. Even tiny little programs that I’m tempted to throw away are in version control. Being able to use diff between my modified file and the previous version is a major reason for doing so.

Now, if I told you to quit your editor and run diff in a terminal, I wouldn’t be surprised if you decided to beat me with a clue stick. You should NEVER leave your editor. If you do, you don’t know how to use your editor, or your editor is not powerful enough. If your problem is the latter, you should switch to Emacs right now. Otherwise, keep reading, I can help you.

Depending on what version control system you use, you should modify the commands given below. I use BitKeeper (well, duh!), so all my examples will use that one.

To start with, stick this in your .emacs:

(defun bk-diffs ()
  "Get diffs between current edited buffer and checked in revision"
  (interactive)
  (let* ((filename (buffer-file-name (current-buffer)))
	(newbuf (get-buffer-create
		 (format "%s diffs"
			 (if filename (buffer-name) default-directory)))))
    (set-buffer newbuf)
    (if buffer-read-only
	(toggle-read-only))
    (erase-buffer)
    (insert
     (shell-command-to-string
      (if filename (format "bk diffs -uph %s" filename) "bk -r diffs -uph")))
    (switch-to-buffer-other-window newbuf)
    (diff-mode)
    (beginning-of-buffer)
    (diff-hunk-next)
    (toggle-read-only)
    newbuf))

Now, whenever you are in a file and want to modify it, all you need to do is run the command bk-diffs and you’ll get something like this:

Emacs diff mode screenshot
Emacs diff mode screenshot

Cool, eh?

The command is also context sensitive, so if you run it from a buffer where you’re not editing a file, e.g. a dired buffer or a shell buffer, it will run a recursive diff and give you diffs for all the files. I use this all the time when I go back to repositories I haven’t touched in a while. It’s my “what the hell was I doing?” command. The output looks something like this:

Emacs diff mode screenshot 2
Emacs diff mode screenshot 2

That’s not all. I have more tricks for you. First of all, navigation:

n or M-n

Move to the next hunk

p or M-p

Move to the previous hunk

M-N

Move to the next file

M-P

Move to the previous file

If you are an old school hacker and would rather see context diffs than unified diffs, you can hit C-c C-d while in the diffs buffer. To go back to unified diffs, hit C-c C-u.

There are also key strokes for going back to the source file from the diff buffer. Pressing kbd:[Enter] or M-o or C-c C-c will take you to the equivalent line (or thereabouts) in the source file from which the diff was taken.

Ok, that is useful, but I see you’re not blown away. The truth is, I saved the best part for last. Once you’re walking the diffs one by one, you can also press C-c C-a to either apply, or revert a hunk! How cool is that eh?

This last feature is something I use all the time to clean up a file before checking it in. E.g. I sometimes have a bunch of debug code or comments to myself that need to be removed before checking the file in. Rather than review the file by hand, I can go through the diffs and use the quick navigation that emacs provides for doing the clean up.

Finally, if you are a CVS user (I’m sorry, really. You should switch to something else), you can probably still use it inside vc-mode, hit C-x v = to get the diffs and try the keystrokes I mentioned.