@matheusbsbs / matheus-bagliano / commits / ef484add9f
Fork 0

rebase -i: add --ignore-whitespace flag

Rebase is implemented with two different backends - 'apply' and 'merge' each of which support a different set of options. In particular the apply backend supports a number of options implemented by 'git am' that are not implemented in the merge backend. This means that the available options are different depending on which backend is used which is confusing. This patch adds support for the --ignore-whitespace option to the merge backend. This option treats lines with only whitespace changes as unchanged and is implemented in the merge backend by translating it to -Xignore-space-change. Signed-off-by: Rohit Ashiwal <rohit.ashiwal265@gmail.com> Signed-off-by: Phillip Wood <phillip.wood@dunelm.org.uk> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Rohit Ashiwal committed Jul 13, 2020 at 11:10 UTC ef484add9f6ba846c62e4f13ebe0ba99b9cc4aa5
4 files changed +93 -6
Documentation/git-rebase.txt
+17 -2
@@ -422,8 +422,23 @@ your branch contains commits which were dropped, this option can be used
422 with `--keep-base` in order to drop those commits from your branch.
423
424 --ignore-whitespace::
425 + Ignore whitespace differences when trying to reconcile
426 +differences. Currently, each backend implements an approximation of
427 +this behavior:
428 ++
429 +apply backend: When applying a patch, ignore changes in whitespace in
430 +context lines. Unfortunately, this means that if the "old" lines being
431 +replaced by the patch differ only in whitespace from the existing
432 +file, you will get a merge conflict instead of a successful patch
433 +application.
434 ++
435 +merge backend: Treat lines with only whitespace changes as unchanged
436 +when merging. Unfortunately, this means that any patch hunks that were
437 +intended to modify whitespace and nothing else will be dropped, even
438 +if the other side had no changes that conflicted.
439 +
440 --whitespace=<option>::
426 - These flags are passed to the 'git apply' program
441 + This flag is passed to the 'git apply' program
442 (see linkgit:git-apply[1]) that applies the patch.
443 Implies --apply.
444 +
@@ -572,7 +587,6 @@ The following options:
587 * --apply
588 * --committer-date-is-author-date
589 * --ignore-date
575 - * --ignore-whitespace
590 * --whitespace
591 * -C
592
@@ -598,6 +612,7 @@ In addition, the following pairs of options are incompatible:
612 * --preserve-merges and --signoff
613 * --preserve-merges and --rebase-merges
614 * --preserve-merges and --empty=
615 + * --preserve-merges and --ignore-whitespace
616 * --keep-base and --onto
617 * --keep-base and --root
618
builtin/rebase.c
+16 -3
@@ -126,6 +126,7 @@ static struct replay_opts get_replay_opts(const struct rebase_options *opts)
126 replay.reschedule_failed_exec = opts->reschedule_failed_exec;
127 replay.gpg_sign = xstrdup_or_null(opts->gpg_sign_opt);
128 replay.strategy = opts->strategy;
129 +
130 if (opts->strategy_opts)
131 parse_strategy_opts(&replay, opts->strategy_opts);
132
@@ -1466,6 +1467,7 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
1467 struct strbuf revisions = STRBUF_INIT;
1468 struct strbuf buf = STRBUF_INIT;
1469 struct object_id merge_base;
1470 + int ignore_whitespace = 0;
1471 enum action action = ACTION_NONE;
1472 const char *gpg_sign = NULL;
1473 struct string_list exec = STRING_LIST_INIT_NODUP;
@@ -1495,9 +1497,6 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
1497 PARSE_OPT_NOARG, NULL, REBASE_DIFFSTAT },
1498 OPT_BOOL(0, "signoff", &options.signoff,
1499 N_("add a Signed-off-by: line to each commit")),
1498 - OPT_PASSTHRU_ARGV(0, "ignore-whitespace", &options.git_am_opts,
1499 - NULL, N_("passed to 'git am'"),
1500 - PARSE_OPT_NOARG),
1500 OPT_PASSTHRU_ARGV(0, "committer-date-is-author-date",
1501 &options.git_am_opts, NULL,
1502 N_("passed to 'git am'"), PARSE_OPT_NOARG),
@@ -1505,6 +1504,8 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
1504 N_("passed to 'git am'"), PARSE_OPT_NOARG),
1505 OPT_PASSTHRU_ARGV('C', NULL, &options.git_am_opts, N_("n"),
1506 N_("passed to 'git apply'"), 0),
1507 + OPT_BOOL(0, "ignore-whitespace", &ignore_whitespace,
1508 + N_("ignore changes in whitespace")),
1509 OPT_PASSTHRU_ARGV(0, "whitespace", &options.git_am_opts,
1510 N_("action"), N_("passed to 'git apply'"), 0),
1511 OPT_BIT('f', "force-rebase", &options.flags,
@@ -1850,6 +1851,18 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
1851 imply_merge(&options, "--rebase-merges");
1852 }
1853
1854 + if (options.type == REBASE_APPLY) {
1855 + if (ignore_whitespace)
1856 + argv_array_push(&options.git_am_opts,
1857 + "--ignore-whitespace");
1858 + } else {
1859 + /* REBASE_MERGE and PRESERVE_MERGES */
1860 + if (ignore_whitespace) {
1861 + string_list_append(&strategy_options,
1862 + "ignore-space-change");
1863 + }
1864 + }
1865 +
1866 if (strategy_options.nr) {
1867 int i;
1868
t/t3422-rebase-incompatible-options.sh
-1
@@ -61,7 +61,6 @@ test_rebase_am_only () {
61 }
62
63 test_rebase_am_only --whitespace=fix
64 -test_rebase_am_only --ignore-whitespace
64 test_rebase_am_only --committer-date-is-author-date
65 test_rebase_am_only -C4
66
t/t3436-rebase-more-options.sh new
+60
@@ -0,0 +1,60 @@
1 +#!/bin/sh
2 +#
3 +# Copyright (c) 2019 Rohit Ashiwal
4 +#
5 +
6 +test_description='tests to ensure compatibility between am and interactive backends'
7 +
8 +. ./test-lib.sh
9 +
10 +. "$TEST_DIRECTORY"/lib-rebase.sh
11 +
12 +# This is a special case in which both am and interactive backends
13 +# provide the same output. It was done intentionally because
14 +# both the backends fall short of optimal behaviour.
15 +test_expect_success 'setup' '
16 + git checkout -b topic &&
17 + test_write_lines "line 1" " line 2" "line 3" >file &&
18 + git add file &&
19 + git commit -m "add file" &&
20 +
21 + test_write_lines "line 1" "new line 2" "line 3" >file &&
22 + git commit -am "update file" &&
23 + git tag side &&
24 +
25 + git checkout --orphan master &&
26 + test_write_lines "line 1" " line 2" "line 3" >file &&
27 + git commit -am "add file" &&
28 + git tag main
29 +'
30 +
31 +test_expect_success '--ignore-whitespace works with apply backend' '
32 + test_must_fail git rebase --apply main side &&
33 + git rebase --abort &&
34 + git rebase --apply --ignore-whitespace main side &&
35 + git diff --exit-code side
36 +'
37 +
38 +test_expect_success '--ignore-whitespace works with merge backend' '
39 + test_must_fail git rebase --merge main side &&
40 + git rebase --abort &&
41 + git rebase --merge --ignore-whitespace main side &&
42 + git diff --exit-code side
43 +'
44 +
45 +test_expect_success '--ignore-whitespace is remembered when continuing' '
46 + (
47 + set_fake_editor &&
48 + FAKE_LINES="break 1" git rebase -i --ignore-whitespace \
49 + main side &&
50 + git rebase --continue
51 + ) &&
52 + git diff --exit-code side
53 +'
54 +
55 +# This must be the last test in this file
56 +test_expect_success '$EDITOR and friends are unchanged' '
57 + test_editor_unchanged
58 +'
59 +
60 +test_done