Monorepo management for opam overlays
0
fork

Configure Feed

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

Document push semantics in man page

Explain the three-stage pipeline (split → checkout → upstream),
tree-hash projection, auto-force on local checkouts with tree
containment, and multi-monorepo workflow (each monorepo is a fork,
conflict resolution happens at the monorepo level).

Updated --force doc: only affects upstream remotes, not local checkouts.

+41 -11
+41 -11
bin/cmd_push.ml
··· 4 4 [ 5 5 `S Manpage.s_description; 6 6 `P 7 - "Exports changes from your monorepo to upstream git repositories. This \ 8 - is how you publish your work."; 7 + "Exports changes from your monorepo to upstream git repositories. Each \ 8 + subdirectory is split into an independent commit history and pushed to \ 9 + its upstream remote."; 9 10 `S "WORKFLOW"; 10 11 `P "After making and committing changes in mono/:"; 11 12 `Pre ··· 14 15 monopam push"; 15 16 `S "WHAT IT DOES"; 16 17 `I ("1.", "Validates that the monorepo has no uncommitted changes"); 17 - `I ("2.", "Exports subtree changes to checkouts (internal)"); 18 - `I ("3.", "Pushes checkouts to their upstream git remotes"); 18 + `I 19 + ( "2.", 20 + "For each package, extracts the subtree commit history using tree-hash \ 21 + projection. Only commits that actually change the subtree are \ 22 + included; commits that modify other packages are skipped." ); 23 + `I 24 + ( "3.", 25 + "Pushes the split history to local checkouts (src/). If the checkout \ 26 + has diverged (e.g. after filter-repo or a split algorithm change) but \ 27 + its tree is a subset of the new split, the push auto-forces. If the \ 28 + checkout has content not in the monorepo, push fails — pull first." ); 29 + `I ("4.", "Pushes checkouts to their upstream git remotes."); 30 + `S "COMMIT METADATA"; 31 + `P 32 + "Split commits preserve the original author, committer, date, and \ 33 + message from the monorepo. This means the split history is a faithful \ 34 + projection of the monorepo history onto each subtree."; 35 + `P 36 + "If multiple monorepos include the same upstream project, each will \ 37 + produce its own split history. The upstream repo accepts pushes from \ 38 + any monorepo as long as they fast-forward from the current HEAD. \ 39 + Conflict resolution happens at the monorepo level: pull upstream \ 40 + changes, resolve conflicts, then push back."; 19 41 `S "OPTIONS"; 20 42 `I 21 43 ( "--local", ··· 23 45 reviewing changes before pushing." ); 24 46 `I 25 47 ( "--clean", 26 - "Clean commit history by removing empty commits from unrelated subtree \ 27 - merges." ); 28 - `I ("--force", "Force push to upstream (use with --clean)."); 48 + "Post-process the split history to remove subtree merge plumbing \ 49 + commits." ); 50 + `I 51 + ( "--force", 52 + "Force push to upstream remotes. Use when the upstream has diverged \ 53 + (e.g. someone pushed directly to the upstream repo). Does not affect \ 54 + local checkout pushes, which auto-force when safe." ); 29 55 `S Manpage.s_examples; 30 56 `P "Push all changes to upstream:"; 31 57 `Pre "monopam push"; 32 58 `P "Push changes for a specific package:"; 33 - `Pre "monopam push eio"; 59 + `Pre "monopam push mylib"; 34 60 `P "Export without pushing (for review):"; 35 61 `Pre "monopam push --local"; 36 - `P "Push with cleaned history:"; 37 - `Pre "monopam push --clean"; 62 + `P "Force push after upstream diverged:"; 63 + `Pre "monopam push --force mylib"; 38 64 ] 39 65 40 66 let local_arg = ··· 51 77 Arg.(value & flag & info [ "clean" ] ~doc) 52 78 53 79 let force_arg = 54 - let doc = "Force push to upstream. Required when using --clean." in 80 + let doc = 81 + "Force push to upstream remotes. Use when the upstream repo has diverged \ 82 + (e.g. someone pushed directly). Local checkout pushes auto-force when \ 83 + safe (tree containment check)." 84 + in 55 85 Arg.(value & flag & info [ "force" ] ~doc) 56 86 57 87 let pp_success ~local_only ~elapsed =