Skip to content
Agentmart
Submit a tool

merge-worktree

Land a Meldom worktree end to end — commit through the ship card, push, merge with a merge commit, pull the main checkout, remove the worktree through…

Skill by meldomapp

IndexedMIT
Write a review

Install

Works with Claude Code, Claude apps, Codex, Cursor, Gemini CLI, GitHub Copilot, VS Code, OpenCode, Goose, Windsurf. Read the repository before you give any tool access to your data.

npx agentmarket install skill/meldomapp-merge-worktree

Asks which of your tools to add it to (Claude Code, Codex, Cursor, VS Code, Windsurf, Gemini CLI, Claude Desktop) and shows the change first. See https://agentmart.dev/cli.

Get the weekly diff

The weekly diff: one email a week with new agent tools, notable updates and grade changes, plus security alerts for tools you follow. Double opt-in, one-click unsubscribe.

We use your email only for this newsletter. Privacy

About

Land a Meldom worktree end to end — commit through the ship card, push, merge with a merge commit, pull the main checkout, remove the worktree through `worktree_remove`, delete the remote branch, confirm. Use when the user presses "Ship it", says "merge worktree", "land this worktree", "finish the worktree", "land my branch", or wants a worktree's work carried all the way back into the main checkout.

No reviews yet. Installed it? Reviews come from verified installers only. How reviews work

Permissions

What this skill can do and what it asks for, from its SKILL.md. Checked Oct 25, 2026.

Tools
No tools found
Secrets
None asked for
Install scripts
None found

Network hosts it talks to 1

  • codeload.github.com · found in install command

Files it touches

  • ~/.claude/skills/merge-worktree

What's inside

Skill name
merge-worktree
Description
Land a Meldom worktree end to end — commit through the ship card, push, merge with a merge commit, pull the main checkout, remove the worktree through `worktree_remove`, delete the remote branch, confirm. Use when the user presses "Ship it", says "merge worktree", "land this worktree", "finish the worktree", "land my branch", or wants a worktree's work carried all the way back into the main checkout.
License
MIT
Instructions
247 lines in SKILL.md · view on GitHub

Files (2)

  • SKILL.md
  • openai.yaml · agents/

SKILL.md (first lines)

# Meldom Merge Worktree

Land: commit → push → merge → pull main → remove the worktree → delete the remote branch → confirm. Run it FROM INSIDE the worktree being landed.

## Finish, don't stop

A landing runs to the end. A conflict, a dirty main checkout, a PR GitHub calls not mergeable, a peer landing already in flight — each is a pause you handle, then you carry on from the same phase.

**Exactly two things end a landing early:**

1. `worktree_remove` reports `git-failed` with `proof: 'local-only'` — commits exist on no ref that survives the removal, so removing would destroy the only copy. Report it verbatim and stop.
2. The user cancels a ship card.

Nothing else qualifies. Do not widen this list.

**Any conflict** — a merge, a rebase, a not-mergeable PR, a `git stash pop` — is resolved deliberately: read what each side intended, resolve every hunk, run the checks, commit, then carry on from the same phase. Never `git merge --abort`, never a forced push.

**A gitlink conflict** (a `UU` on a submodule pointer) is settled by the ancestor test, never by "the newest":

```bash
git -C <submodule-path> fetch origin                               # the other side may be a commit you have never seen
git -C <submodule-path> merge-base --is-ancestor <ours> <theirs>   # theirs contains ours -> take theirs
git -C <submodule-path> merge-base --is-ancestor <theirs> <ours>   # ours contains theirs -> take ours
```

Neither contains the other → a real divergence: resolve it with your own reading of both sides.

**A peer landing** — a merge in progress or `UU` entries in the main checkout or one of its submodules, that you did not create — is another agent's landing, never "unrelated changes". Wait for it in ONE shell command that re-checks every 30 seconds for up to 30 minutes, and touch nothing of theirs. There is no lock: this rule is the only thing keeping two landings out of each other's way.

```bash
M=<main-checkout>
busy() { test -e "$(git -C "$M" rev-parse --path-format=absolute --git-path MERGE_HEAD)" || git -C "$M" status --porcelain | grep -q '^UU' \
  || git -C "$M" submodule foreach --quiet --recursive 'test -e "$(git rev-parse --path-format=absolute --git-path MERGE_HEAD)" && echo busy; true' | grep -q busy; }
for i in $(seq 60); do busy || break; sleep 30; done; busy && echo STILL-BUSY
git -C "$M" submodule foreach --quiet --recursive 'git symbolic-ref -q HEAD >/dev/null || echo "DETACHED: $displaypath"'
```

`STILL-BUSY` → tell the user which merge is still open and carry on when they answer. A `DETACHED` submodule with no merge in progress is no landing: report it, and Phase 4 puts it back on its branch.

## Phase 1 — Preflight

ONE chained Bash call from the worktree root:

```bash
git rev-parse --show-toplevel && git rev-parse --git-common-dir --git-dir && git branch --show-current && git remote get-url origin 2>/dev/null; test -f .gitmodules && echo HAS_SUBMODULES
```

