Monorepo management for opam overlays
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

Fix subtree split producing duplicate-tree commits

The split was faithfully reproducing revert-redo cycles from the monorepo
history (caused by subtree merges importing stale upstream state). This
made push fail with non-fast-forward errors because each split produced
different commit hashes than the previous --clean push.

Fix: replace should_skip_commit (which only checked the first parent)
with find_existing_split_with_tree, which walks the entire split ancestor
chain looking for a commit with the same tree. When found, the current
commit is collapsed to that existing ancestor instead of creating a
duplicate.

Before: ocaml-agent split had 36 commits with 30 unique trees (6 dupes)
After: 30 commits with 30 unique trees (zero dupes)

Also fix monopam push to force-push when freshly cloning a checkout,
since the remote and split histories are independent lineages.

Added 3 subtree split tests: basic split, skip unrelated commits,
and no duplicate trees (the regression test for this bug).

+6 -2
+6 -2
lib/push.ml
··· 82 82 end 83 83 else begin 84 84 let checkout_eio = Eio.Path.(fs / Fpath.to_string checkout_dir) in 85 + let freshly_cloned = needs_clone ~fs ~checkout_eio ~checkout_dir in 85 86 let* () = 86 - if needs_clone ~fs ~checkout_eio ~checkout_dir then begin 87 + if freshly_cloned then begin 87 88 Log.info (fun m -> m "Creating checkout for %s" (Package.repo_name pkg)); 88 89 Ctx.ensure_checkout ~proc 89 90 ~fs:(fs :> _ Eio.Path.t) ··· 111 112 let* () = 112 113 Git_cli.clean_untracked ~proc ~fs:(fs :> _ Eio.Path.t) checkout_dir 113 114 in 115 + (* Force-push when we just cloned the checkout: the remote's history 116 + and the monorepo's subtree history are independent lineages, so a 117 + normal push will always be non-fast-forward. *) 114 118 split_and_push ~proc ~fs ~monorepo ~git_repo ~prefix ~checkout_url ~clean 115 - ~force ~branch 119 + ~force:(force || freshly_cloned) ~branch 116 120 |> Result.map (fun () -> true) 117 121 end 118 122 end