rebase --stat: fix when rebasing to an unrelated history

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>
This commit is contained in:
Johannes Schindelin 2018-11-29 05:01:54 -08:00 committed by Junio C Hamano
parent 7068cbc4ab
commit 8797f0f008
3 changed files with 30 additions and 8 deletions

View File

@ -1481,10 +1481,15 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
if (options.flags & REBASE_DIFFSTAT) { if (options.flags & REBASE_DIFFSTAT) {
struct diff_options opts; struct diff_options opts;
if (options.flags & REBASE_VERBOSE) 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"), printf(_("Changes from %s to %s:\n"),
oid_to_hex(&merge_base), oid_to_hex(&merge_base),
oid_to_hex(&options.onto->object.oid)); oid_to_hex(&options.onto->object.oid));
}
/* We want color (if set), but no pager */ /* We want color (if set), but no pager */
diff_setup(&opts); diff_setup(&opts);
@ -1494,8 +1499,9 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
DIFF_FORMAT_SUMMARY | DIFF_FORMAT_DIFFSTAT; DIFF_FORMAT_SUMMARY | DIFF_FORMAT_DIFFSTAT;
opts.detect_rename = DIFF_DETECT_RENAME; opts.detect_rename = DIFF_DETECT_RENAME;
diff_setup_done(&opts); diff_setup_done(&opts);
diff_tree_oid(&merge_base, &options.onto->object.oid, diff_tree_oid(is_null_oid(&merge_base) ?
"", &opts); the_hash_algo->empty_tree : &merge_base,
&options.onto->object.oid, "", &opts);
diffcore_std(&opts); diffcore_std(&opts);
diff_flush(&opts); diff_flush(&opts);
} }

View File

@ -718,10 +718,16 @@ if test -n "$diffstat"
then then
if test -n "$verbose" if test -n "$verbose"
then then
if test -z "$mb"
then
echo "$(eval_gettext "Changes to \$onto:")"
else
echo "$(eval_gettext "Changes from \$mb to \$onto:")" echo "$(eval_gettext "Changes from \$mb to \$onto:")"
fi fi
fi
mb_tree="${mb:-$(git hash-object -t tree /dev/null)}"
# We want color (if set), but no pager # 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 fi
test -n "$interactive_rebase" && run_specific_rebase test -n "$interactive_rebase" && run_specific_rebase

View File

@ -91,4 +91,14 @@ test_expect_success 'error out early upon -C<n> or --whitespace=<bad>' '
test_i18ngrep "Invalid whitespace option" err 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 test_done