rebase --stat: fix when rebasing to an unrelated history
authorJohannes Schindelin <johannes.schindelin@gmx.de>
Thu, 29 Nov 2018 13:01:54 +0000 (05:01 -0800)
committerJunio C Hamano <gitster@pobox.com>
Fri, 30 Nov 2018 05:43:00 +0000 (14:43 +0900)
When rebasing to a commit history that has no common commits with the
current branch, there is no merge base. In diffstat mode, this means
that we cannot compare to the merge base, but we have to compare to the
empty tree instead.

Also, if running in verbose diffstat mode, we should not output

Changes from <merge-base> to <onto>

as that does not make sense without any merge base.

Note: neither scripted nor built-in versoin of `git rebase` were
prepared for this situation well. We use this opportunity not only to
fix the bug(s), but also to make both versions' output consistent in
this instance. And add a regression test to keep this working in all
eternity.

Reported-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
builtin/rebase.c
git-legacy-rebase.sh
t/t3406-rebase-message.sh
index 5b3e5baec8a09fb19798c71b201d08f88225e7af..1c6f817f4b7197114729a367c97d1950ac3080a5 100644 (file)
@@ -1481,10 +1481,15 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
        if (options.flags & REBASE_DIFFSTAT) {
                struct diff_options opts;
 
-               if (options.flags & REBASE_VERBOSE)
-                       printf(_("Changes from %s to %s:\n"),
-                               oid_to_hex(&merge_base),
-                               oid_to_hex(&options.onto->object.oid));
+               if (options.flags & REBASE_VERBOSE) {
+                       if (is_null_oid(&merge_base))
+                               printf(_("Changes to %s:\n"),
+                                      oid_to_hex(&options.onto->object.oid));
+                       else
+                               printf(_("Changes from %s to %s:\n"),
+                                      oid_to_hex(&merge_base),
+                                      oid_to_hex(&options.onto->object.oid));
+               }
 
                /* We want color (if set), but no pager */
                diff_setup(&opts);
@@ -1494,8 +1499,9 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
                        DIFF_FORMAT_SUMMARY | DIFF_FORMAT_DIFFSTAT;
                opts.detect_rename = DIFF_DETECT_RENAME;
                diff_setup_done(&opts);
-               diff_tree_oid(&merge_base, &options.onto->object.oid,
-                             "", &opts);
+               diff_tree_oid(is_null_oid(&merge_base) ?
+                             the_hash_algo->empty_tree : &merge_base,
+                             &options.onto->object.oid, "", &opts);
                diffcore_std(&opts);
                diff_flush(&opts);
        }
index b97ffdc9dd550d8802039d672623f2ba3e7a5f0c..b4c7dbfa575d3b5c664677c22b8613284d2e33fb 100755 (executable)
@@ -718,10 +718,16 @@ if test -n "$diffstat"
 then
        if test -n "$verbose"
        then
-               echo "$(eval_gettext "Changes from \$mb to \$onto:")"
+               if test -z "$mb"
+               then
+                       echo "$(eval_gettext "Changes to \$onto:")"
+               else
+                       echo "$(eval_gettext "Changes from \$mb to \$onto:")"
+               fi
        fi
+       mb_tree="${mb:-$(git hash-object -t tree /dev/null)}"
        # We want color (if set), but no pager
-       GIT_PAGER='' git diff --stat --summary "$mb" "$onto"
+       GIT_PAGER='' git diff --stat --summary "$mb_tree" "$onto"
 fi
 
 test -n "$interactive_rebase" && run_specific_rebase
index 38bd876cabf9757cce439be90c0f1e094225cac3..c2c9950568f27e17d49d166c647dfc8794dd1a35 100755 (executable)
@@ -91,4 +91,14 @@ test_expect_success 'error out early upon -C<n> or --whitespace=<bad>' '
        test_i18ngrep "Invalid whitespace option" err
 '
 
+test_expect_success 'rebase -i onto unrelated history' '
+       git init unrelated &&
+       test_commit -C unrelated 1 &&
+       git -C unrelated remote add -f origin "$PWD" &&
+       git -C unrelated branch --set-upstream-to=origin/master &&
+       git -C unrelated -c core.editor=true rebase -i -v --stat >actual &&
+       test_i18ngrep "Changes to " actual &&
+       test_i18ngrep "5 files changed" actual
+'
+
 test_done