How can I diff a single file with magit?
Asked Answered
K

3

55

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?

Kalman answered 22/7, 2013 at 21:53 Comment(1)
What about using e on magit-status for Ediff dwimming?Ropy
P
101

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.

Pandora answered 23/7, 2013 at 0:16 Comment(9)
I didn't know about TAB.Kalman
Right, I thought that might be the case. That's pretty much the "killer app" aspect of magit you were missing out on, there! :) You can stage or unstage whole files, individual hunks within a file, or even the marked region. You should skim through magit.github.io/magit/magit.html as you're probably also missing out on some other nice features.Pandora
I've just been using a cheat sheet. I didn't know what the "section visibility" commands meant, and I just thought that s didn't work in my version of magit.Kalman
It sounds like your cheat sheet could make things clearer for people who don't already know how it works. You should write to the author and suggest improvements.Pandora
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.Emporium
Thanks for the answer. it helps my a lot by using vc-diffCasuistry
eleforest: You're welcome. You may also find it useful to bind a key sequence to vc-ediff, as that has no default binding (I use C-x v C-=).Pandora
Any idea how to keep magit-ediff from rearranging my windows? It closed all the windows and replaced them with its own in a different layout, instead of just taking the windows over.Cavender
Peter Becich: You could undoubtedly have code to remember and restore the window configuration either side of the ediff call, but personally I just rely on winner-mode for this sort of thing. A quick C-c <left> or two always puts things back the way they were, and it works for everything.Pandora
A
24

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.

Acclimate answered 23/7, 2013 at 6:30 Comment(1)
It's sad that the last magit screencast was 4 years ago. As a community Emacs needs to embrace screencasts more.Luong
P
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.

Phenomenalism answered 29/11, 2016 at 4:14 Comment(2)
vc-diff also allows you to jump to the location of the diff. (Which is possibly a new feature.)Quote
I wish I could upvote this dozens of times for the "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."Dido

© 2022 - 2024 — McMap. All rights reserved.