rebase: add a config option for --no-fork-point

Some users (myself included) would prefer to have this feature off by default because it can silently drop commits. Signed-off-by: Alex Henrie <alexhenrie24@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Alex Henrie committed Feb 23, 2021 at 00:18 UTC 2803d800d2268cde4b932fab38dffe6712d86d16
3 files changed +61 -17
Documentation/config/rebase.txt
+3
@@ -68,3 +68,6 @@ rebase.rescheduleFailedExec::
68 Automatically reschedule `exec` commands that failed. This only makes
69 sense in interactive mode (or when an `--exec` option was provided).
70 This is the same as specifying the `--reschedule-failed-exec` option.
71 +
72 +rebase.forkPoint::
73 + If set to false set `--no-fork-point` option by default.
builtin/rebase.c
+13 -7
@@ -102,6 +102,7 @@ struct rebase_options {
102 int reschedule_failed_exec;
103 int use_legacy_rebase;
104 int reapply_cherry_picks;
105 + int fork_point;
106 };
107
108 #define REBASE_OPTIONS_INIT { \
@@ -111,7 +112,8 @@ struct rebase_options {
112 .default_backend = "merge", \
113 .flags = REBASE_NO_QUIET, \
114 .git_am_opts = STRVEC_INIT, \
114 - .git_format_patch_opt = STRBUF_INIT \
115 + .git_format_patch_opt = STRBUF_INIT, \
116 + .fork_point = -1, \
117 }
118
119 static struct replay_opts get_replay_opts(const struct rebase_options *opts)
@@ -1095,6 +1097,11 @@ static int rebase_config(const char *var, const char *value, void *data)
1097 return 0;
1098 }
1099
1100 + if (!strcmp(var, "rebase.forkpoint")) {
1101 + opts->fork_point = git_config_bool(var, value) ? -1 : 0;
1102 + return 0;
1103 + }
1104 +
1105 if (!strcmp(var, "rebase.usebuiltin")) {
1106 opts->use_legacy_rebase = !git_config_bool(var, value);
1107 return 0;
@@ -1306,7 +1313,6 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
1313 const char *gpg_sign = NULL;
1314 struct string_list exec = STRING_LIST_INIT_NODUP;
1315 const char *rebase_merges = NULL;
1309 - int fork_point = -1;
1316 struct string_list strategy_options = STRING_LIST_INIT_NODUP;
1317 struct object_id squash_onto;
1318 char *squash_onto_name = NULL;
@@ -1406,7 +1412,7 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
1412 N_("mode"),
1413 N_("try to rebase merges instead of skipping them"),
1414 PARSE_OPT_OPTARG, NULL, (intptr_t)""},
1409 - OPT_BOOL(0, "fork-point", &fork_point,
1415 + OPT_BOOL(0, "fork-point", &options.fork_point,
1416 N_("use 'merge-base --fork-point' to refine upstream")),
1417 OPT_STRING('s', "strategy", &options.strategy,
1418 N_("strategy"), N_("use the given merge strategy")),
@@ -1494,7 +1500,7 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
1500 die(_("cannot combine '--keep-base' with '--root'"));
1501 }
1502
1497 - if (options.root && fork_point > 0)
1503 + if (options.root && options.fork_point > 0)
1504 die(_("cannot combine '--root' with '--fork-point'"));
1505
1506 if (action != ACTION_NONE && !in_progress)
@@ -1840,8 +1846,8 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
1846 NULL);
1847 if (!options.upstream_name)
1848 error_on_missing_default_upstream();
1843 - if (fork_point < 0)
1844 - fork_point = 1;
1849 + if (options.fork_point < 0)
1850 + options.fork_point = 1;
1851 } else {
1852 options.upstream_name = argv[0];
1853 argc--;
@@ -1945,7 +1951,7 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
1951 } else
1952 BUG("unexpected number of arguments left to parse");
1953
1948 - if (fork_point > 0) {
1954 + if (options.fork_point > 0) {
1955 struct commit *head =
1956 lookup_commit_reference(the_repository,
1957 &options.orig_head);
t/t3431-rebase-fork-point.sh
+45 -10
@@ -26,19 +26,23 @@ test_expect_success setup '
26 test_commit G
27 '
28
29 +do_test_rebase () {
30 + expected="$1" &&
31 + shift &&
32 + git checkout master &&
33 + git reset --hard E &&
34 + git checkout side &&
35 + git reset --hard G &&
36 + git rebase $* &&
37 + test_write_lines $expected >expect &&
38 + git log --pretty=%s >actual &&
39 + test_cmp expect actual
40 +}
41 +
42 test_rebase () {
43 expected="$1" &&
44 shift &&
32 - test_expect_success "git rebase $*" "
33 - git checkout master &&
34 - git reset --hard E &&
35 - git checkout side &&
36 - git reset --hard G &&
37 - git rebase $* &&
38 - test_write_lines $expected >expect &&
39 - git log --pretty=%s >actual &&
40 - test_cmp expect actual
41 - "
45 + test_expect_success "git rebase $*" "do_test_rebase '$expected' $*"
46 }
47
48 test_rebase 'G F E D B A'
@@ -74,4 +78,35 @@ test_expect_success 'git rebase --fork-point with ambigous refname' '
78 test_must_fail git rebase --fork-point --onto D one
79 '
80
81 +test_expect_success '--fork-point and --root both given' '
82 + test_must_fail git rebase --fork-point --root 2>err &&
83 + test_i18ngrep "cannot combine" err
84 +'
85 +
86 +test_expect_success 'rebase.forkPoint set to false' '
87 + test_config rebase.forkPoint false &&
88 + do_test_rebase "G F C E D B A"
89 +'
90 +
91 +test_expect_success 'rebase.forkPoint set to false and then to true' '
92 + test_config_global rebase.forkPoint false &&
93 + test_config rebase.forkPoint true &&
94 + do_test_rebase "G F E D B A"
95 +'
96 +
97 +test_expect_success 'rebase.forkPoint set to false and command line says --fork-point' '
98 + test_config rebase.forkPoint false &&
99 + do_test_rebase "G F E D B A" --fork-point
100 +'
101 +
102 +test_expect_success 'rebase.forkPoint set to true and command line says --no-fork-point' '
103 + test_config rebase.forkPoint true &&
104 + do_test_rebase "G F C E D B A" --no-fork-point
105 +'
106 +
107 +test_expect_success 'rebase.forkPoint set to true and --root given' '
108 + test_config rebase.forkPoint true &&
109 + git rebase --root
110 +'
111 +
112 test_done