Emacs: diff mode
emacs diff mode
Emacs diff mode tutorial (AI generated)
Diff Mode in Emacs is a major mode for viewing, editing, and applying patches (outputs from the diff command or tools like Git). It makes it easy to navigate changes (called "hunks"), refine differences, apply/revert patches selectively, convert between diff formats, and more.
Entering Diff Mode
- Automatically: Running
M-x diff(compare two files) or commands likeC-x v =(VC diff) opens a*diff*buffer in Diff mode. - Manually:
M-x diff-modein any buffer containing a patch. - From Dired: Mark files and use
=ord(diff) commands.
Diff mode supports unified diffs (most common, from diff -u), context diffs, and to a lesser extent normal diffs.
Basic Structure of a Patch in Diff Mode
A patch contains:
- File headers: Show old/new file names and timestamps.
- Hunks: Groups of changes with headers like
@@ -old_start,old_lines +new_start,new_lines @@. - Context lines (unchanged) around added (
+), removed (-), or changed lines.
Emacs highlights hunk headers and (by default) refines changes for finer granularity.
Key Navigation Commands
| Key | Command | Description |
M-n | diff-hunk-next | Next hunk (prefix arg for nth) |
M-p | diff-hunk-prev | Previous hunk |
M-} | diff-file-next | Next file (in multi-file patches) |
M-{ | diff-file-prev | Previous file |
C-c C-n | diff-restrict-view | Narrow to current hunk (or file with prefix); C-x n w to widen |
C-c C-c | diff-goto-source | Jump to source file/line (new version by default; prefix for old) |
Refining hunks (highlighting word/character-level changes):
- By default, hunks refine automatically on display.
- Set
diff-refineto'navigationfor on-demand only. C-c C-b(diff-refine-hunk) manually refines the current hunk.
Editing and Manipulating Hunks
You can edit the patch like any text buffer. Diff mode automatically updates hunk line numbers (diff-update-on-the-fly; set to nil to disable).
| Key | Command | Description |
M-k | diff-hunk-kill | Kill current hunk |
M-K | diff-file-kill | Kill current file's changes (multi-file) |
C-c C-s | diff-split-hunk | Split hunk at point (unified diffs only) |
C-c C-l | diff-refresh-hunk | Recompute current hunk |
C-c C-w | diff-ignore-whitespace-hunk | Recompute ignoring whitespace (prefix for all) |
C-c C-r | diff-reverse-direction | Reverse patch (old ↔ new); prefix for region |
Format conversion:
C-c C-u→ Unified formatC-c C-d→ Context format
Applying Patches
| Key | Command | Description |
C-c C-a | diff-apply-hunk | Apply hunk (prefix C-u to reverse/revert) |
C-c RET a | diff-apply-buffer | Apply all hunks, save buffers |
C-c C-e | diff-ediff-patch | Start Ediff session with the patch |
diff-jump-to-old-filecontrols default target (new vs. old version).- Use
M-x diff-delete-trailing-whitespaceto clean up unwanted whitespace in patches.
Other Useful Commands
C-x 4 A(diff-add-change-log-entries-other-window): Generate skeleton ChangeLog entries from hunks.M-g M-n/ compilation commands: Treat hunks as "errors" to jump to sources.- Whitespace mode: Highlights trailing whitespace in modified lines.
Generating Diffs
M-x diff: Compare two files (usesdiff-switches, default-ufor unified).- VC (Version Control):
C-x v =for current file vs. repo version. - From Dired or other tools.
Customization
Key variables:
diff-switches: Default options fordiff(e.g.,"-u").diff-refine: Control auto-refinement (t,nil, or'navigation).diff-update-on-the-fly: Auto-fix line numbers on edit.diff-font-lock-syntax: Syntax-highlight source fragments in hunks (non-nilby default in recent Emacs).- Faces: Customize
diff-added,diff-removed,diff-hunk-header,diff-refine-added, etc. viaM-x customize-face.
Enable in hooks or for specific files: (add-to-list 'auto-mode-alist '("\\.patch\\'" . diff-mode)) or ("\\.diff\\'" . diff-mode).
Tips and Workflows
- Quick review in VC:
C-x v =→M-n/M-pto navigate →C-c C-cto jump to code →C-c C-ato apply/revert hunks selectively. - Selective patching: Split hunks (
C-c C-s), kill unwanted ones, then apply. - Ediff integration: Use
C-c C-efor interactive side-by-side merging (much more powerful for complex diffs). - Read-only buffers: Many commands work without
ESCprefix. - diff-hl-mode (from GNU ELPA): Fringe highlights for changed lines in source buffers + navigation.
Related Tools
- Ediff (
M-x ediff-files,ediff-revision, etc.): Powerful interactive comparison/merging with control panel. - Magit: Excellent Git interface with superior diff views (many users prefer it over raw diff-mode).
- diff-hl, vdiff, etc.: Extensions for enhanced visuals.
For the full details, consult the Emacs manual with C-h i m emacs RET i diff-mode RET or online.
Practice by creating a small patch: Edit two copies of a file, run M-x diff, then experiment with the keys above. Diff mode turns patch handling into a seamless Emacs-native experience!