---
name: merge
description: Merge a branch into another following this repo's git conventions — all merges to main are squash merges, with a clean review-and-confirm flow. Use when the user says "merge X into Y", "squash merge to main", "merge dev to main", "land this branch", or similar.
argument-hint: "[source branch] into [target branch] — e.g. 'dev into main'. Omit to merge current branch into main."
---

# Merge a branch (repo git conventions)

Merge `$ARGUMENTS` following this repo's conventions. If no arguments given, default to merging the **current branch into `main`**.

## Repo conventions (non-negotiable)

- **All merges to `main` MUST be squash merges** — one commit per feature/refactor keeps `main` history clean.
- **Force push to `main` is acceptable after squash merges** (only when required to replace history) — and only after the squash merge is committed locally and confirmed.
- Default working branch is `dev`; default integration branch is `main`. Remote is `origin` (https://github.com/rightbrain/appza_woo.git).

## Step 0 — Parse intent

From `$ARGUMENTS` determine SOURCE and TARGET:
- `"dev into main"` → SOURCE=dev, TARGET=main
- `"main into dev"` → SOURCE=main, TARGET=dev
- empty → SOURCE=current branch, TARGET=main

If the target is `main`, this is a **squash merge** (see Step 3a). Any other target is a **regular merge** (Step 3b) unless the user explicitly asks for a squash.

## Step 1 — Pre-flight checks (always)

Run and show the user the results before doing anything destructive:

```bash
git status              # working tree must be clean — stop if dirty, ask user
git fetch origin
git log --oneline origin/<TARGET>..<SOURCE>   # commits that will land
git log --oneline <SOURCE>..origin/<TARGET>   # commits on target not in source (divergence)
```

- **Dirty working tree** → stop. Show `git status` and ask the user to commit/stash first. Never merge over uncommitted work.
- **Nothing to merge** (`origin/<TARGET>..<SOURCE>` empty) → tell the user, stop.
- Summarize the commit list so the user sees exactly what's landing.
- **Note on squash workflows:** once `main` has had its first squash merge, `main` and `dev` no longer share commit SHAs, so `origin/main..dev` will list *all* of dev's commits even though their content is already on `main`. The genuinely new work is only the commits since the last squash. Surface this so the list doesn't alarm.

## Step 2 — Sync both branches

```bash
git checkout <TARGET>
git pull origin <TARGET>
git checkout <SOURCE>
git pull origin <SOURCE>
```

## Step 3a — Squash merge (TARGET = main)

```bash
git checkout main
git merge --squash <SOURCE>
```

Then **stop and craft a single commit message** summarizing the whole batch (one feature/refactor per line if multiple). Show the user the proposed message and the staged diff stat (`git diff --cached --stat`) and **wait for confirmation** before committing.

After approval:

```bash
git commit -m "<approved message>"
```

End commit messages with the Co-Authored-By trailer (see Step 5).

### Conflicts during squash
Squash workflows merge against an old base, so conflicts can appear even when the net change is small. If `git merge --squash` reports conflicts: list the conflicted files, resolve them (or ask the user if the resolution is non-obvious), `git add` them, verify no markers remain (`grep -rn -E '^(<<<<<<<|=======|>>>>>>>)' <file>`), then continue from the commit step. Never auto-resolve a conflict whose intent is ambiguous — ask.

## Step 3b — Regular merge (TARGET ≠ main)

```bash
git checkout <TARGET>
git merge <SOURCE>      # fast-forward or merge commit as git decides
```

Resolve conflicts the same way as 3a. No squash for non-main targets unless the user asked.

## Step 4 — Push (confirm first)

Show what will be pushed (`git log --oneline origin/<TARGET>..<TARGET>`) and **ask before pushing** — pushing is outward-facing.

- Fast-forward (squash commit sits on top of `origin/main`, which is the common case) or regular merge:
  ```bash
  git push origin <TARGET>
  ```
- Only if the push is rejected because the squash rewrote existing history, and after the user confirms:
  ```bash
  git push --force-with-lease origin main
  ```
  Prefer `--force-with-lease` over `--force` — it refuses to clobber commits you haven't seen. If it fails, stop and show the user; do **not** escalate to `--force` without explicit approval.

## Step 5 — Commit message trailer

End every merge/squash commit message with a blank line then:

```
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
```

## Step 6 — Report

Tell the user: what merged, the new commit SHA on TARGET, whether it was pushed, and (if squash) the squashed message. Leave the user back on their original branch unless they asked otherwise:

```bash
git checkout <SOURCE>   # or wherever they started
```

## Guardrails

- Never push to `main` without explicit confirmation in this session.
- Never `git push --force` (without `-with-lease`) unless the user explicitly says to.
- Never merge over a dirty working tree.
- Never invent a squash commit message and commit it silently — always show it first.
- If anything diverges unexpectedly (e.g. `--force-with-lease` rejected), STOP and surface it. Don't guess.
