From: Fernando Ramos <greenfoo@u92.eu>
To: git@vger.kernel.org
Cc: me@ttaylorr.com
Subject: [RFC] Show empty root commits when using --simplify-by-decoration
Date: Sat, 4 Apr 2026 17:17:43 +0200 [thread overview]
Message-ID: <adErl-EdiaXopVx-@x395.localdomain> (raw)
Regarding "--simplify-by-decoration", I found a somewhat unexpected behavior.
Let's say we have a repository with two branches ("master" and "branch") and
this history structure:
a * <master> b * <branch>
| |
2 *------------------'
|
1 *
|
start *
If I now run this...
$ git log --graph --all --oneline --simplify-by-decoration
...I get this (which is expected and ok):
* 0f3892d (branch) b
| * 0c37d8c (master) a
|/
* d783631 Start
HOWEVER, if the root commit ("start") is an empty commit, then the same command
will print this instead:
* 7abc10a (branch) b
* 14d51e1 (master) a
...which is confusing for two reasons:
1. The graph is not showing a common origin.
2. Because "root" commits use an "*", it looks like "a" is the parent of "b",
when the reality is that the graph is showing two independen origins.
Issue (1) seems to be caused by the fact that empty root commits are marked as
TREESAME and thus discarded when showing the graph. This can be fixed with
patch #1 at the end of this email. Note, however, that this patch partially
breaks what Taylor did on 1343c893138 (I say "partially" because it only happens
when using "--simplify-by-decoration"). I have CC'ed Taylor in case he has any
comments about it.
Issue (2) can be "fixed" by using a diferent character (for example "I") for
root commits (ie. those without parents), which can be done with patch #2 at the
end of this email.
With those two patches applied, this is what the output looks like in both cases
(with the root commit being empty or not):
* 7abc10a (branch) b
| * 14d51e1 (master) a
|/
I c0db521 Start
Let me know what you think and whether you want me to send a proper patch that
includes (1) or (2) or (1)+(2).
Thanks!
PS: Path #3 at the end of this emails includes a dummy script to quickly
recreate the two scenarios described above.
--------------------------------------------------------------------------------
Patch #1
--------------------------------------------------------------------------------
diff --git a/revision.c b/revision.c
index c9b8bfd09f..0e7bf2ed3c 100644
--- a/revision.c
+++ b/revision.c
@@ -978,15 +978,17 @@ static void try_to_simplify_commit(struct rev_info *revs, struct commit *commit)
return;
if (!commit->parents) {
- /*
- * Pretend as if we are comparing ourselves to the
- * (non-existent) first parent of this commit object. Even
- * though no such parent exists, its changed-path Bloom filter
- * (if one exists) is relative to the empty tree, using Bloom
- * filters is allowed here.
- */
- if (rev_same_tree_as_empty(revs, commit, 0))
- commit->object.flags |= TREESAME;
+ if (!revs->simplify_by_decoration) {
+ /*
+ * Pretend as if we are comparing ourselves to the
+ * (non-existent) first parent of this commit object. Even
+ * though no such parent exists, its changed-path Bloom filter
+ * (if one exists) is relative to the empty tree, using Bloom
+ * filters is allowed here.
+ */
+ if (rev_same_tree_as_empty(revs, commit, 0))
+ commit->object.flags |= TREESAME;
+ }
return;
}
--------------------------------------------------------------------------------
Patch #2
--------------------------------------------------------------------------------
diff --git a/revision.c b/revision.c
index 31808e3df0..c9b8bfd09f 100644
--- a/revision.c
+++ b/revision.c
@@ -4565,7 +4565,7 @@ const char *get_revision_mark(const struct rev_info *revs, const struct commit *
else
return ">";
} else if (revs->graph)
- return "*";
+ return commit->parents ? "*" : "I";
else if (revs->cherry_mark)
return "+";
return "";
--------------------------------------------------------------------------------
Patch #3
--------------------------------------------------------------------------------
diff --git a/build_example.sh b/build_example.sh
new file mode 100755
index 0000000000..60f63c5344
--- /dev/null
+++ b/build_example.sh
@@ -0,0 +1,61 @@
+#!/bin/bash
+
+################################################################################
+# Example #1
+################################################################################
+#
+# This will create this a repo with this history structure:
+#
+# a * (master) b * (branch)
+# | |
+# 2 * -----------------'
+# |
+# 1 *
+# |
+# start *
+
+rm -rf EXAMPLE1 || true; mkdir -p EXAMPLE1; cd EXAMPLE1
+
+touch start.txt; git init; git add start.txt; git commit -m 'Start'
+touch 1.txt; git add 1.txt; git commit -m '1'
+touch 2.txt; git add 2.txt; git commit -m '2'
+touch a.txt; git add a.txt; git commit -m 'a'
+git checkout -b branch HEAD^
+touch b.txt; git add b.txt; git commit -m 'b'
+
+git log --graph --all --oneline --simplify-by-decoration
+# The previous command will print this, which is what we expected:
+#
+# * 0f3892d (HEAD -> branch) b
+# | * 0c37d8c (master) a
+# |/
+# * d783631 Start
+
+cd ..
+
+
+
+################################################################################
+# Example #2
+################################################################################
+#
+# This will create this a repo with the same structure as before, but this time
+# the root commit ("start") is an empty one.
+
+rm -rf EXAMPLE2 || true; mkdir -p EXAMPLE2; cd EXAMPLE2
+
+git init; git commit --allow-empty -m 'Start'
+touch 1.txt; git add 1.txt; git commit -m '1'
+touch 2.txt; git add 2.txt; git commit -m '2'
+touch a.txt; git add a.txt; git commit -m 'a'
+git checkout -b branch HEAD^
+touch b.txt; git add b.txt; git commit -m 'b'
+
+git log --graph --all --oneline --simplify-by-decoration
+# The previous command will print this, which is unexpected:
+#
+# * 7abc10a (HEAD -> branch) b
+# * 14d51e1 (master) a
+
+cd ..
+
next reply other threads:[~2026-04-04 15:17 UTC|newest]
Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-04-04 15:17 Fernando Ramos [this message]
2026-04-04 16:08 ` [RFC] Show empty root commits when using --simplify-by-decoration Pablo
2026-04-04 20:05 ` Fernando Ramos
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=adErl-EdiaXopVx-@x395.localdomain \
--to=greenfoo@u92.eu \
--cc=git@vger.kernel.org \
--cc=me@ttaylorr.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox