Merging branches
Method and tools for systematic work with an AI development assistant — curated skills, subagents, CLI, and a working methodology, plus a VS Code setup for macOS.
npx -y skills add KirKruglov/OFFICINA --skill merging-branchesAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
One thing to look at
- 1 stars1 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
What its author says it does
Copied from the file, not written here
Use BEFORE any git merge, rebase, or branch integration. Reads the project conventions file (CLAUDE.md or AGENTS.md) to determine merge strategy, runs pre-merge safety checks (diff name-status both sides, clean working tree, up-to-date with remote, conflict scan), requires explicit user confirmation for merge to main/master/release branches. Trigger phrases — "merge X into Y", "rebase onto", or any request implying branch integration.
SKILL.md
8.6 KB, as published. Nobody here has run it
Merging Branches
When invoked, follow this procedure step by step. Create a TodoWrite task per step.
Rule Hierarchy
- Explicit user instruction in the current message — wins.
- Project conventions file —
CLAUDE.mdorAGENTS.md— sections## Git workflow,## Branching,## Release process. - Global conventions —
~/.claude/CLAUDE.md(or your harness's global agents file, e.g.~/.codex/AGENTS.md). - This SKILL.md.
Step 1: Read conventions and determine strategy
- Read the project conventions file —
CLAUDE.mdorAGENTS.md. Look for sections:## Git workflow,## Branching,## Release process. - Read the global conventions file —
~/.claude/CLAUDE.md(or the equivalent for your harness) — as fallback. - If you find merge-strategy guidance, surface the relevant quote to the user and ask to confirm interpretation:
From project conventions file:
> On release push — squash-merge the branch's commits.
Interpreted strategy: squash. Confirm? (y/n/other)
If strategy is NOT described in any conventions file — ask user directly: squash / merge commit / rebase / ff-only.
Step 2: Identify source and target
- Both must come from user request. If either is ambiguous — ask. Do NOT guess based on current branch.
Step 3: Classify target
Protected branches (require extra confirmation):
main,masterrelease/*production,prod,staging
For protected target, add an explicit confirmation gate:
⚠ Target = main (protected branch).
This will change commit history on `main` permanently. Confirm explicitly by typing the exact phrase: "yes merge to main"
Only proceed if user types the exact confirmation phrase.
Note: the phrase must include the full branch name including any / characters. For release/0.1.0 the confirmation is "yes merge to release/0.1.0".
Step 4: Pre-merge safety checks
Run all four in order. Any failure → STOP and report.
4a. Clean working tree
git status --porcelain
If non-empty → STOP. List dirty files. Ask user: stash / commit (invoke committing-changes) / cancel.
After committing-changes completes and reports success, resume this skill from Step 4b. The merge has NOT been performed yet — only the working tree was cleaned.
4b. Up-to-date with remote
Detect target's configured upstream (avoid hardcoding origin):
git rev-parse --abbrev-ref <target>@{upstream}
If this fails (no upstream configured) → skip the rest of 4b with a note in the plan: "step 4b skipped — no upstream for <target>".
Otherwise:
git fetch
git rev-list --count <target>..<target>@{upstream}
If count > 0 (local target is behind upstream) → STOP. Offer git pull --ff-only on target before proceeding.
Also check source the same way:
git rev-parse --abbrev-ref <source>@{upstream} 2>/dev/null && \
git rev-list --count <source>..<source>@{upstream}
If source is behind its upstream — warn user but allow continuing.
4c. Diff name-status both sides
git diff --name-status <target>...<source>
git diff --name-status <source>...<target>
Show both lists. Highlight files that appear in BOTH (potential conflicts).
4d. Pre-conflict scan (cascading fallback)
Phase 1: detect Git version
git --version
Phase 2: pick strategy by version
-
Git ≥ 2.38 — modern
merge-tree:git merge-tree --write-tree <target> <source>Parse output for conflict markers (
<<<<<<<,=======,>>>>>>>). Git auto-computes the merge base. -
Git ≥ 2.0, < 2.38 — old
merge-tree:base=$(git merge-base <target> <source>) git merge-tree "$base" <target> <source>Old format: blocks "changed in both" + conflict markers.
-
Any version — fallback via temp worktree (if
merge-treefailed or gave unreadable output):WT=/tmp/claude-conflict-check-$$ git worktree add --detach "$WT" <target> git -C "$WT" merge --no-commit --no-ff <source> || true git -C "$WT" diff --name-only --diff-filter=U git -C "$WT" merge --abort 2>/dev/null || true git worktree remove --force "$WT"Uses
git -C <path>to avoidcd(each Bash call resets working directory in Claude's model).|| trueensures cleanup runs even if merge fails.
Results:
- No conflicts → note "predicted conflicts: none", continue.
- Conflicts → show file list (+ blocks if available), ask user: proceed and resolve manually / cancel.
- Scan failed (worktree fallback also failed, e.g., shallow clone) → say "pre-conflict scan not performed", ask user to OK skipping.
Edge case: Git < 2.0 → say "Git version too old for safe pre-merge scan", ask user to confirm skipping the step.
Step 5: Present consolidated plan
Merge plan:
source: <branch> (<N commits>)
target: <branch> (protected: true/false)
strategy: <squash|merge|rebase|ff-only> (source: conventions | user)
Files changed: <N>
Overlaps with target: <N>
Predicted conflicts: none | <list>
Commands:
git checkout <target>
git merge ... <source>
Confirm? (y/n)
Without y, do NOT execute.
Step 6: Execute merge
| Strategy | Commands |
|---|---|
| squash | git checkout <target> && git merge --squash <source> then invoke committing-changes with context: "this is a squash merge — skip atomic-split check (Step 4), produce a single commit". |
| merge commit | git checkout <target> && git merge --no-ff <source> -m "merge: <source> into <target>" |
| rebase | git checkout <source> && git rebase <target> && git checkout <target> && git merge --ff-only <source> |
| ff-only | git checkout <target> && git merge --ff-only <source> (fails if not fast-forward — feature, not bug) |
Step 7: Conflict during actual merge
- STOP. Do NOT run
git merge --abortwithout confirmation. - Show conflicts:
git diff --name-only --diff-filter=U. - Ask user: resolve manually / abort.
- Do NOT auto-edit conflict files.
Step 8: Final report
- SHA of merge commit (or new HEAD for ff/rebase).
- Run
git statusand confirm clean. - Brief: "Merged N commits into <target>".
- Do NOT push. Push is always separate, explicit.
- Do NOT delete source branch without explicit user command.
Step 9: Forbidden without explicit user command
These require a separate, explicit user instruction:
git push(any form)--force/--force-with-leasegit branch -D <source>git push origin --delete <source>git reset --hard
If Claude is tempted to use any of these — STOP, report to user, wait for explicit go-ahead.
Override phrases
| Phrase | Effect |
|---|---|
| "force squash/merge/rebase" | Set strategy manually, skip conventions read |
| "skip checks" | Skip 4b (remote sync) and 4d (conflict pre-scan) only. 4a (clean working tree) and 4c (diff display) always run. |
| "force" | Does NOT enable --force push. Force-push still requires "yes force push to <branch>" |
Absolute prohibitions
- Any
git configmodifications. git push --forceto protected branch without typed phrase "yes force push to <branch>".git reset --hardif untracked files exist — first offer stash, then separate confirmation.
Edge cases (handle and report)
- Not a git repository: report and stop. Never run
git init. - Detached HEAD on target: report and stop — cannot meaningfully merge into detached HEAD without explicit user intent.
- No
originremote: skip step 4b (up-to-date check) with a note in the plan. Local-only merge still proceeds. - Shallow clone (
.git/shallowexists): pre-conflict scan may be inaccurate — warn user before step 4d. - Submodules in either branch: warn separately — submodule pointer changes can surprise users.
- Existing
.git/MERGE_HEAD: STOP. A previous merge is unfinished. Ask user to resolve or abort it first. - Existing
.git/rebase-merge/or.git/rebase-apply/: STOP. A previous rebase is unfinished. Ask user to resolve (git rebase --continue) or abort (git rebase --abort) first. - Pre-conflict scan fails entirely (worktree fallback also fails): say "pre-merge conflict prediction unavailable", require explicit user OK to proceed without it.