- **Confirm this IS a worktree**: `--git-common-dir` differs from `--git-dir`. If they match, this is the main checkout — stop and say so.
- **Superrepo**: `.gitmodules` present at toplevel. If so, list every submodule whose checked-out commit differs from the recorded pointer: `git submodule status --recursive | awk '$1 ~ /^[+-]/ {print $2}'`.
- **Remote per repo**: `git remote get-url origin`. A `github.com` URL with `gh auth status` succeeding → the **remote path** (Phase 3). A **local filesystem path** → the [local-origin path](#local-origin-submodules). Nothing at all → the [no-remote path](#no-remote-path).
- **Original branch** (what this lands into): `git symbolic-ref refs/remotes/origin/HEAD`, falling back to `main` → `master` → `develop`.

## Phase 2 — Commit and push

One repo at a time, **every changed submodule before the superrepo** — a pointer-bump commit can only name a submodule commit that already exists on that submodule's remote.

1. **Commit** — invoke the `meldom:ship` skill. That is the ship card, and it is the only way your work commits here. Nothing to commit in this repo → move to the next.
2. **Push** — `git push -u origin <branch>`. The first push has no upstream yet, so set one. Never force.

## Phase 3 — Merge

Remote path, per repo:

```bash
gh pr create --base <original-branch> --head <branch>    # or reuse the open one
gh pr merge <number> --merge
gh pr view <number> --json state,mergeStateStatus        # state must read MERGED
```

- **A merge commit, always.** Never `--squash` and never `--rebase`: a squash mints a new commit the worktree's own checkout does not have, which is what makes a superrepo pointer stale and a worktree branch look unmerged.
- **Never delete the branch as part of the merge.** The remote branch goes in Phase 6, after removal has confirmed the work is durable.
- **Not mergeable** → repair it INSIDE the worktree, not on the remote: `git fetch origin <base>`, `git merge origin/<base>`, resolve, push, then merge the PR.
- **Blocked by required checks** → `gh pr merge <number> --merge --auto`, then wait in one blocking call: `gh pr checks <number> --watch --fail-fast --required`. It returns when every required check has passed or the first one fails; a failure is fixed inside the worktree and pushed. If it reports no checks right after a push, wait 30 seconds and run it again. After a clean exit the queued merge is landing; re-check it every 30 seconds for up to 20 minutes in one call:

  ```bash
  for i in $(seq 40); do
    s=$(gh pr view <number> --json state,autoMergeRequest -q '"\(.state) \(.autoMergeRequest != null)"')
    [ "$s" = "OPEN true" ] || break; sleep 30
  done; echo "$s"
  ```

  A state of `MERGED` (either flag) → carry on. Anything else — `CLOSED`, `OPEN false` (auto-merge cancelled), or `OPEN true` after the ceiling — tell the user what it reads and carry on when they answer. These waits, like the peer-landing loop, can outlast a default command timeout: run them with a long timeout or in the background. Waiting is a pause, not an end.
- Confirm `state: MERGED` before moving on.

**Superrepo, right after a submodule merges**: move the worktree's own submodule checkout to the merged remote head before staging the pointer, so the pointer names a commit that is actually on the submodule's remote.

```bash
git -C <worktree>/<submodule-path> fetch origin
git -C <worktree>/<submodule-path> checkout <submodule-branch>
git -C <worktree>/<submodule-path> merge --ff-only origin/<submodule-branch>
git -C <worktree> add <submodule-path>      # then commit the pointer bump and land the superrepo
```

The pointer bump is your own commit, so it goes through `meldom:ship` like any other.

## Phase 4 — Pull the main checkout

**Record first, stash if dirty, pop afterwards. The user's files are never moved, deleted or excluded.**

```bash
# from the main checkout
# The record Phase 7 compares against. Name it after THIS worktree's slug: a peer landing on the same machine
# writes its own, and a shared filename would leave both confirming against the wrong baseline.
git status --porcelain > "/tmp/meldom-landing-<slug>.txt"
# anything listed? stash it, untracked included:
git stash push -u -m "meldom-auto: landing <slug>"

git pull --ff-only                                        # on its own branch, never detached
# per initialized submodule:
git -C <submodule-path> checkout <its branch> && git -C <submodule-path> pull --ff-only

git stash pop                                             # conflict -> resolve it, then carry on
```

**Never let git re-checkout the submodules from the superrepo's recorded pointer (`git submodule update`, `--init --recursive`) in the shared main checkout.** It leaves every submodule DETACHED at that pointer, and a peer landing then merges onto no branch — the merge is reachable from no ref and the next checkout orphans it. Check out each submodule's branch and pull it instead, as above. A submodule already left detached with no merge in progress goes back on its branch before anything merges into it.

The stash is the user's own work. Pop it before the landing ends, whatever else happened, and never `git stash drop` it.

## Phase 5 — Remove the worktree

From meldomapp/skills, MIT.

More from meldomapp/skills

Signals

Stars
0
Forks
0
Open issues
0
Last commit (this folder)
Oct 6, 2026 (23 days ago)
Last release
Oct 15, 2026 (14 days ago)

From GitHub (fetched Oct 24, 2026).

Details

License
MIT
First seen
Oct 24, 2026
Last checked
Oct 24, 2026

More from meldomapp

Cite this page

merge-worktree skill. Agent Mart. https://agentmart.dev/skills/meldomapp-merge-worktree (last updated 2026-10-24)