How can I diff a single file with magit?

Solution 1:

Magit enables you to "review and commit each of the files separately" directly from the magit-status buffer, without the need for any separate diff buffers.

You just expand the file(s) you're interested in (with TAB, which shows you the diff for the file at point); then you can stage the bits of it that you want to commit (either the whole file, or individual hunks, or even a marked region) with s to stage (or u to unstage). Repeat for all the changes involved in that commit and, once everything necessary has been staged, press c to begin the commit.

You might prefer the visibility cycling behaviour you get by using C-TAB (repeatedly) instead of the simple toggle you get by default with TAB.


If you really do want to view the diff for a file in a separate buffer, you can do that from the file's buffer by calling magit-diff-buffer-file directly, or using the "diff" option (d) in magit-file-popup. e.g.:

(global-set-key (kbd "C-c m d") 'magit-diff-buffer-file)
(global-set-key (kbd "C-c m f") 'magit-file-popup)

Also note @assem's comment below:

You might also be interested in magit-ediff which is bound to e by default, and opens an ediff session for the diff/file at point.


Some other alternatives available in Emacs by default (i.e. not Magit) are:

  • C-xv= to call vc-diff
  • M-x vc-ediff for the ediff equivalent
  • M-x ediff-revision to create an ediff session with more options

I bind vc-ediff to C-xvC-= so that the two variants have similar key bindings.

Solution 2:

I recommend watching the video by the creator of magit. It's 20 min and it shows you the work-flow as it was intended.

Also, a small tip: you can use 1 2 3 to change the diff verbosity of the current heading.

Another small tip: if you're not happy with the size of the hunks, you can stage arbitrary regions by - that's right - marking a region and pressing s. It's magic. I didn't know about this option for a while, I was actually dropping back to console and doing git add -p the old fashioned way.

Solution 3:

There are definitely advantages to not going against the grain when using tools, as is exemplified by the other answers.

On the other hand, sometimes you just want to tell your editor what to do, and have people on the internet answer your questions instead of telling you want to do something else.

magit provides a menu interface for doing things to the current file through M-x magit-file-popup. The keys you need to press from here are "du". This may well be too many key presses for you, if this is the case you can call magit-diff directly like so:

(defun magit-diff-given-file (&optional file)
  (interactive)
  (unless file
    (setf file buffer-file-name))
  (magit-diff-working-tree "HEAD" nil (list (file-relative-name file (magit-toplevel file)))))

You might like to define your own function and keybinding for this.

magit-diff has advantages over vc-diff because if allows you to jump to the location of the diff.