5.4 Diffing

The status buffer contains diffs for the staged and unstaged commits, but that obviously isn’t enough. The transient prefix command magit-diff, on d, features several suffix commands, which show a specific diff in a separate diff buffer.

Like other transient prefix commands, magit-diff also features several infix arguments that can be changed before invoking one of the suffix commands. However, in the case of the diff transient, these arguments may be taken from those currently in use in the current repository’s diff buffer, depending on the value of magit-prefix-use-buffer-arguments (see Transient Arguments and Buffer Variables).

Also see the git-diff(1) manpage.

d (magit-diff)

This transient prefix command binds the following suffix commands along with the appropriate infix arguments and displays them in a temporary buffer until a suffix is invoked.

d d (magit-diff-dwim)

Show changes for the thing at point.

For example, if point is on a commit, show the changes introduced by that commit. Likewise if point is on the section titled "Unstaged changes", then show those changes in a separate buffer. Generally speaking, compare the thing at point with the most logical, trivial and (in any situation) at least potentially useful other thing it could be compared to.

When the region selects commits, then compare the two commits at either end. There are different ways two commits can be compared. In the buffer showing the diff, you can control how the comparison, is done, using "D r" and "D f".

This function does not always show the changes that you might want to view in any given situation. You can think of the changes being shown as the smallest common denominator. There is no AI involved. If this command never does what you want, then ignore it, and instead use the commands that allow you to explicitly specify what you need.

d r (magit-diff-range)

Show differences between two commits.

RANGE should be a range (A..B or A…B) but can also be a single commit. If one side of the range is omitted, then it defaults to HEAD. If just a commit is given, then changes in the working tree relative to that commit are shown.

If the region is active, use the revisions on the first and last line of the region. With a prefix argument, instead of diffing the revisions, choose a revision to view changes along, starting at the common ancestor of both revisions (i.e., use a "…" range).

d w (magit-diff-working-tree)

Show changes between the current working tree and the HEAD commit. With a prefix argument show changes between the working tree and a commit read from the minibuffer.

d s (magit-diff-staged)

Show changes between the index and the HEAD commit. With a prefix argument show changes between the index and a commit read from the minibuffer.

d u (magit-diff-unstaged)

Show changes between the working tree and the index.

d p (magit-diff-paths)

Show changes between any two files on disk.

All of the above suffix commands update the repository’s diff buffer. The diff transient also features two commands which show differences in another buffer:

d c (magit-show-commit)

Show the commit at point. If there is no commit at point or with a prefix argument, prompt for a commit.

d t (magit-stash-show)

Show all diffs of a stash in a buffer.

Two additional commands that show the diff for the file or blob that is being visited in the current buffer exists, see Commands for Buffers Visiting Files.

5.4.1 Refreshing Diffs

The transient prefix command magit-diff-refresh, on D, can be used to change the diff arguments used in the current buffer, without changing which diff is shown. This works in dedicated diff buffers, but also in the status buffer.

(There is one exception; diff arguments cannot be changed in buffers created by magit-merge-preview because the underlying Git command does not support these arguments.)

D (magit-diff-refresh)

This transient prefix command binds the following suffix commands along with the appropriate infix arguments and displays them in a temporary buffer until a suffix is invoked.

D g (magit-diff-refresh)

This suffix command sets the local diff arguments for the current buffer.

D s (magit-diff-set-default-arguments)

This suffix command sets the default diff arguments for buffers of the same type as that of the current buffer. Other existing buffers of the same type are not affected because their local values have already been initialized.

D w (magit-diff-save-default-arguments)

This suffix command sets the default diff arguments for buffers of the same type as that of the current buffer, and saves the value for future sessions. Other existing buffers of the same type are not affected because their local values have already been initialized.

D t (magit-diff-toggle-refine-hunk)

This command toggles hunk refinement on or off.

D r (magit-diff-switch-range-type)

This command converts the diff range type from "revA..revB" to "revB…revA", or vice versa.

D f (magit-diff-flip-revs)

This command swaps revisions in the diff range from "revA..revB" to "revB..revA", or vice versa.

D F (magit-diff-toggle-file-filter)

This command toggles the file restriction of the diffs in the current buffer, allowing you to quickly switch between viewing all the changes in the commit and the restricted subset. As a special case, when this command is called from a log buffer, it toggles the file restriction in the repository’s revision buffer, which is useful when you display a revision from a log buffer that is restricted to a file or files.

In addition to the above transient, which allows changing any of the supported arguments, there also exist some commands that change only a particular argument.

- (magit-diff-less-context)

This command decreases the context for diff hunks by COUNT lines.

+ (magit-diff-more-context)

This command increases the context for diff hunks by COUNT lines.

0 (magit-diff-default-context)

This command resets the context for diff hunks to the default height.

The following commands quickly change what diff is being displayed without having to using one of the diff transient.

C-c C-d (magit-diff-while-committing)

While committing, this command shows the changes that are about to be committed. While amending, invoking the command again toggles between showing just the new changes or all the changes that will be committed.

This binding is available in the diff buffer as well as the commit message buffer.

C-c C-b (magit-go-backward)

This command moves backward in current buffer’s history.

C-c C-f (magit-go-forward)

This command moves forward in current buffer’s history.

5.4.2 Commands Available in Diffs

Some commands are only available if point is inside a diff.

magit-diff-visit-file and related commands visit the appropriate version of the file that the diff at point is about. Likewise magit-diff-visit-worktree-file and related commands visit the worktree version of the file that the diff at point is about. See Visiting Files and Blobs from a Diff for more information and the key bindings.

C-c C-t (magit-diff-trace-definition)

This command shows a log for the definition at point.

User Option: magit-log-trace-definition-function

The function specified by this option is used by magit-log-trace-definition to determine the function at point. For major-modes that have special needs, you could set the local value using the mode’s hook.

C-c C-e (magit-diff-edit-hunk-commit)

From a hunk, this command edits the respective commit and visits the file.

First it visits the file being modified by the hunk at the correct location using magit-diff-visit-file. This actually visits a blob. When point is on a diff header, not within an individual hunk, then this visits the blob the first hunk is about.

Then it invokes magit-edit-line-commit, which uses an interactive rebase to make the commit editable, or if that is not possible because the commit is not reachable from HEAD by checking out that commit directly. This also causes the actual worktree file to be visited.

Neither the blob nor the file buffer are killed when finishing the rebase. If that is undesirable, then it might be better to use magit-rebase-edit-commit instead of this command.

j (magit-jump-to-diffstat-or-diff)

This command jumps to the diffstat or diff. When point is on a file inside the diffstat section, then jump to the respective diff section. Otherwise, jump to the diffstat section or a child thereof.

The next two commands are not specific to Magit-Diff mode (or and Magit buffer for that matter), but it might be worth pointing out that they are available here too.

SPC (scroll-up)

This command scrolls text upward.

DEL (scroll-down)

This command scrolls text downward.

5.4.3 Diff Options

User Option: magit-diff-refine-hunk

Whether to show word-granularity differences within diff hunks.

  • nil Never show fine differences.
  • all Show fine differences for all displayed diff hunks.
  • t Refine each hunk once it becomes the current section. Keep the refinement when another section is selected. Refreshing the buffer removes all refinement. This variant is only provided for performance reasons.
User Option: magit-diff-refine-ignore-whitespace

Whether to ignore whitespace changes in word-granularity differences.

User Option: magit-diff-adjust-tab-width

Whether to adjust the width of tabs in diffs.

Determining the correct width can be expensive if it requires opening large and/or many files, so the widths are cached in the variable magit-diff--tab-width-cache. Set that to nil to invalidate the cache.

  • nil Never adjust tab width. Use ‘tab-width’s value from the Magit buffer itself instead.
  • t If the corresponding file-visiting buffer exits, then use tab-width’s value from that buffer. Doing this is cheap, so this value is used even if a corresponding cache entry exists.
  • always If there is no such buffer, then temporarily visit the file to determine the value.
  • NUMBER Like always, but don’t visit files larger than NUMBER bytes.
User Option: magit-diff-paint-whitespace

Specify where to highlight whitespace errors.

See magit-diff-highlight-trailing, magit-diff-highlight-indentation. The symbol t means in all diffs, status means only in the status buffer, and nil means nowhere.

  • nil Never highlight whitespace errors.
  • t Highlight whitespace errors everywhere.
  • uncommitted Only highlight whitespace errors in diffs showing uncommitted changes. For backward compatibility status is treated as a synonym.
User Option: magit-diff-paint-whitespace-lines

Specify in what kind of lines to highlight whitespace errors.

  • t Highlight only in added lines.
  • both Highlight in added and removed lines.
  • all Highlight in added, removed and context lines.
User Option: magit-diff-highlight-trailing

Whether to highlight whitespace at the end of a line in diffs. Used only when magit-diff-paint-whitespace is non-nil.

User Option: magit-diff-highlight-indentation

This option controls whether to highlight the indentation in case it used the "wrong" indentation style. Indentation is only highlighted if magit-diff-paint-whitespace is also non-nil.

The value is an alist of the form ((REGEXP . INDENT)...). The path to the current repository is matched against each element in reverse order. Therefore if a REGEXP matches, then earlier elements are not tried.

If the used INDENT is tabs, highlight indentation with tabs. If INDENT is an integer, highlight indentation with at least that many spaces. Otherwise, highlight neither.

User Option: magit-diff-hide-trailing-cr-characters

Whether to hide ^M characters at the end of a line in diffs.

User Option: magit-diff-highlight-hunk-region-functions

This option specifies the functions used to highlight the hunk-internal region.

magit-diff-highlight-hunk-region-dim-outside overlays the outside of the hunk internal selection with a face that causes the added and removed lines to have the same background color as context lines. This function should not be removed from the value of this option.

magit-diff-highlight-hunk-region-using-overlays and magit-diff-highlight-hunk-region-using-underline emphasize the region by placing delimiting horizontal lines before and after it. Both of these functions have glitches which cannot be fixed due to limitations of Emacs’ display engine. For more information see https://github.com/magit/magit/issues/2758 ff.

Instead of, or in addition to, using delimiting horizontal lines, to emphasize the boundaries, you may wish to emphasize the text itself, using magit-diff-highlight-hunk-region-using-face.

In terminal frames it’s not possible to draw lines as the overlay and underline variants normally do, so there they fall back to calling the face function instead.

User Option: magit-diff-unmarked-lines-keep-foreground

This option controls whether added and removed lines outside the hunk-internal region only lose their distinct background color or also the foreground color. Whether the outside of the region is dimmed at all depends on magit-diff-highlight-hunk-region-functions.

User Option: magit-diff-extra-stat-arguments

This option specifies additional arguments to be used alongside --stat.

The value is a list of zero or more arguments or a function that takes no argument and returns such a list. These arguments are allowed here: --stat-width, --stat-name-width, --stat-graph-width and --compact-summary. Also see the git-diff(1) manpage.

User Option: magit-format-file-function

This function is used to format lines representing a file. It is used for file headings in diffs, in diffstats and for lists of files (such as the untracked files). Depending on the caller, it receives either three or five arguments; the signature has to be (kind file face &optional status orig). KIND is one of diff, module, stat and list.

5.4.4 Revision Buffer

User Option: magit-revision-insert-related-refs

Whether to show related branches in revision buffers.

  • nil Don’t show any related branches.
  • t Show related local branches.
  • all Show related local and remote branches.
  • mixed Show all containing branches and local merged branches.
User Option: magit-revision-show-gravatars

Whether to show gravatar images in revision buffers.

If nil, then don’t insert any gravatar images. If t, then insert both images. If author or committer, then insert only the respective image.

If you have customized the option magit-revision-headers-format and want to insert the images then you might also have to specify where to do so. In that case the value has to be a cons-cell of two regular expressions. The car specifies where to insert the author’s image. The top half of the image is inserted right after the matched text, the bottom half on the next line in the same column. The cdr specifies where to insert the committer’s image, accordingly. Either the car or the cdr may be nil."

User Option: magit-revision-use-hash-sections

Whether to turn hashes inside the commit message into sections.

If non-nil, then hashes inside the commit message are turned into commit sections. There is a trade off to be made between performance and reliability:

  • slow calls git for every word to be absolutely sure.
  • quick skips words less than seven characters long.
  • quicker additionally skips words that don’t contain a number.
  • quickest uses all words that are at least seven characters long and which contain at least one number as well as at least one letter.

If nil, then no hashes are turned into sections, but you can still visit the commit at point using "RET".

The diffs shown in the revision buffer may be automatically restricted to a subset of the changed files. If the revision buffer is displayed from a log buffer, the revision buffer will share the same file restriction as that log buffer (also see the command magit-diff-toggle-file-filter).

User Option: magit-revision-filter-files-on-follow

Whether showing a commit from a log buffer honors the log’s file filter when the log arguments include --follow.

When this option is nil, displaying a commit from a log ignores the log’s file filter if the log arguments include --follow. Doing so avoids showing an empty diff in revision buffers for commits before a rename event. In such cases, the --patch argument of the log transient can be used to show the file-restricted diffs inline.

Set this option to non-nil to keep the log’s file restriction even if --follow is present in the log arguments.

If the revision buffer is not displayed from a log buffer, the file restriction is determined as usual (see Transient Arguments and Buffer Variables).