Update docs, changelog, examples, and add ADRs for v1.2
- Add v1.1.0 and v1.2.0 changelog entries - Add exclude field to config reference and example config - Add ADRs documenting all major design decisions - Fix step numbering in reverse_sync() - Fix action.yml to copy VERSION file - Add dist/ and .env to .gitignore - Use refs/tags/ format for Nix flake tag refs Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
42
docs/adr/008-first-parent-ordering.md
Normal file
42
docs/adr/008-first-parent-ordering.md
Normal file
@@ -0,0 +1,42 @@
|
||||
# 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.
|
||||
|
||||
```bash
|
||||
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.
|
||||
Reference in New Issue
Block a user