Volume XXII, number 279Tuesday, October 6, 2026Latest message 23 minutes ago

The Git List

News and archive of git@vger.kernel.org, since April 2005

[ANNOUNCE] git-carrier 0.1.0: park a stopped merge, land it later as a real merge

1 messages between Oct 3, 2026 and Oct 3, 2026, from Oscar Mira.

Plain Markdown or JSON for tools and agents.

Oscar MiraOct 3, 2026, 01:37 UTC on lore
Hello,

I've just published a set of git extensions that park a merge that stopped at conflicts as an ordinary commit, and land it later as a real merge.

An idea like this has been proposed on this list several times, as a solution to the problem of working with large merges. I believe ours is the first tool to implement it in plain git.

I'm one of the maintainers of Molly, a Signal client fork of Signal for Android. Upstream updates arrive in our tree as large merges that generate many conflicts. I wrote this tool because we need to distribute the resolution work across the team, so the conflict state has to travel across clones.

git-carrier is one bash script that implements three git commands, with no dependencies beyond git and standard Unix utilities:

  git park --branch carrier/v1.2.3
      Moves the stopped merge onto a carrier branch, without
      recreating the merge, and stores the conflicted paths under
      a .hangar directory in ordinary commits.
  git unpark -- <path>
      Takes a parked path back out of the hangar. If the file is
      unchanged, it reopens as the conflict git left, so
      `git mergetool` works as usual. If you changed or deleted it,
      the working file is the resolution.
  git land <dst>
      Stages the finished work onto the destination without the
      .hangar directory, and writes MERGE_HEAD. Then it stops, and
      you run `git commit` to finish the two-parent merge.

Everything in between is ordinary git. The carrier branch is pushed, reviewed and cloned like any branch. The work left is the .hangar/stages/<path>/ directories at HEAD, and a path is released by deleting its directory, which shows in any diff. No new ref namespaces, no server-side changes.

The tool was designed to meet our needs. We read the list's discussions of the same problem only afterward, and it was a happy convergence. In June 2020 this list discussed how to pass a partially resolved merge on to the next person [1]. Junio's answer was that the important and useful part is the data format used for that hand-off [2]. Chris Torek sketched what the format holds [3]; his sketch reads like a description of the hangar:

    resolved entries          the carrier's own commits
    stages 1, 2, 3            .hangar/stages/<path>/{1,2,3}
    the working file          .hangar/stages/<path>/w
    the merge's own context   .hangar/manifest and .hangar/message

And the 2025 contributor summit expected external tooling to cover this until first-class conflicts exist [6].

I want to share the design, because the format is the useful part for this list. The spec is on its own page, CC0, and git-carrier is just one possible implementation. That said, the spec was written after the first implementation and can have gaps; the script does more than it explains.

Notes on the decisions, since the list has positions on them:
  * Out of tree. The thread's advice was to implement it outside
    git [4], and to help distros bundle good tools rather than
    integrate them [5]. We are not proposing contrib/ or core
    inclusion. But we would love to list the tool on the git wiki's
    tools page.
  * If everyone in the loop runs jj, it is a good alternative: jj
    makes conflicts first-class committable state. This tool is for
    loops where some resolvers, CI, or agents are plain git.
  * The carrier branch carries conflict markers by design. It is a
    handoff, never merged directly, and the landed tree is the
    carrier's tree minus .hangar.
  * Merge conflicts only, for now: no rebase, cherry-pick, or revert
    parking, one merge source, no octopus, no submodule gitlinks.

A note on confidence: the tool is brand new. The bash code was mostly authored through several LLM iterations, and the commits carry "Assisted-by: LLM" trailers for that reason. We reviewed and tested it extensively, but it could still be wrong somewhere. The bash file grew bigger than expected, and I know we pay for that in maintenance.

I built it with care, and I hope it is useful.
  Repo:  https://github.com/git-carrier/git-carrier
  Spec:  docs/hangar-format.txt in the repository, CC0.
  Tool:  one bash file, MIT, with a bats test suite. It needs bash
         3.2 or newer and git 2.34 or newer.

Thanks for reading. Comments welcome, especially on the format. Bug reports even more.

Oscar Mira

[1] https://lore.kernel.org/git/BY5PR19MB3400EB9AD87DFE612AFD5CC390810@BY5PR19MB3400.namprd19.prod.outlook.com/ [2] https://lore.kernel.org/git/xmqq1rmgxo67.fsf@gitster.c.googlers.com/ [3] https://lore.kernel.org/git/CAPx1GvdT6sZRtu8q1R9=fA-mE9pi1Ag-gKEzQfwbGap+KqSoSg@mail.gmail.com/ [4] https://lore.kernel.org/git/874kr92xyz.fsf@osv.gnss.ru/ [5] https://lore.kernel.org/git/xmqqa716zs7w.fsf@gitster.c.googlers.com/ [6] https://lore.kernel.org/git/aOQV%2Fja9Ltw%2FbTP3@nand.local/

Back to recent threads