git/list[1] front-page[2] threads[3] people[4] search[5] about
 

[PATCH v2 1/1] rebase --stat: fix when rebasing to an unrelated history

From
Johannes Schindelin via GitGitGadget <gitgitgadget@gmail.com>
Date
Nov 29, 2018, 13:01 UTC
Message-ID
<190c7856ad0c500107d0e063572890c151e4eae7.1543496511.git.gitgitgadget@gmail.com>
In-Reply-To
<pull.88.v2.git.gitgitgadget@gmail.com>
From: Johannes Schindelin <johannes.schindelin@gmx.de>

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>
---
 builtin/rebase.c          | 18 ++++++++++++------
 git-legacy-rebase.sh      | 10 ++++++++--
 t/t3406-rebase-message.sh | 10 ++++++++++
 3 files changed, 30 insertions(+), 8 deletions(-)
diff --git a/builtin/rebase.c b/builtin/rebase.c
index 5b3e5baec8..1c6f817f4b 100644
--- a/builtin/rebase.c
+++ b/builtin/rebase.c
@@ -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);
 	}
diff --git a/git-legacy-rebase.sh b/git-legacy-rebase.sh
index b97ffdc9dd..b4c7dbfa57 100755
--- a/git-legacy-rebase.sh
+++ b/git-legacy-rebase.sh
@@ -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
diff --git a/t/t3406-rebase-message.sh b/t/t3406-rebase-message.sh
index 38bd876cab..c2c9950568 100755
--- a/t/t3406-rebase-message.sh
+++ b/t/t3406-rebase-message.sh
@@ -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
-- 
gitgitgadget
Previous: Johannes Schindelin via GitGitGadget
Message 7 of 7 in “Fix git rebase --stat -i <unrelated-history>”
  1. 0/1 Fix git rebase --stat -i <unrelated-history>Johannes Schindelin via GitGitGadget, Nov 27, 2018
  2. 1/1 rebase --stat: fix when rebasing to an unrelated historyJohannes Schindelin via GitGitGadget, Nov 27, 2018
  3. Junio C HamanoNov 29, 2018
  4. Johannes SchindelinNov 29, 2018
  5. Junio C HamanoNov 30, 2018
  6. 0/1 Fix git rebase --stat -i <unrelated-history>Johannes Schindelin via GitGitGadget, Nov 29, 2018
  7. 1/1 rebase --stat: fix when rebasing to an unrelated historyJohannes Schindelin via GitGitGadget, Nov 29, 2018

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.