Skip to content

Commit ef484ad

Browse files
r1walzgitster
authored andcommitted
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 <[email protected]> Signed-off-by: Phillip Wood <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 048abe1 commit ef484ad

File tree

4 files changed

+93
-6
lines changed

4 files changed

+93
-6
lines changed

Documentation/git-rebase.txt

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -422,8 +422,23 @@ your branch contains commits which were dropped, this option can be used
422422
with `--keep-base` in order to drop those commits from your branch.
423423

424424
--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+
425440
--whitespace=<option>::
426-
These flags are passed to the 'git apply' program
441+
This flag is passed to the 'git apply' program
427442
(see linkgit:git-apply[1]) that applies the patch.
428443
Implies --apply.
429444
+
@@ -572,7 +587,6 @@ The following options:
572587
* --apply
573588
* --committer-date-is-author-date
574589
* --ignore-date
575-
* --ignore-whitespace
576590
* --whitespace
577591
* -C
578592

@@ -598,6 +612,7 @@ In addition, the following pairs of options are incompatible:
598612
* --preserve-merges and --signoff
599613
* --preserve-merges and --rebase-merges
600614
* --preserve-merges and --empty=
615+
* --preserve-merges and --ignore-whitespace
601616
* --keep-base and --onto
602617
* --keep-base and --root
603618

builtin/rebase.c

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,7 @@ static struct replay_opts get_replay_opts(const struct rebase_options *opts)
126126
replay.reschedule_failed_exec = opts->reschedule_failed_exec;
127127
replay.gpg_sign = xstrdup_or_null(opts->gpg_sign_opt);
128128
replay.strategy = opts->strategy;
129+
129130
if (opts->strategy_opts)
130131
parse_strategy_opts(&replay, opts->strategy_opts);
131132

@@ -1466,6 +1467,7 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
14661467
struct strbuf revisions = STRBUF_INIT;
14671468
struct strbuf buf = STRBUF_INIT;
14681469
struct object_id merge_base;
1470+
int ignore_whitespace = 0;
14691471
enum action action = ACTION_NONE;
14701472
const char *gpg_sign = NULL;
14711473
struct string_list exec = STRING_LIST_INIT_NODUP;
@@ -1495,16 +1497,15 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
14951497
PARSE_OPT_NOARG, NULL, REBASE_DIFFSTAT },
14961498
OPT_BOOL(0, "signoff", &options.signoff,
14971499
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),
15011500
OPT_PASSTHRU_ARGV(0, "committer-date-is-author-date",
15021501
&options.git_am_opts, NULL,
15031502
N_("passed to 'git am'"), PARSE_OPT_NOARG),
15041503
OPT_PASSTHRU_ARGV(0, "ignore-date", &options.git_am_opts, NULL,
15051504
N_("passed to 'git am'"), PARSE_OPT_NOARG),
15061505
OPT_PASSTHRU_ARGV('C', NULL, &options.git_am_opts, N_("n"),
15071506
N_("passed to 'git apply'"), 0),
1507+
OPT_BOOL(0, "ignore-whitespace", &ignore_whitespace,
1508+
N_("ignore changes in whitespace")),
15081509
OPT_PASSTHRU_ARGV(0, "whitespace", &options.git_am_opts,
15091510
N_("action"), N_("passed to 'git apply'"), 0),
15101511
OPT_BIT('f', "force-rebase", &options.flags,
@@ -1850,6 +1851,18 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
18501851
imply_merge(&options, "--rebase-merges");
18511852
}
18521853

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+
18531866
if (strategy_options.nr) {
18541867
int i;
18551868

t/t3422-rebase-incompatible-options.sh

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,6 @@ test_rebase_am_only () {
6161
}
6262

6363
test_rebase_am_only --whitespace=fix
64-
test_rebase_am_only --ignore-whitespace
6564
test_rebase_am_only --committer-date-is-author-date
6665
test_rebase_am_only -C4
6766

t/t3436-rebase-more-options.sh

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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

0 commit comments

Comments
 (0)