Stop drawing a line below root commits in the commit graph

If a root commit isn't the last one in the list, the graph draws a
vertical line below it in every row that follows. A root commit's pipe
to the empty tree never terminates, because no commit comes after it,
so it is carried on from row to row. The line also takes up its column,
and an unrelated commit after the root commit is placed to the right of
it.

Drop that pipe after the root commit's row. In its own row, it still
gives the commit symbol the style of the commit. Also, place a commit
that no line leads to next to the lines that go on into its row, not
next to the lines that ended in the row before. Their columns are free
again.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Stefan Haller
2026-10-04 18:47:01 +02:00
co-authored by Claude Opus 5.5
parent cee602c029
commit 91378b1e8a
2 changed files with 8 additions and 26 deletions
+8 -9
View File
@@ -107,19 +107,18 @@ func RenderAux(pipeSets [][]Pipe, commits []*models.Commit, selectedCommitHashPt
}
func getNextPipes(prevPipes []Pipe, commit *models.Commit, getStyle func(c *models.Commit) *style.TextStyle) []Pipe {
maxPos := int16(0)
for _, pipe := range prevPipes {
if pipe.toPos > maxPos {
maxPos = pipe.toPos
}
}
// a pipe that terminated in the previous line has no bearing on the current line
// so we'll filter those out
// so we'll filter those out. The same goes for the pipe from a root commit to
// the empty tree, because no commit comes after a root commit.
currentPipes := lo.Filter(prevPipes, func(pipe Pipe, _ int) bool {
return pipe.kind != TERMINATES
return pipe.kind != TERMINATES && !equalHashes(pipe.toHash, &EmptyTreeCommitHash)
})
maxPos := int16(-1)
for _, pipe := range currentPipes {
maxPos = max(maxPos, pipe.toPos)
}
newPipes := make([]Pipe, 0, len(currentPipes)+len(commit.ParentPtrs()))
// start by assuming that we've got a brand new commit not related to any preceding commit.
// (this only happens when we're doing `git log --all`). These will be tacked onto the far end.
-17
View File
@@ -102,18 +102,11 @@ func TestRenderCommitGraph(t *testing.T) {
{Hash: "A", Parents: []string{"B"}},
{Hash: "B"},
},
/* EXPECTED:
expectedOutput: `
1 ○
2 ○
A ○
B ○`,
ACTUAL: */
expectedOutput: `
1 ○
2 ○
A │ ○
B │ ○`,
},
{
name: "with a merge of an unrelated history",
@@ -123,18 +116,11 @@ func TestRenderCommitGraph(t *testing.T) {
{Hash: "A"},
{Hash: "3"},
},
/* EXPECTED:
expectedOutput: `
1 ◎─╮
2 ○ │
A │ ○
3 ○`,
ACTUAL: */
expectedOutput: `
1 ◎─╮
2 ○ │
A │ ○
3 ○ │`,
},
{
name: "with a path that has room to move to the left and continues",
@@ -570,10 +556,7 @@ func TestGetNextPipes(t *testing.T) {
Parents: []string{},
}),
expected: []Pipe{
/* EXPECTED:
{fromPos: 0, toPos: 0, fromHash: pool("root"), toHash: pool(models.EmptyTreeCommitHash), kind: STARTS, style: &style.FgDefault},
ACTUAL: */
{fromPos: 1, toPos: 1, fromHash: pool("root"), toHash: pool(models.EmptyTreeCommitHash), kind: STARTS, style: &style.FgDefault},
},
},
}