Comparing Files in Emacs using Diff
diff-mode
diff
displays the differences between two files.
ediff
is a much more sophisticated alternative.
diff-backup
compares a file with its most recent backup. To know where your backups are kept, use this variable: backup-directory-alist
diff-buffer-with-file
compares the version of a file in a buffer with its version on disk. This is helpful for seeing what recent changes you have made before saving a file.
Note: diff
can be run with different switches. The default -u
generates unified diff
format, i.e., it displays all the changes between the two files in single continuous output.
-w
ignores whitespace. For precision's sake, one should leave this off.
The output of the diff
command is called a patch
.
Patches can at first appear confusing!
Try to get a global view of things first. A lot can be told by the global view.
Patches begin with details of the diff
command and the switches it ran, and the names of the files compared.
Details of each file follow.
--- c:/tan/wrd.vbs_original 2023-08-10 06:36:43.924694800 +0200
Note the timestamp in seconds and even fractional seconds. +0200
represents the time zone.
The changes specified in a patch
are grouped together into hunks
.
Note: Hunks also include lines that are the same in both files to help provide context.
Each hunk is preceded by a hunk header
.
Hunk headers begin with @@
and end with @@
. There is no special significance attached to the choice of the @@ symbol.
Hunk headers include lines for both files in which changes occur.
@@ -1,19 +1,31 @@
@@
marks out the hunk heading
-
indicates affected lines in the old file
+
indicates affected lines in the new file
The number formula "1,19" means the change starts at line 1 and spans 19 lines.
Then follows the hunk proper
, which should be the same number of lines as indicated in the hunk header.
An increase of span in a hunk header usually indicates the addition of new lines.
+1,31
1 indicates the starting line, 31 the number of lines involved (i.e., the span of affected lines). We can work out that 12 lines have been added.
If there is another hunk in the file, it will follow immediately after the end of the last hunk.
DIFF Commands
Note the ORDER in which files are invoked when compared; it's significant (NB). Usually, the old file is invoked first, followed by the more recent file.
Note: The diff process does not necessarily involve applying or reverting changes. It is primarily about understanding what changes exist between the two versions.
The second file is considered the "target file," i.e., the file TO WHICH any changes would be applied if applying a hunk.
If you want to make changes when using DIFF and know in advance which file needs to be changed, load that file second.
Note: The prefix key is C-c
for most DIFF commands.
M-n
: Moves to the start of the next hunk.
M-p
: Moves to the start of the previous hunk.
Tip: Setting diff-refine
refines the hunk only when you move to it.
You can "kill" a hunk, which means you remove it from the display. The files are unaffected by a "kill."
M-k
: Kill the hunk at the point.
C-c C-a
: Applies the hunk to the target file; a prefix argument applies THE REVERSE OF THE HUNK.
One can also save a DIFF buffer to a patch file. It is common to use the .patch
or .diff
extension.
C-c C-c
: Jumps to the target file and line corresponding to the hunk (diff-goto-source). With a prefix argument, it jumps to the “old” version instead.
C-c C-l
: Refreshes.