{"id":49615103,"url":"https://github.com/mwallner/mergetopus","last_synced_at":"2026-05-04T21:05:49.294Z","repository":{"id":346417267,"uuid":"1189249792","full_name":"mwallner/mergetopus","owner":"mwallner","description":"untangle complex merges","archived":false,"fork":false,"pushed_at":"2026-04-10T20:04:53.000Z","size":843,"stargazers_count":0,"open_issues_count":1,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-04-10T21:31:08.274Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/mwallner.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-03-23T06:00:09.000Z","updated_at":"2026-03-31T05:19:57.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/mwallner/mergetopus","commit_stats":null,"previous_names":["mwallner/mergetopus"],"tags_count":3,"template":false,"template_full_name":null,"purl":"pkg:github/mwallner/mergetopus","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mwallner%2Fmergetopus","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mwallner%2Fmergetopus/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mwallner%2Fmergetopus/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mwallner%2Fmergetopus/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mwallner","download_url":"https://codeload.github.com/mwallner/mergetopus/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mwallner%2Fmergetopus/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32624751,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-04T10:08:07.713Z","status":"ssl_error","status_checked_at":"2026-05-04T10:08:02.005Z","response_time":58,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-05-04T21:05:42.750Z","updated_at":"2026-05-04T21:05:49.284Z","avatar_url":"https://github.com/mwallner.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"# mergetopus\n\n[![Build Linux](https://img.shields.io/github/actions/workflow/status/mwallner/mergetopus/build-linux.yml?branch=main\u0026label=Build%20Linux)](https://github.com/mwallner/mergetopus/actions/workflows/build-linux.yml)\n[![Build Windows](https://img.shields.io/github/actions/workflow/status/mwallner/mergetopus/build-windows.yml?branch=main\u0026label=Build%20Windows)](https://github.com/mwallner/mergetopus/actions/workflows/build-windows.yml)\n\n![mergetopus logo](assets/mergetopus-logo.svg)\n\n`mergetopus` is a tool that helps teams follow a structured workflow for very large merges by splitting one risky merge into parallelizable tasks:\n\n- one integration branch for trivial/non-conflicting merge results\n- optional slice branches for selected conflicted files\n\nIt follows and extends the workflow in `ext/Invoke-TheMergetopus.ps1`.\n\nThe core idea is collaborative merge execution:\n\n- one person initializes the merge plan (`mergetopus`)\n- multiple developers resolve different slice branches in parallel (`mergetopus resolve`)\n- a coordinator monitors progress and next actions (`mergetopus status`)\n- once promoted, temporary branches are cleaned up (`mergetopus cleanup`)\n\n## What It Does\n\nWhen you run `mergetopus \u003csource\u003e`, it:\n\n1. Checks that you're in a Git repo with a clean working tree.\n2. Creates an integration branch (`_mmm/\u003ctarget\u003e/\u003csource\u003e/integration`).\n3. Runs `git merge --no-commit` against the source.\n4. Commits everything that merged cleanly into the integration branch.\n5. Resets conflicted files back to `ours` in that same commit — they'll be dealt with in slices.\n6. Lets you group conflicts into slices (via TUI or `--select-paths`). Any conflicts you don't explicitly group get their own one-file slice.\n7. Creates a branch per slice from the merge base, with the source-side version of each file and a commit message noting where it came from.\n\nFrom there, use `mergetopus resolve` to work through each slice with your merge tool (see [Resolving Conflicts](#resolving-conflicts)).\n\n## Collaborative Workflow (Large Merges)\n\nUse the commands together as a repeatable team process.\n\n1. Plan and split the merge (`mergetopus`).\n\n```bash\n# from your target branch (for example: main)\nmergetopus feature/very-large-change\n```\n\nWhat this does:\n\n- creates `_mmm/\u003ctarget\u003e/\u003csource\u003e/integration`\n- records non-conflicting merge results\n- creates per-conflict slice branches (`_mmm/\u003ctarget\u003e/\u003csource\u003e/sliceN`)\n\n2. Resolve slices in parallel (`mergetopus resolve`).\n\n```bash\n# each developer picks a slice and resolves it\nmergetopus resolve _mmm/main/feature_very-large-change/slice1\nmergetopus resolve --commit _mmm/main/feature_very-large-change/slice1\n```\n\nEach slice is merged into the integration branch with `--no-commit`, resolved with your merge tool, and optionally committed.\n\n3. Track progress and next actions (`mergetopus status`).\n\n```bash\nmergetopus status feature/very-large-change\n```\n\nStatus reports merged vs pending slices and suggests what to do next.\n\n4. Promote and clean up (`mergetopus cleanup`).\n\n- after all slices are merged, optionally create a [`kokomeco`](#why-kokomeco-exists) snapshot branch (a consolidated merge commit for promotion)\n- merge the chosen final branch into your target branch using normal Git policy\n- run cleanup to remove obsolete integration/slice branches\n\n```bash\nmergetopus cleanup\n```\n\n## Complex Merge Diagrams\n\n1. Hard merge without slicing (everything blocked in one place):\n\n```text\nmain:      A---B---C\n                 \\\nfeature:            D---E---F\n\nattempt:\nmain + feature  -\u003e conflicts in many files at once\n\nresult:\n- one large conflict-resolution task\n- hard to parallelize\n```\n\n2. mergetopus split strategy (parallel conflict handling):\n\n```text\nremembered HEAD: C\n\nmain:                 A---B---C\n                            \\\nsource feature:              D---E---F\n\nintegration branch:\n_mmm/main/feature/integration   C---M(partial: only non-conflicting files)\n                         |\n                         +-- conflicted files reset to ours in M\n\nslice branches from merge-base(C,F):\n_mmm/main/feature/slice1   B---S1 (explicit group: fileA,fileB)\n_mmm/main/feature/slice2   B---S2 (explicit group: fileC)\n_mmm/main/feature/slice3   B---S3 (auto singleton for unassigned fileD)\n_mmm/main/feature/slice4   B---S4 (auto singleton for unassigned fileE)\n```\n\n3. After resolution and optional consolidation:\n\n```text\nintegration after merging slices:\n_mmm/main/feature/integration   C---M---(merge S1)---(merge S2)---(merge S3)---(merge S4)\n\noptional non-destructive consolidation output:\n_mmm/main/feature/kokomeco\n                      \\---MC (single merge-commit snapshot branch)\n\nnotes:\n- integration history stays intact\n- consolidated branch is created for review/promotion\n```\n\n## Example: Large Team Merge across LTS Versions\n\n### Scenario\n\nFive developers maintain a project with multiple long-term stable (LTS) release branches:\n\n| Developer      | Role                 | Active branches          |\n| -------------- | -------------------- | ------------------------ |\n| Wendy Corduroy | Developer            | LTS_v17, LTS_v32         |\n| Gideon Gleeful | Developer            | LTS_v17, LTS_v32         |\n| Dipper Pines   | Developer            | LTS_v32, main            |\n| Mabel Pines    | Team lead (Gideon's) | LTS_v32, main            |\n| Stan Pines     | Senior integrator    | LTS_v42 (merges forward) |\n\nWendy and Gideon make **overlapping changes** to `config.toml` and `engine.rs`\nin LTS_v17. All four developers contribute to LTS_v32. Dipper and Mabel also\nwork on `main`. Stan regularly merges from older LTS versions into newer ones\nand eventually upstream to `main`.\n\n### Branch Topology\n\n```text\n                    Wendy: v17 pooling     Gideon: v17 hardening\n                    (config, engine,       (config line 2,\n                     api, utils)            engine line 2)\nLTS_v17:  M0 ──────── W1 ────────────────── G1\n            │\n            │          Wendy: v32   Gideon: v32   Dipper: v32     Mabel: v32\n            │          retry        caching       debug logging   auth + logging\nLTS_v32:  M0 ──────── W2 ──────── G2 ──────── D1 ──────────── MB1\n            │\n            │          Stan: v42\n            │          baseline\nLTS_v42:  M0 ──────── S1 ────── kokomeco₁ ────── kokomeco₂ ──── ···\n            │                       ↑                  ↑\n            │                 merge LTS_v17       merge LTS_v32\n            │\n            │          Dipper:      Mabel:\n            │          metrics      telemetry\nmain:     M0 ──────── D2 ──────── MB2 ─────────────── ··· ────── merge kokomeco₃\n```\n\n### Cascade Merge Steps\n\nStan merges LTS_v17 → LTS_v42, then LTS_v32 → LTS_v42, then LTS_v42 → main.\n\n#### Step 1: LTS_v17 → LTS_v42\n\n```bash\n# Stan initiates the merge from LTS_v42\nmergetopus LTS_v17 --select-paths config.toml,engine.rs\n```\n\n```text\nLTS_v42 HEAD (Stan)                             LTS_v17 (Wendy + Gideon)\n     │                                               │\n     └─── mergetopus LTS_v17 ───┐                    │\n                                │                    │\n   _mmm/LTS_v42/LTS_v17/        │                    │\n     integration ◄── partial merge (auto-merged files,\n         │               conflicts reset to ours)\n         │\n         ├── slice1: config.toml + engine.rs  ←  explicit group (--select-paths)\n         │     → Mabel resolves (contains Gideon's overlapping changes)\n         │\n         ├── slice2: api.rs\n         │     → Dipper resolves (Wendy's caching changes)\n         │\n         └── slice3: utils.rs\n               → Dipper resolves (Wendy's format changes)\n\n  After all slices resolved + consolidated:\n  _mmm/LTS_v42/LTS_v17/kokomeco\n      parent 1: original LTS_v42 HEAD (Stan's baseline)\n      parent 2: LTS_v17 tip (Wendy + Gideon)\n      tree:     final integration state\n```\n\n#### Step 2: LTS_v32 → LTS_v42\n\n```bash\n# After promoting kokomeco₁ into LTS_v42\ngit checkout LTS_v42 \u0026\u0026 git merge _mmm/LTS_v42/LTS_v17/kokomeco\nmergetopus LTS_v32 --select-paths engine.rs,utils.rs\n```\n\n```text\n  _mmm/LTS_v42/LTS_v32/\n     integration\n         │\n         ├── slice1: engine.rs + utils.rs  ←  Mabel resolves (Gideon/Mabel changes)\n         │\n         ├── slice2: api.rs                ←  Dipper resolves (Wendy's retry logic)\n         │\n         └── slice3: config.toml           ←  Dipper resolves (Wendy/Dipper's config)\n\n  After consolidation:\n  _mmm/LTS_v42/LTS_v32/kokomeco\n      parent 1: LTS_v42 (post kokomeco₁)\n      parent 2: LTS_v32 tip\n```\n\n#### Step 3: LTS_v42 → main\n\n```bash\n# After promoting kokomeco₂\ngit checkout main\nmergetopus LTS_v42\n```\n\nOnly `config.toml` and `engine.rs` conflict (main never changed `api.rs` or\n`utils.rs` from the initial commit, so those auto-merge).\n\n### Blame Verification on kokomeco\n\nAfter the full cascade, `git blame` on the final kokomeco correctly traces\nthrough the merge parents back to the original authors — no squash, no\nhistory rewrite:\n\n```text\ngit blame _mmm/LTS_v42/LTS_v17/kokomeco -- config.toml:\n  max_connections = 200   → Wendy Corduroy   (\"Wendy: v17 connection pooling and caching\")\n  timeout = 60            → Gideon Gleeful   (\"Gideon: v17 timeout hardening and error handling\")\n\ngit blame _mmm/LTS_v42/LTS_v17/kokomeco -- engine.rs:\n  fn init() { wendy_pool(); }       → Wendy Corduroy\n  fn process() { gideon_errors(); } → Gideon Gleeful\n\ngit blame _mmm/LTS_v42/LTS_v17/kokomeco -- api.rs:\n  fn handle() { wendy_caching(); }  → Wendy Corduroy\n\ngit blame _mmm/LTS_v42/LTS_v17/kokomeco -- utils.rs:\n  fn format() { wendy_format(); }   → Wendy Corduroy\n\ngit blame _mmm/main/LTS_v42/kokomeco -- engine.rs:\n  fn init() { mabel_auth(); }       → Mabel Pines     (from LTS_v32)\n  fn process() { gideon_cache(); }  → Gideon Gleeful   (from LTS_v32)\n\ngit blame _mmm/main/LTS_v42/kokomeco -- api.rs:\n  fn handle() { wendy_retry(); }    → Wendy Corduroy   (from LTS_v32, auto-merged)\n```\n\nThe kokomeco merge topology preserves correct line-blame because:\n\n- each kokomeco has the source branch as merge parent 2\n- unchanged lines from the source side trace through that parent to original commits\n- the cascade (kokomeco₁ → kokomeco₂ → kokomeco₃) maintains a clean ancestry chain\n- no squash or history rewrite occurs — only clean merge snapshots\n\n\u003e This scenario is exercised by the integration test\n\u003e `lts_cascade_merge_preserves_authorship_in_kokomeco` in `tests/test_suite_d.rs`.\n\n## Existing Topology Handling\n\nIf the integration branch already exists, `mergetopus`:\n\n1. discovers related slice branches (`_mmm/\u003csafe-current\u003e/\u003csafe-source\u003e/sliceN`)\n2. checks whether each slice is merged into the integration branch\n3. reports merged/pending status\n4. when all slices are merged, offers optional consolidation\n\nConsolidation is non-destructive: it creates a separate branch `_mmm/\u003csafe-current\u003e/\u003csafe-source\u003e/kokomeco` with a single merge commit snapshot.\n\n### Why \"kokomeco\" Exists\n\n`kokomeco` stands for **KOrrekt KOnsoliderter MErge COmmit** (German: \"correctly consolidated merge commit\").\n\nThe name is intentional: the consolidation step is not a squash and not a history rewrite of the integration branch. Instead, Mergetopus creates a separate merge-commit snapshot branch with merge parents derived from:\n\n- the remembered target-branch head (before the merge workflow started)\n- the original merge source commit\n\nand with the final resolved tree copied from the integration branch.\n\nWhy this matters for `git blame`:\n\n- A plain squash-style consolidation would collapse ownership and often attribute many lines to the integrator commit.\n- Kokomeco keeps a proper merge ancestry edge to the original source side, so line-blame can continue to follow where unchanged lines actually came from.\n- Temporary integration/slice execution history can be cleaned up later, while the promoted branch still shows where changes came from in the final merge history.\n\n## Installation\n\nDownload the `mergetopus` binary for your platform from the [GitHub Releases](https://github.com/mwallner/mergetopus/releases) page and place it in a directory on your system's `PATH`.\n\nOn **Windows** with [Chocolatey](https://chocolatey.org/):\n\n```bash\nchoco install mergetopus.portable\n```\n\n## Platform Support\n\n`mergetopus` works on **Windows**, **macOS**, and **Linux**.\n\nDuring `resolve`, Mergetopus sets the same environment variables (`LOCAL`, `BASE`, `REMOTE`, `MERGED`) across platforms so merge tool configuration stays portable.\n\nOn Windows, merge tools are invoked directly (without `cmd /c`) to avoid quoting/whitespace proxy issues.\nOn Unix-like systems (macOS, Linux), command execution uses `sh -c`.\n\nWhen running inside a Git worktree on Windows, mergetopus ensures `core.longpaths=true`\nfor the repository so deep path merges remain usable.\n\n## Worktree Behavior\n\nMergetopus adapts its worktree behavior based on your existing setup:\n\n- If your repository has no additional worktrees, Mergetopus keeps the existing default behavior (no automatic worktree creation).\n- If your repository already uses worktrees, Mergetopus prefers running branch operations in branch-specific worktree directories.\n- When Mergetopus needs to create a branch worktree and no suitable branch worktree exists yet, it infers a base directory from existing worktree paths.\n- If a common base cannot be inferred, Mergetopus falls back to the parent of the repository root.\n\nThis keeps non-worktree workflows unchanged while making branch checkouts easier in repositories that already use worktrees.\n\n## Branch Naming Conventions\n\n- **Integration branches** follow the pattern `_mmm/\u003csafe-original-branch\u003e/\u003csafe-source-branch\u003e/integration`.\n  These are temporary working branches that hold the merge result with auto-merged\n  files staged and conflicted files reset to \"ours\".\n  - Example: `_mmm/main/feature/integration`, `_mmm/develop/release_v1/integration`\n\n- **Slice branches** follow the pattern `_mmm/\u003csafe-original-branch\u003e/\u003csafe-source-branch\u003e/slice\u003cN\u003e` where `N` is a number (1, 2, 3, ...).\n  These are temporary per-conflict branches for resolving individual conflict groups.\n  - Example: `_mmm/main/feature/slice1`, `_mmm/main/feature/slice2`\n\n- **Kokomeco branches** follow the pattern `_mmm/\u003csafe-original-branch\u003e/\u003csafe-source-branch\u003e/kokomeco`.\n  These are optional output branches created after all slices are merged, containing\n  a single merge-commit snapshot.\n  - Example: `_mmm/main/feature/kokomeco`\n\nThe `safe-*` components use the same sanitization rules as before: characters outside `[0-9A-Za-z._-]` are replaced with `_`.\n\n### Branch Filtering\n\nWhen selecting a source branch for `mergetopus`:\n- **Slice branches** (`_mmm/.../slice\u003cN\u003e`) are automatically filtered out from the branch picker.\n  They should only be used with `mergetopus resolve`, never as a source for a new merge.\n- Only non-slice branches are available for selection, reducing accidental misuse.\n\n### Integration Branch Redirection\n\nIf you select an integration branch as the source, `mergetopus` detects this\nand asks what you want to do:\n\n- **Switch to this integration branch and view its status** — checks out the\n  integration branch and shows slice progress.\n- **Create a new merge targeting this integration branch** — checks out the\n  original target branch and merges the actual source, creating a fresh\n  integration branch.\n\nExample: if you select `_mmm/main/feature/integration`, mergetopus will\nrecognize that the target was `main` and the source was `feature`, then let\nyou pick between viewing existing status or starting a new merge of `feature`\ninto `main`.\n\n## Usage\n\nInteractive source selection (branch picker overlay shown):\n\n```bash\nmergetopus\n```\n\nProvide source branch explicitly:\n\n```bash\nmergetopus feature/refactor-auth\n```\n\nExplicit conflict grouping by path list:\n\n```bash\n# Put explicit paths into one grouped slice; all remaining conflicts become one-file slices\nmergetopus feature/refactor-auth --select-paths src/a.rs,src/b.rs\n```\n\nInteractive conflict grouping (with `F3` opening your configured `diff.tool`, or the inline 3-way view when no `diff.tool` is set) when `--select-paths` is not provided:\n\n```bash\nmergetopus feature/refactor-auth\n```\n\nAuto-confirm consolidation prompt:\n\n```bash\nmergetopus feature/refactor-auth --yes\n```\n\nNon-interactive CI/CD mode (no TUI):\n\n```bash\n# SOURCE is required in quiet mode\nmergetopus feature/refactor-auth --quiet\n\n# Quiet mode + explicit conflict grouping\nmergetopus feature/refactor-auth --quiet --select-paths src/a.rs,src/b.rs\n\n# Quiet mode + auto-consolidate when eligible\nmergetopus feature/refactor-auth --quiet --yes\n\n# Show slice/integration progress status\nmergetopus status feature/refactor-auth\n\n# Cleanup temporary integration/slice branches (interactive confirmation)\nmergetopus cleanup\n\n# Take over an already in-progress manual merge\nmergetopus HERE\n```\n\nTakeover mode for an in-progress merge:\n\n```bash\n# Optional: non-interactive explicit grouping for remaining conflicts\nmergetopus --quiet --select-paths src/big/file1.cs,src/big/file2.cs HERE\n```\n\n## Status Reporting\n\nUse `mergetopus status` to inspect an integration branch and its slice progress.\n\n```bash\n# Status by source ref\nmergetopus status feature/refactor-auth\n\n# Status by integration branch name\nmergetopus status _mmm/main/feature_refactor-auth/integration\n```\n\nThe status output includes:\n\n- integration branch\n- source ref and source SHA (when derivable from integration history)\n- merged/pending slice counts\n- pending slice details with detected affected paths (when available)\n- suggested next commands\n\n## Resolving Conflicts\n\nAfter mergetopus has created slice branches, use `resolve` to merge a selected\nslice into its corresponding integration branch with `--no-commit`, then open\neach conflicted file in your configured merge tool one-by-one:\n\n```bash\n# Interactive slice branch picker (TUI)\nmergetopus resolve\n\n# Resolve a specific slice branch directly\nmergetopus resolve _mmm/main/feature/slice1\n\n# Non-interactive (--quiet requires an explicit branch)\nmergetopus resolve --quiet _mmm/main/feature/slice1\n\n# Create a commit automatically after staging\nmergetopus resolve --commit _mmm/main/feature/slice1\n```\n\n### What resolve does\n\n1. Derives the corresponding integration branch from the slice branch name.\n2. Checks out the integration branch and starts `git merge --no-commit \u003cslice\u003e`.\n3. For each currently conflicted file, derives from the Git graph:\n  - `LOCAL` as the integration branch `HEAD` before the merge\n  - `REMOTE` as the slice branch tip\n  - `BASE` as `merge-base(LOCAL, REMOTE)`\n4. Writes three temporary files per conflicted path:\n  - `LOCAL`  — the file at the integration branch side\n  - `BASE`   — the file at the common ancestor (merge-base)\n  - `REMOTE` — the file at the slice branch side\n5. Executes the configured merge tool with `LOCAL`, `BASE`, `REMOTE`, and `MERGED`\n   set as environment variables (same convention as `git mergetool`). The command\n   is executed via the appropriate shell:\n  - **Windows**: invoked directly without `cmd /c`\n   - **Unix-like systems** (macOS, Linux): `sh -c \u003ccmd\u003e`\n   \n  `MERGED` points to the conflicted working-tree file on the integration branch,\n  so the tool writes the resolution directly into the repository.\n6. Stages each resolved file.\n7. Optional: if `--commit` is passed, creates the merge commit on the integration branch.\n\n## Take Over In-Progress Merge (`HERE`)\n\nUse `mergetopus HERE` when you already started a regular `git merge` manually,\nresolved some conflicts, and want Mergetopus to take over only the remaining\nunresolved conflicts.\n\nTypical scenario:\n\n1. You run `git merge \u003csource\u003e` on your target branch.\n2. Git stops with conflicts.\n3. You manually resolve some files.\n4. You run `mergetopus HERE` to continue using slice workflow for what remains.\n\nBehavior of `HERE`:\n\n- requires an active merge (`MERGE_HEAD` must exist)\n- preserves already-resolved file content from your working tree/index\n- aborts the manual merge and rebuilds canonical Mergetopus integration state\n- creates slices only for still-unresolved conflict paths\n- opens normal conflict grouping flow (or uses `--select-paths` in quiet mode)\n\nCommand examples:\n\n```bash\n# Interactive takeover\nmergetopus HERE\n\n# Quiet takeover with explicit grouping for remaining conflicts\nmergetopus --quiet --select-paths src/module/a.rs,src/module/b.rs HERE\n```\n\n### Configuring the merge tool\n\n`mergetopus resolve` reads the merge tool from Git config.  Set it once in\nyour global or repository config:\n\n```bash\n# Choose a tool name\ngit config merge.tool vimdiff\n\n# Provide the shell command template.\n# $LOCAL, $BASE, $REMOTE, $MERGED are expanded at runtime.\ngit config mergetool.vimdiff.cmd 'vimdiff \"$LOCAL\" \"$BASE\" \"$REMOTE\" -c \"wincmd J\" \"$MERGED\"'\n```\n\nSome common examples:\n\n| Tool           | Example `mergetool.\u003cname\u003e.cmd`                               |\n| -------------- | ------------------------------------------------------------ |\n| vimdiff        | `vimdiff \"$LOCAL\" \"$BASE\" \"$REMOTE\" -c \"wincmd J\" \"$MERGED\"` |\n| nvim           | `nvim -d \"$LOCAL\" \"$REMOTE\" \"$MERGED\"`                       |\n| code (VS Code) | `code --wait --merge \"$LOCAL\" \"$REMOTE\" \"$BASE\" \"$MERGED\"`   |\n| meld           | `meld \"$LOCAL\" \"$BASE\" \"$REMOTE\" --output \"$MERGED\"`         |\n| kdiff3         | `kdiff3 \"$BASE\" \"$LOCAL\" \"$REMOTE\" -o \"$MERGED\"`             |\n\nAny tool that reads `$LOCAL`, `$BASE`, `$REMOTE` and writes its result to\n`$MERGED` will work.\n\n### Configuring optional F3 diff tool\n\nIn the conflict selector, `F3` behaves as follows:\n\n- if `git config diff.tool` is set, `F3` launches that difftool for the selected conflicted file\n- if `diff.tool` is not set, `F3` opens the built-in inline 3-way diff overlay\n\nExample:\n\n```bash\ngit config diff.tool vscode\ngit config difftool.vscode.cmd 'code --wait --diff \"$LOCAL\" \"$REMOTE\"'\n```\n\n## TUI Keybindings\n\nWhen `--quiet` is not set, TUI is used for source branch picking (if `SOURCE`\nis omitted), conflict selection (if `--select-paths` is omitted), and slice\nbranch selection for `resolve` (if `BRANCH` is omitted).\n\nConflict selector:\n\n- `Arrow Up/Down`: move cursor\n- `Tab`: switch pane\n- `n`: create new explicit slice\n- `Space`: assign/move highlighted conflict into currently selected slice\n- `u`: unassign highlighted conflict (it will become default one-file slice)\n- `d`: delete selected explicit slice (its files become unassigned)\n- `F3`: open configured difftool for selected file (or inline 3-way diff if `diff.tool` is not set)\n- `Enter`: apply selection\n- `Esc`: close overlay or cancel selector\n- `q`: cancel selector\n\nSource branch picker / Slice branch picker:\n\n- Type text to filter branch list\n- `Arrow Up/Down`: move\n- `Enter`: select\n- `Esc` or `q`: cancel\n\n3-way diff overlay:\n\n- `Up/Down`: scroll\n- `PageUp/PageDown`: fast scroll\n- `Home/End`: jump to top/bottom\n- `Esc`: close overlay\n\n## Commit Metadata\n\nSlice commits include informational trailers that document where each file came from:\n\n- `Source-Ref`\n- `Source-Commit`\n- `Source-Path`\n- `Source-Path-Commit`\n- `Co-authored-by` (when source-side author info is available)\n\nThese trailers are purely metadata for humans and tools like `mergetopus status`.\nKokomeco creation does not depend on them — it works entirely from git history\nand the integration branch tree.\n\n## Authorship Clarification\n\nA squash or consolidation commit does not preserve per-commit author lineage by itself.\n`mergetopus` keeps attribution info using co-author trailers on slice commits\nand preserves original integration/slice history by writing consolidated output\nto a separate branch. The kokomeco branch itself gets correct `git blame`\nthrough its merge parents, not through trailers.\n\n## Safety Notes\n\n- No destructive reset/rewrite is performed automatically.\n- Consolidation requires explicit confirmation (unless `--yes` is used).\n- `--quiet` disables TUI interactions; provide `SOURCE` explicitly for CI/CD runs.\n- Integration branch is not rewritten by default.\n\n## License\n\nMIT. See `LICENSE`.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmwallner%2Fmergetopus","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmwallner%2Fmergetopus","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmwallner%2Fmergetopus/lists"}