rebase: fix incompatiblity checks for --[no-]reapply-cherry-picks

--[no-]reapply-cherry-picks was traditionally only supported by the sequencer. Support was added for the apply backend, when --keep-base is also specified, in commit ce5238a690 ("rebase --keep-base: imply --reapply-cherry-picks", 2022-10-17). Make the code error out when --[no-]reapply-cherry-picks is specified AND the apply backend is used AND --keep-base is not specified. Also, clarify a number of comments surrounding the interaction of these flags. Helped-by: Phillip Wood <phillip.wood@dunelm.org.uk> 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 ffeaca177ac789942b1db95c334d0eff9c8f12a5
3 files changed +32 -14
Documentation/git-rebase.txt
+1 -1
@@ -650,7 +650,7 @@ are incompatible with the following options:
650 * --exec
651 * --no-keep-empty
652 * --empty=
653 - * --reapply-cherry-picks
653 + * --[no-]reapply-cherry-picks when used without --keep-base
654 * --edit-todo
655 * --update-refs
656 * --root when used without --onto
builtin/rebase.c
+21 -13
@@ -1224,13 +1224,6 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
1224 if (options.fork_point < 0)
1225 options.fork_point = 0;
1226 }
1227 - /*
1228 - * --keep-base defaults to --reapply-cherry-picks to avoid losing
1229 - * commits when using this option.
1230 - */
1231 - if (options.reapply_cherry_picks < 0)
1232 - options.reapply_cherry_picks = keep_base;
1233 -
1227 if (options.root && options.fork_point > 0)
1228 die(_("options '%s' and '%s' cannot be used together"), "--root", "--fork-point");
1229
@@ -1406,12 +1399,27 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
1399 if (options.empty != EMPTY_UNSPECIFIED)
1400 imply_merge(&options, "--empty");
1401
1409 - /*
1410 - * --keep-base implements --reapply-cherry-picks by altering upstream so
1411 - * it works with both backends.
1412 - */
1413 - if (options.reapply_cherry_picks && !keep_base)
1414 - imply_merge(&options, "--reapply-cherry-picks");
1402 + if (options.reapply_cherry_picks < 0)
1403 + /*
1404 + * We default to --no-reapply-cherry-picks unless
1405 + * --keep-base is given; when --keep-base is given, we want
1406 + * to default to --reapply-cherry-picks.
1407 + */
1408 + options.reapply_cherry_picks = keep_base;
1409 + else if (!keep_base)
1410 + /*
1411 + * The apply backend always searches for and drops cherry
1412 + * picks. This is often not wanted with --keep-base, so
1413 + * --keep-base allows --reapply-cherry-picks to be
1414 + * simulated by altering the upstream such that
1415 + * cherry-picks cannot be detected and thus all commits are
1416 + * reapplied. Thus, --[no-]reapply-cherry-picks is
1417 + * supported when --keep-base is specified, but not when
1418 + * --keep-base is left out.
1419 + */
1420 + imply_merge(&options, options.reapply_cherry_picks ?
1421 + "--reapply-cherry-picks" :
1422 + "--no-reapply-cherry-picks");
1423
1424 if (gpg_sign)
1425 options.gpg_sign_opt = xstrfmt("-S%s", gpg_sign);
t/t3422-rebase-incompatible-options.sh
+10
@@ -60,6 +60,16 @@ test_rebase_am_only () {
60 test_must_fail git rebase $opt --exec 'true' A
61 "
62
63 + test_expect_success "$opt incompatible with --no-reapply-cherry-picks" "
64 + git checkout B^0 &&
65 + test_must_fail git rebase $opt --no-reapply-cherry-picks A
66 + "
67 +
68 + test_expect_success "$opt incompatible with --reapply-cherry-picks" "
69 + git checkout B^0 &&
70 + test_must_fail git rebase $opt --reapply-cherry-picks A
71 + "
72 +
73 test_expect_success "$opt incompatible with --update-refs" "
74 git checkout B^0 &&
75 test_must_fail git rebase $opt --update-refs A