Skip to content

rev-parse: honor .git/info/grafts when resolving commit parents#45

Open
mizchi wants to merge 1 commit into
mainfrom
claude/fix-grafts
Open

rev-parse: honor .git/info/grafts when resolving commit parents#45
mizchi wants to merge 1 commit into
mainfrom
claude/fix-grafts

Conversation

@mizchi
Copy link
Copy Markdown
Member

@mizchi mizchi commented May 16, 2026

Summary

Fix the large graft octopus subtest in upstream t6101-rev-parse-parents:
rev-parse now honours .git/info/grafts when resolving commit parents
through ^N / ~N suffixes. The known-breakage patch that gated the
assertion behind a BIT_GRAFTS prereq is removed; the subtest runs
verbatim and passes.

What changed

The graft file at <git_dir>/info/grafts contains one entry per
non-comment line: <commit-id> <parent-id> <parent-id>.... When a line
matches the commit being resolved, its parents replace the commit's
natural parents.

Two commit_nth_parent implementations needed the same treatment:

  • src/lib/revparse.mbt (reached via @bitlib).
  • src/repo_ops/revparse_ops.mbt (reached from git rev-parse in
    src/cmd/bit/rev_parse.mbt via @bitrepo — this is what t6101's
    git rev-parse --verify b1^30 actually hits).

Each grew a small revparse_read_graft_parents helper that parses the
graft file once and git_dir was threaded into commit_nth_parent.
The caret/tilde walkers fall back to info.parents when no graft
applies, so non-grafted repos see no behaviour change.

src/repo_ops/moon.pkg gained an import of mizchi/bit/string_utils
for the existing trim_string/whitespace handling used by the new
helper.

Why two implementations?

src/lib/revparse.mbt and src/repo_ops/revparse_ops.mbt are both
public APIs (@bitlib.rev_parse vs @bitrepo.rev_parse), used by
different downstreams. Consolidating them is out of scope for this
fix.

Test plan

  • t6101-rev-parse-parents.sh subtest fix: implement SSH clone with native interactive protocol #17 (large graft octopus):
    SKIP → PASS under the strict shim. Other subtests unchanged
    (one pre-existing unrelated failure: rev-list merge^-3 (invalid parent)).
  • Manual repro: 40 orphan commits, single 40-OID grafts line, then
    git rev-parse --verify b1^30 returns b31's hex.
  • CI git-compat shards remain green.

https://claude.ai/code/session_01M3TPgeGLDKQxep3AAYpDVs


Generated by Claude Code

The "large graft octopus" subtest in upstream t6101 sets up 40 orphan
commits and grafts them into a chain via `.git/info/grafts` (one
40-OID line declaring commit b1's parents as b2..b40), then asserts
`rev-parse --verify b1^30 == b31`. bit's rev-parse ignored grafts and
read parents straight from the commit object, so the 30th parent
lookup failed.

The graft file lives at `<git_dir>/info/grafts`. Each non-comment line
is `<commit-id> <parent-id> <parent-id>...`. If a line matches the
commit being resolved, its parents replace the commit's natural
parents.

Both `commit_nth_parent` implementations need the fix:

- `src/lib/revparse.mbt` (used by lib/cmd consumers that go through
  `@bitlib`).
- `src/repo_ops/revparse_ops.mbt` (the implementation reached from
  `git rev-parse` in cmd/bit/rev_parse.mbt via `@bitrepo`).

Each grew a `revparse_read_graft_parents` helper that parses the
graft file and a thread of `git_dir` into `commit_nth_parent`. The
caret (`^N`) and tilde (`~N`) suffix walkers now resolve parents via
the grafted list when one exists, falling back to `info.parents`
otherwise.

The known-breakage patch `tools/git-patches/t6101-rev-parse-parents-grafts.patch`
(which gated the assertion behind a `BIT_GRAFTS` prereq that nothing
sets) is removed; upstream's test now runs verbatim and passes.

Verified locally: t6101 subtest #17 "large graft octopus" goes from
SKIP (with patch) to PASS (without patch + this fix).

https://claude.ai/code/session_01M3TPgeGLDKQxep3AAYpDVs
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants