Skip to content

Commit 467ddc1

Browse files
committed
git diff -D: omit the preimage of deletes
When reviewing a patch while concentrating primarily on the text after then change, wading through pages of deleted text involves a cognitive burden. Introduce the -D option that omits the preimage text from the patch output for deleted files. When used with -B (represent total rewrite as a single wholesale deletion followed by a single wholesale addition), the preimage text is also omitted. To prevent such a patch from being applied by mistake, the output is designed not to be usable by "git apply" (or GNU "patch"); it is strictly for human consumption. It of course is possible to "apply" such a patch by hand, as a human can read the intention out of such a patch. It however is impossible to apply such a patch even manually in reverse, as the whole point of this option is to omit the information necessary to do so from the output. Initial request by Mart Sõmermaa, documentation and tests helped by Michael J Gruber. Signed-off-by: Michael J Gruber <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent afb0b79 commit 467ddc1

File tree

4 files changed

+70
-6
lines changed

4 files changed

+70
-6
lines changed

Documentation/diff-options.txt

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -259,6 +259,19 @@ endif::git-log[]
259259
projects, so use it with caution. Giving more than one
260260
`-C` option has the same effect.
261261

262+
-D::
263+
--irreversible-delete::
264+
Omit the preimage for deletes, i.e. print only the header but not
265+
the diff between the preimage and `/dev/null`. The resulting patch
266+
is not meant to be applied with `patch` nor `git apply`; this is
267+
solely for people who want to just concentrate on reviewing the
268+
text after the change. In addition, the output obviously lack
269+
enough information to apply such a patch in reverse, even manually,
270+
hence the name of the option.
271+
+
272+
When used together with `-B`, omit also the preimage in the deletion part
273+
of a delete/create pair.
274+
262275
-l<num>::
263276
The `-M` and `-C` options require O(n^2) processing time where n
264277
is the number of potential rename/copy targets. This

diff.c

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -572,11 +572,14 @@ static void emit_rewrite_diff(const char *name_a,
572572
line_prefix, metainfo, a_name.buf, name_a_tab, reset,
573573
line_prefix, metainfo, b_name.buf, name_b_tab, reset,
574574
line_prefix, fraginfo);
575-
print_line_count(o->file, lc_a);
575+
if (!o->irreversible_delete)
576+
print_line_count(o->file, lc_a);
577+
else
578+
fprintf(o->file, "?,?");
576579
fprintf(o->file, " +");
577580
print_line_count(o->file, lc_b);
578581
fprintf(o->file, " @@%s\n", reset);
579-
if (lc_a)
582+
if (lc_a && !o->irreversible_delete)
580583
emit_rewrite_lines(&ecbdata, '-', data_one, size_one);
581584
if (lc_b)
582585
emit_rewrite_lines(&ecbdata, '+', data_two, size_two);
@@ -1943,7 +1946,11 @@ static void builtin_diff(const char *name_a,
19431946
}
19441947
}
19451948

1946-
if (!DIFF_OPT_TST(o, TEXT) &&
1949+
if (o->irreversible_delete && lbl[1][0] == '/') {
1950+
fprintf(o->file, "%s", header.buf);
1951+
strbuf_reset(&header);
1952+
goto free_ab_and_return;
1953+
} else if (!DIFF_OPT_TST(o, TEXT) &&
19471954
( (!textconv_one && diff_filespec_is_binary(one)) ||
19481955
(!textconv_two && diff_filespec_is_binary(two)) )) {
19491956
if (fill_mmfile(&mf1, one) < 0 || fill_mmfile(&mf2, two) < 0)
@@ -1963,8 +1970,7 @@ static void builtin_diff(const char *name_a,
19631970
fprintf(o->file, "%sBinary files %s and %s differ\n",
19641971
line_prefix, lbl[0], lbl[1]);
19651972
o->found_changes = 1;
1966-
}
1967-
else {
1973+
} else {
19681974
/* Crazy xdl interfaces.. */
19691975
const char *diffopts = getenv("GIT_DIFF_OPTS");
19701976
xpparam_t xpp;
@@ -3160,6 +3166,9 @@ int diff_opt_parse(struct diff_options *options, const char **av, int ac)
31603166
return error("invalid argument to -M: %s", arg+2);
31613167
options->detect_rename = DIFF_DETECT_RENAME;
31623168
}
3169+
else if (!strcmp(arg, "-D") || !strcmp(arg, "--irreversible-delete")) {
3170+
options->irreversible_delete = 1;
3171+
}
31633172
else if (!prefixcmp(arg, "-C") || !prefixcmp(arg, "--find-copies=") ||
31643173
!strcmp(arg, "--find-copies")) {
31653174
if (options->detect_rename == DIFF_DETECT_COPY)

diff.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,7 @@ struct diff_options {
104104
int interhunkcontext;
105105
int break_opt;
106106
int detect_rename;
107+
int irreversible_delete;
107108
int skip_stat_unmatch;
108109
int line_termination;
109110
int output_format;

t/t4022-diff-rewrite.sh

Lines changed: 42 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,9 @@ test_expect_success setup '
1111
tr \
1212
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" \
1313
"nopqrstuvwxyzabcdefghijklmNOPQRSTUVWXYZABCDEFGHIJKLM" \
14-
<"$TEST_DIRECTORY"/../COPYING >test
14+
<"$TEST_DIRECTORY"/../COPYING >test &&
15+
echo "to be deleted" >test2 &&
16+
git add test2
1517
1618
'
1719

@@ -25,5 +27,44 @@ test_expect_success 'detect rewrite' '
2527
2628
'
2729

30+
cat >expect <<EOF
31+
diff --git a/test2 b/test2
32+
deleted file mode 100644
33+
index 4202011..0000000
34+
--- a/test2
35+
+++ /dev/null
36+
@@ -1 +0,0 @@
37+
-to be deleted
38+
EOF
39+
test_expect_success 'show deletion diff without -D' '
40+
41+
rm test2 &&
42+
git diff -- test2 >actual &&
43+
test_cmp expect actual
44+
'
45+
46+
cat >expect <<EOF
47+
diff --git a/test2 b/test2
48+
deleted file mode 100644
49+
index 4202011..0000000
50+
EOF
51+
test_expect_success 'suppress deletion diff with -D' '
52+
53+
git diff -D -- test2 >actual &&
54+
test_cmp expect actual
55+
'
56+
57+
test_expect_success 'show deletion diff with -B' '
58+
59+
git diff -B -- test >actual &&
60+
grep "Linus Torvalds" actual
61+
'
62+
63+
test_expect_success 'suppress deletion diff with -B -D' '
64+
65+
git diff -B -D -- test >actual &&
66+
grep -v "Linus Torvalds" actual
67+
'
68+
2869
test_done
2970

0 commit comments

Comments
 (0)