@matheusbsbs / matheus-bagliano / commits / 467ddc14fe
Fork 0

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 <git@drmicha.warpmail.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Junio C Hamano committed Feb 28, 2011 at 16:11 UTC 467ddc14fe37ea6a3d77058fb24c4240e82e6344
4 files changed +70 -6
Documentation/diff-options.txt
+13
@@ -259,6 +259,19 @@ endif::git-log[]
259 projects, so use it with caution. Giving more than one
260 `-C` option has the same effect.
261
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 +
275 -l<num>::
276 The `-M` and `-C` options require O(n^2) processing time where n
277 is the number of potential rename/copy targets. This
diff.c
+14 -5
@@ -572,11 +572,14 @@ static void emit_rewrite_diff(const char *name_a,
572 line_prefix, metainfo, a_name.buf, name_a_tab, reset,
573 line_prefix, metainfo, b_name.buf, name_b_tab, reset,
574 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, "?,?");
579 fprintf(o->file, " +");
580 print_line_count(o->file, lc_b);
581 fprintf(o->file, " @@%s\n", reset);
579 - if (lc_a)
582 + if (lc_a && !o->irreversible_delete)
583 emit_rewrite_lines(&ecbdata, '-', data_one, size_one);
584 if (lc_b)
585 emit_rewrite_lines(&ecbdata, '+', data_two, size_two);
@@ -1943,7 +1946,11 @@ static void builtin_diff(const char *name_a,
1946 }
1947 }
1948
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) &&
1954 ( (!textconv_one && diff_filespec_is_binary(one)) ||
1955 (!textconv_two && diff_filespec_is_binary(two)) )) {
1956 if (fill_mmfile(&mf1, one) < 0 || fill_mmfile(&mf2, two) < 0)
@@ -1963,8 +1970,7 @@ static void builtin_diff(const char *name_a,
1970 fprintf(o->file, "%sBinary files %s and %s differ\n",
1971 line_prefix, lbl[0], lbl[1]);
1972 o->found_changes = 1;
1966 - }
1967 - else {
1973 + } else {
1974 /* Crazy xdl interfaces.. */
1975 const char *diffopts = getenv("GIT_DIFF_OPTS");
1976 xpparam_t xpp;
@@ -3160,6 +3166,9 @@ int diff_opt_parse(struct diff_options *options, const char **av, int ac)
3166 return error("invalid argument to -M: %s", arg+2);
3167 options->detect_rename = DIFF_DETECT_RENAME;
3168 }
3169 + else if (!strcmp(arg, "-D") || !strcmp(arg, "--irreversible-delete")) {
3170 + options->irreversible_delete = 1;
3171 + }
3172 else if (!prefixcmp(arg, "-C") || !prefixcmp(arg, "--find-copies=") ||
3173 !strcmp(arg, "--find-copies")) {
3174 if (options->detect_rename == DIFF_DETECT_COPY)
diff.h
+1
@@ -104,6 +104,7 @@ struct diff_options {
104 int interhunkcontext;
105 int break_opt;
106 int detect_rename;
107 + int irreversible_delete;
108 int skip_stat_unmatch;
109 int line_termination;
110 int output_format;
t/t4022-diff-rewrite.sh
+42 -1
@@ -11,7 +11,9 @@ test_expect_success setup '
11 tr \
12 "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" \
13 "nopqrstuvwxyzabcdefghijklmNOPQRSTUVWXYZABCDEFGHIJKLM" \
14 - <"$TEST_DIRECTORY"/../COPYING >test
14 + <"$TEST_DIRECTORY"/../COPYING >test &&
15 + echo "to be deleted" >test2 &&
16 + git add test2
17
18 '
19
@@ -25,5 +27,44 @@ test_expect_success 'detect rewrite' '
27
28 '
29
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 +
69 test_done
70