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

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