Search code examples
emacsgit-diffmagit

How can I diff a single file with magit?


Say I've made a number of unrelated changes to uncoupled files in my git repo. I want to review and commit each of the files separately.

I run magit-status, and get a list of changed files. But the only magit diff commands I can find (d and D) diff entire revisons, not individual files.

I want the output of git diff <filename>, but in the magit diff buffer. How can I get magit to diff only one file?


Solution

  • 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.