rebase -i: add --ignore-whitespace flag
There are two backends available for rebasing, viz, the am and the interactive. Naturally, there shall be some features that are implemented in one but not in the other. One such flag is --ignore-whitespace which indicates merge mechanism to treat lines with only whitespace changes as unchanged. Wire the interactive rebase to also understand the --ignore-whitespace flag by translating it to -Xignore-space-change. Signed-off-by: Rohit Ashiwal <rohit.ashiwal265@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Rohit Ashiwal committed
Nov 1, 2019 at 19:29 UTC
ba51d2fb24b1a41b8cc15270a06f24c35c0fcf19
4 files changed
+90
-7
Documentation/git-rebase.txt
+10
-2
@@ -371,8 +371,16 @@ If either <upstream> or --root is given on the command line, then the
371
default is `--no-fork-point`, otherwise the default is `--fork-point`.
372
373
--ignore-whitespace::
374
+ Behaves differently depending on which backend is selected.
375
++
376
+'am' backend: When applying a patch, ignore changes in whitespace in
377
+context lines if necessary.
378
++
379
+'interactive' backend: Treat lines with only whitespace changes as
380
+unchanged for the sake of a three-way merge.
381
+
382
--whitespace=<option>::
375
- These flag are passed to the 'git apply' program
383
+ This flag is passed to the 'git apply' program
384
(see linkgit:git-apply[1]) that applies the patch.
385
+
386
See also INCOMPATIBLE OPTIONS below.
@@ -520,7 +528,6 @@ The following options:
528
* --committer-date-is-author-date
529
* --ignore-date
530
* --whitespace
523
- * --ignore-whitespace
531
* -C
532
533
are incompatible with the following options:
@@ -543,6 +550,7 @@ In addition, the following pairs of options are incompatible:
550
* --preserve-merges and --interactive
551
* --preserve-merges and --signoff
552
* --preserve-merges and --rebase-merges
553
+ * --preserve-merges and --ignore-whitespace
554
* --rebase-merges and --strategy
555
* --rebase-merges and --strategy-option
556
builtin/rebase.c
+15
-4
@@ -79,6 +79,7 @@ struct rebase_options {
79
int allow_rerere_autoupdate;
80
int keep_empty;
81
int autosquash;
82
+ int ignore_whitespace;
83
char *gpg_sign_opt;
84
int autostash;
85
char *cmd;
@@ -99,6 +100,7 @@ struct rebase_options {
100
101
static struct replay_opts get_replay_opts(const struct rebase_options *opts)
102
{
103
+ struct strbuf strategy_buf = STRBUF_INIT;
104
struct replay_opts replay = REPLAY_OPTS_INIT;
105
106
replay.action = REPLAY_INTERACTIVE_REBASE;
@@ -114,9 +116,15 @@ static struct replay_opts get_replay_opts(const struct rebase_options *opts)
116
replay.reschedule_failed_exec = opts->reschedule_failed_exec;
117
replay.gpg_sign = xstrdup_or_null(opts->gpg_sign_opt);
118
replay.strategy = opts->strategy;
119
+
120
if (opts->strategy_opts)
118
- parse_strategy_opts(&replay, opts->strategy_opts);
121
+ strbuf_addstr(&strategy_buf, opts->strategy_opts);
122
+ if (opts->ignore_whitespace)
123
+ strbuf_addstr(&strategy_buf, " --ignore-space-change");
124
+ if (strategy_buf.len)
125
+ parse_strategy_opts(&replay, strategy_buf.buf);
126
127
+ strbuf_release(&strategy_buf);
128
return replay;
129
}
130
@@ -511,6 +519,8 @@ int cmd_rebase__interactive(int argc, const char **argv, const char *prefix)
519
argc = parse_options(argc, argv, NULL, options,
520
builtin_rebase_interactive_usage, PARSE_OPT_KEEP_ARGV0);
521
522
+ opts.strategy_opts = xstrdup_or_null(opts.strategy_opts);
523
+
524
if (!is_null_oid(&squash_onto))
525
opts.squash_onto = &squash_onto;
526
@@ -964,6 +974,8 @@ static int run_am(struct rebase_options *opts)
974
am.git_cmd = 1;
975
argv_array_push(&am.args, "am");
976
977
+ if (opts->ignore_whitespace)
978
+ argv_array_push(&am.args, "--ignore-whitespace");
979
if (opts->action && !strcmp("continue", opts->action)) {
980
argv_array_push(&am.args, "--resolved");
981
argv_array_pushf(&am.args, "--resolvemsg=%s", resolvemsg);
@@ -1412,9 +1424,6 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
1424
PARSE_OPT_NOARG, NULL, REBASE_DIFFSTAT },
1425
OPT_BOOL(0, "signoff", &options.signoff,
1426
N_("add a Signed-off-by: line to each commit")),
1415
- OPT_PASSTHRU_ARGV(0, "ignore-whitespace", &options.git_am_opts,
1416
- NULL, N_("passed to 'git am'"),
1417
- PARSE_OPT_NOARG),
1427
OPT_PASSTHRU_ARGV(0, "committer-date-is-author-date",
1428
&options.git_am_opts, NULL,
1429
N_("passed to 'git am'"), PARSE_OPT_NOARG),
@@ -1422,6 +1431,8 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
1431
N_("passed to 'git am'"), PARSE_OPT_NOARG),
1432
OPT_PASSTHRU_ARGV('C', NULL, &options.git_am_opts, N_("n"),
1433
N_("passed to 'git apply'"), 0),
1434
+ OPT_BOOL(0, "ignore-whitespace", &options.ignore_whitespace,
1435
+ N_("ignore changes in whitespace")),
1436
OPT_PASSTHRU_ARGV(0, "whitespace", &options.git_am_opts,
1437
N_("action"), N_("passed to 'git apply'"), 0),
1438
OPT_BIT('f', "force-rebase", &options.flags,
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/t3433-rebase-options-compatibility.sh
new
+65
@@ -0,0 +1,65 @@
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
+# This is a special case in which both am and interactive backends
11
+# provide the same output. It was done intentionally because
12
+# both the backends fall short of optimal behaviour.
13
+test_expect_success 'setup' '
14
+ git checkout -b topic &&
15
+ q_to_tab >file <<-\EOF &&
16
+ line 1
17
+ Qline 2
18
+ line 3
19
+ EOF
20
+ git add file &&
21
+ git commit -m "add file" &&
22
+ cat >file <<-\EOF &&
23
+ line 1
24
+ new line 2
25
+ line 3
26
+ EOF
27
+ git commit -am "update file" &&
28
+ git tag side &&
29
+
30
+ git checkout --orphan master &&
31
+ sed -e "s/^|//" >file <<-\EOF &&
32
+ |line 1
33
+ | line 2
34
+ |line 3
35
+ EOF
36
+ git add file &&
37
+ git commit -m "add file" &&
38
+ git tag main
39
+'
40
+
41
+test_expect_success '--ignore-whitespace works with am backend' '
42
+ cat >expect <<-\EOF &&
43
+ line 1
44
+ new line 2
45
+ line 3
46
+ EOF
47
+ test_must_fail git rebase main side &&
48
+ git rebase --abort &&
49
+ git rebase --ignore-whitespace main side &&
50
+ test_cmp expect file
51
+'
52
+
53
+test_expect_success '--ignore-whitespace works with interactive backend' '
54
+ cat >expect <<-\EOF &&
55
+ line 1
56
+ new line 2
57
+ line 3
58
+ EOF
59
+ test_must_fail git rebase --merge main side &&
60
+ git rebase --abort &&
61
+ git rebase --merge --ignore-whitespace main side &&
62
+ test_cmp expect file
63
+'
64
+
65
+test_done