rebase: provide better error message for apply options vs. merge config

When config which selects the merge backend (currently, rebase.autosquash=true or rebase.updateRefs=true) conflicts with other options on the command line (such as --whitespace=fix), make the error message specifically call out the config option and specify how to override that config option on the command line. Signed-off-by: Elijah Newren <newren@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Elijah Newren committed Jan 25, 2023 at 04:03 UTC eddfcd8eced9b9f840491064b35a3956f959fd12
3 files changed +46 -7
Documentation/git-rebase.txt
+1 -1
@@ -648,7 +648,7 @@ are incompatible with the following options:
648 * --merge
649 * --strategy
650 * --strategy-option
651 - * --[no-]autosquash
651 + * --autosquash
652 * --rebase-merges
653 * --interactive
654 * --exec
builtin/rebase.c
+21 -6
@@ -122,6 +122,8 @@ struct rebase_options {
122 int reapply_cherry_picks;
123 int fork_point;
124 int update_refs;
125 + int config_autosquash;
126 + int config_update_refs;
127 };
128
129 #define REBASE_OPTIONS_INIT { \
@@ -136,6 +138,10 @@ struct rebase_options {
138 .fork_point = -1, \
139 .reapply_cherry_picks = -1, \
140 .allow_empty_message = 1, \
141 + .autosquash = -1, \
142 + .config_autosquash = -1, \
143 + .update_refs = -1, \
144 + .config_update_refs = -1, \
145 }
146
147 static struct replay_opts get_replay_opts(const struct rebase_options *opts)
@@ -778,7 +784,7 @@ static int rebase_config(const char *var, const char *value, void *data)
784 }
785
786 if (!strcmp(var, "rebase.autosquash")) {
781 - opts->autosquash = git_config_bool(var, value);
787 + opts->config_autosquash = git_config_bool(var, value);
788 return 0;
789 }
790
@@ -795,7 +801,7 @@ static int rebase_config(const char *var, const char *value, void *data)
801 }
802
803 if (!strcmp(var, "rebase.updaterefs")) {
798 - opts->update_refs = git_config_bool(var, value);
804 + opts->config_update_refs = git_config_bool(var, value);
805 return 0;
806 }
807
@@ -1366,7 +1372,8 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
1372 if ((options.flags & REBASE_INTERACTIVE_EXPLICIT) ||
1373 (options.action != ACTION_NONE) ||
1374 (options.exec.nr > 0) ||
1369 - options.autosquash) {
1375 + (options.autosquash == -1 && options.config_autosquash == 1) ||
1376 + options.autosquash == 1) {
1377 allow_preemptive_ff = 0;
1378 }
1379 if (options.committer_date_is_author_date || options.ignore_date)
@@ -1499,20 +1506,28 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
1506 if (strcmp(options.git_am_opts.v[i], "-q"))
1507 break;
1508
1502 - if (i >= 0) {
1509 + if (i >= 0 || options.type == REBASE_APPLY) {
1510 if (is_merge(&options))
1511 die(_("apply options and merge options "
1512 "cannot be used together"));
1513 + else if (options.autosquash == -1 && options.config_autosquash == 1)
1514 + die(_("apply options are incompatible with rebase.autosquash. Consider adding --no-autosquash"));
1515 + else if (options.update_refs == -1 && options.config_update_refs == 1)
1516 + die(_("apply options are incompatible with rebase.updateRefs. Consider adding --no-update-refs"));
1517 else
1518 options.type = REBASE_APPLY;
1519 }
1520 }
1521
1511 - if (options.update_refs)
1522 + if (options.update_refs == 1)
1523 imply_merge(&options, "--update-refs");
1524 + options.update_refs = (options.update_refs >= 0) ? options.update_refs :
1525 + ((options.config_update_refs >= 0) ? options.config_update_refs : 0);
1526
1514 - if (options.autosquash)
1527 + if (options.autosquash == 1)
1528 imply_merge(&options, "--autosquash");
1529 + options.autosquash = (options.autosquash >= 0) ? options.autosquash :
1530 + ((options.config_autosquash >= 0) ? options.config_autosquash : 0);
1531
1532 if (options.type == REBASE_UNSPECIFIED) {
1533 if (!strcmp(options.default_backend, "merge"))
t/t3422-rebase-incompatible-options.sh
+24
@@ -94,6 +94,30 @@ test_rebase_am_only () {
94 git checkout B^0 &&
95 test_must_fail git rebase $opt --root A
96 "
97 +
98 + test_expect_success "$opt incompatible with rebase.autosquash" "
99 + git checkout B^0 &&
100 + test_must_fail git -c rebase.autosquash=true rebase $opt A 2>err &&
101 + grep -e --no-autosquash err
102 + "
103 +
104 + test_expect_success "$opt incompatible with rebase.updateRefs" "
105 + git checkout B^0 &&
106 + test_must_fail git -c rebase.updateRefs=true rebase $opt A 2>err &&
107 + grep -e --no-update-refs err
108 + "
109 +
110 + test_expect_success "$opt okay with overridden rebase.autosquash" "
111 + test_when_finished \"git reset --hard B^0\" &&
112 + git checkout B^0 &&
113 + git -c rebase.autosquash=true rebase --no-autosquash $opt A
114 + "
115 +
116 + test_expect_success "$opt okay with overridden rebase.updateRefs" "
117 + test_when_finished \"git reset --hard B^0\" &&
118 + git checkout B^0 &&
119 + git -c rebase.updateRefs=true rebase --no-update-refs $opt A
120 + "
121 }
122
123 # Check options which imply --apply