Skip to content

Worktrees() reports a worktree on an unborn branch as sitting at commit 0000000… instead of Head = null #165

Description

@matt-edmondson

What's wrong

In a repository with no commits yet, git worktree list --porcelain still prints a HEAD line, and its value is the null object id. Reproduced with git 2.43 on a freshly git init-ed repository:

worktree /tmp/ub
HEAD 0000000000000000000000000000000000000000
branch refs/heads/master

GitWorktreeParser passes that value straight into GitCommitSha, whose regex ^[0-9a-fA-F]{4,64}$ accepts forty zeros:

So GitWorktree.Head comes back looking like a real commit id. That contradicts two documented intents:

  • GitWorktree.Head's documentation says null means "git reported none".
  • The worktrees design makes Head nullable so the library never invents a value.

The all-zero id is git's sentinel for "no commit". It is not a commit.

Failure scenarios

  1. A launcher lists worktrees right after Init() and passes worktree.Head to Log().ForRevision(...) or RevParse(...). Git fails with bad revision '0000000…', and nothing in the returned model warned the caller.
  2. Two worktrees on different unborn branches report equal Head values, so a caller comparing heads wrongly concludes they are at the same commit.
  3. A caller checking Head is null to detect "nothing to show" never sees null in this case.

Precedent in this repository

GitSubmoduleParser already treats the all-zero id as "none", through IsNullObjectId (GitIntegration/Parsing/GitSubmoduleParser.cs around L300, added for #103). It checks every character is a zero, so the 64-character SHA-256 form is covered too. The worktree parser does not reuse it.

Suggested fix

  • Move IsNullObjectId into GitParseValues or another shared internal helper.
  • Use it in GitWorktreeParser, so an all-zero HEAD yields Head = null.
  • Update the GitWorktree.Head remarks to say an unborn branch also reports null.

Acceptance criteria

  • Parser tests for an all-zero HEAD in both the 40-character and 64-character forms.
  • An integration test that calls Worktrees() on a freshly initialised repository and gets Head == null.

This is separate from #141, which covers newline paths and C-quoted lock/prunable reasons in the same parser.

Activity

  1. matt-edmondson commented on Sep 29, 2026

    @matt-edmondson
    ContributorAuthor

    Triage


    Generated by Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions