Files
josh-sync/docs/adr/008-first-parent-ordering.md
sync-bot b35703d271 Import josh-sync from subrepo/main
Sync-Origin: import/josh-sync/20260528-041502
2026-05-28 04:15:02 +01:00

2.3 KiB

ADR-008: First-Parent Ordering in Reconciliation Merges

Status: Accepted Date: 2026-02

Context

Josh-proxy uses first-parent traversal when mapping subrepo history back to the monorepo. When you push a commit through josh-proxy, josh walks the first-parent chain to find a commit it can map to a monorepo commit. If the first parent leads to unmappable history, josh cannot reconstruct the monorepo-side branch correctly.

This became critical when the reconciliation merge (ADR-007) initially had the wrong parent order: old subrepo history as parent 1, josh-filtered as parent 2. Josh followed parent 1, couldn't find any mappable commit, and created a monorepo branch containing only the subrepo subfolder content — effectively deleting 1280 files from the rest of the monorepo.

Decision

In reconciliation merge commits, the josh-filtered HEAD must be parent 1 (first parent). The old subrepo HEAD is parent 2.

git commit-tree "$josh_tree" \
  -p "$josh_head" \      # parent 1: josh-filtered — josh follows this
  -p "$subrepo_head" \   # parent 2: old history — side branch, ignored by josh
  -m "..."

Why this is safe

  • The old subrepo HEAD (subrepo_head) is still an ancestor of the merge commit regardless of parent order — push succeeds either way
  • --ancestry-path in reverse sync still follows B → M → C regardless of parent order (it traces all paths, not just first-parent)
  • Josh follows first-parent and finds the josh-filtered commit, which maps cleanly back to the monorepo

Consequences

Positive:

  • Josh can map the reconciliation merge back to the monorepo correctly
  • Reverse sync through josh produces correct diffs (only subrepo-scoped changes)
  • git log --first-parent on the subrepo shows the clean josh-filtered lineage

Negative:

  • This is a subtle invariant — future changes to merge commit creation must preserve parent order
  • The constraint is undocumented in josh-proxy's own documentation (discovered empirically)
  • No automated test can verify this without a running josh-proxy instance

Lesson learned: Parent order in git commit-tree -p is not cosmetic. For tools that rely on first-parent traversal (josh-proxy, git log --first-parent), parent 1 must be the "mainline" that the tool should follow.