git-rebase: error out when incompatible options passed
authorElijah Newren <newren@gmail.com>
Wed, 27 Jun 2018 07:23:14 +0000 (00:23 -0700)
committerJunio C Hamano <gitster@pobox.com>
Wed, 27 Jun 2018 18:23:22 +0000 (11:23 -0700)
git rebase has three different types: am, merge, and interactive, all of
which are implemented in terms of separate scripts. am builds on git-am,
merge builds on git-merge-recursive, and interactive builds on
git-cherry-pick. We make use of features in those lower-level commands in
the different rebase types, but those features don't exist in all of the
lower level commands so we have a range of incompatibilities. Previously,
we just accepted nearly any argument and silently ignored whichever ones
weren't implemented for the type of rebase specified. Change this so the
incompatibilities are documented, included in the testsuite, and tested
for at runtime with an appropriate error message shown.

Some exceptions I left out:

* --merge and --interactive are technically incompatible since they are
supposed to run different underlying scripts, but with a few small
changes, --interactive can do everything that --merge can. In fact,
I'll shortly be sending another patch to remove git-rebase--merge and
reimplement it on top of git-rebase--interactive.

* One could argue that --interactive and --quiet are incompatible since
--interactive doesn't implement a --quiet mode (perhaps since
cherry-pick itself does not implement one). However, the interactive
mode is more quiet than the other modes in general with progress
messages, so one could argue that it's already quiet.

Signed-off-by: Elijah Newren <newren@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
git-rebase.sh
t/t3422-rebase-incompatible-options.sh
index bf71b7fa203138b00dcaf90368d5c03b65d301ee..18ac8226c4e7f3fb581f62eaa2bde487d5d5dd22 100755 (executable)
@@ -503,6 +503,24 @@ then
        git_format_patch_opt="$git_format_patch_opt --progress"
 fi
 
+if test -n "$git_am_opt"; then
+       incompatible_opts=$(echo " $git_am_opt " | \
+                           sed -e 's/ -q / /g' -e 's/^ \(.*\) $/\1/')
+       if test -n "$interactive_rebase"
+       then
+               if test -n "$incompatible_opts"
+               then
+                       die "$(gettext "error: cannot combine interactive options (--interactive, --exec, --rebase-merges, --preserve-merges, --keep-empty, --root + --onto) with am options ($incompatible_opts)")"
+               fi
+       fi
+       if test -n "$do_merge"; then
+               if test -n "$incompatible_opts"
+               then
+                       die "$(gettext "error: cannot combine merge options (--merge, --strategy, --strategy-option) with am options ($incompatible_opts)")"
+               fi
+       fi
+fi
+
 if test -n "$signoff"
 then
        test -n "$preserve_merges" &&
@@ -511,6 +529,23 @@ then
        force_rebase=t
 fi
 
+if test -n "$preserve_merges"
+then
+       # Note: incompatibility with --signoff handled in signoff block above
+       # Note: incompatibility with --interactive is just a strong warning;
+       #       git-rebase.txt caveats with "unless you know what you are doing"
+       test -n "$rebase_merges" &&
+               die "$(gettext "error: cannot combine '--preserve_merges' with '--rebase-merges'")"
+fi
+
+if test -n "$rebase_merges"
+then
+       test -n "$strategy_opts" &&
+               die "$(gettext "error: cannot combine '--rebase_merges' with '--strategy-option'")"
+       test -n "$strategy" &&
+               die "$(gettext "error: cannot combine '--rebase_merges' with '--strategy'")"
+fi
+
 if test -z "$rebase_root"
 then
        case "$#" in
index b007a15eba2be253375967947670003493e69cce..bb78a6ec86d3a86f7c1e872981b7952f2293274b 100755 (executable)
@@ -33,27 +33,27 @@ test_expect_success 'setup' '
 test_rebase_am_only () {
        opt=$1
        shift
-       test_expect_failure "$opt incompatible with --merge" "
+       test_expect_success "$opt incompatible with --merge" "
                git checkout B^0 &&
                test_must_fail git rebase $opt --merge A
        "
 
-       test_expect_failure "$opt incompatible with --strategy=ours" "
+       test_expect_success "$opt incompatible with --strategy=ours" "
                git checkout B^0 &&
                test_must_fail git rebase $opt --strategy=ours A
        "
 
-       test_expect_failure "$opt incompatible with --strategy-option=ours" "
+       test_expect_success "$opt incompatible with --strategy-option=ours" "
                git checkout B^0 &&
                test_must_fail git rebase $opt --strategy-option=ours A
        "
 
-       test_expect_failure "$opt incompatible with --interactive" "
+       test_expect_success "$opt incompatible with --interactive" "
                git checkout B^0 &&
                test_must_fail git rebase $opt --interactive A
        "
 
-       test_expect_failure "$opt incompatible with --exec" "
+       test_expect_success "$opt incompatible with --exec" "
                git checkout B^0 &&
                test_must_fail git rebase $opt --exec 'true' A
        "
@@ -70,17 +70,17 @@ test_expect_success '--preserve-merges incompatible with --signoff' '
        test_must_fail git rebase --preserve-merges --signoff A
 '
 
-test_expect_failure '--preserve-merges incompatible with --rebase-merges' '
+test_expect_success '--preserve-merges incompatible with --rebase-merges' '
        git checkout B^0 &&
        test_must_fail git rebase --preserve-merges --rebase-merges A
 '
 
-test_expect_failure '--rebase-merges incompatible with --strategy' '
+test_expect_success '--rebase-merges incompatible with --strategy' '
        git checkout B^0 &&
        test_must_fail git rebase --rebase-merges -s resolve A
 '
 
-test_expect_failure '--rebase-merges incompatible with --strategy-option' '
+test_expect_success '--rebase-merges incompatible with --strategy-option' '
        git checkout B^0 &&
        test_must_fail git rebase --rebase-merges -Xignore-space-change A
 '