skills/fix-rebase-conflicts/SKILL.md
Resolve git rebase conflicts methodically. Classifies each conflict (imports/namespace cleanup vs real logic clash), analyzes the commit introducing the change against the current ticket context, auto-fixes only trivial cases with a per-file summary, and asks the user when ambiguous. Verifies static analysis tools pass at the end and optionally runs functional tests. Use after `git rebase` triggers conflicts, or when the user asks to "resolve conflicts", "fix rebase", "j'ai des conflits", "aide-moi sur ce rebase".
npx skillsauth add nicolas-codemate/claudecodeconfig fix-rebase-conflictsInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
This skill resolves rebase conflicts carefully. It distinguishes trivial conflicts (imports, namespaces, cosmetic) from real semantic conflicts. For real conflicts, it analyzes the commit introducing the change against the current ticket context. When in doubt, it asks the user instead of guessing.
$ARGUMENTS
--with-tests — also run functional tests after static checks (default: skip tests)--no-continue — stop after the report instead of running git rebase --continue (default: auto-continue)--file <path> — limit analysis to a single conflicted file (repeatable)Worktree caveat: in a git worktree,
.gitis a file pointing to the real git directory, so[ -d .git/rebase-merge ]always returns false. Always resolve rebase paths throughgit rev-parse --git-path— never hardcode.git/....
REBASE_MERGE_DIR=$(git rev-parse --git-path rebase-merge)
REBASE_APPLY_DIR=$(git rev-parse --git-path rebase-apply)
if [ ! -d "$REBASE_MERGE_DIR" ] && [ ! -d "$REBASE_APPLY_DIR" ]; then
# Cross-check: a rebase can also be inferred from `git status --porcelain=v2 --branch`
if ! git status --porcelain=v2 --branch | grep -qE '^# branch.head \(no branch'; then
echo "ERROR: aucun rebase en cours."
exit 1
fi
fi
If git diff --name-only --diff-filter=U is empty, the rebase has no remaining conflicts. Tell the user to run git rebase --continue themselves and stop.
REBASE_MERGE_DIR=$(git rev-parse --git-path rebase-merge)
REBASE_APPLY_DIR=$(git rev-parse --git-path rebase-apply)
CONFLICTS=$(git diff --name-only --diff-filter=U)
BRANCH=$(git rev-parse --abbrev-ref HEAD)
REBASE_HEAD=$(git rev-parse REBASE_HEAD 2>/dev/null \
|| cat "$REBASE_MERGE_DIR/stopped-sha" 2>/dev/null)
ONTO=$(cat "$REBASE_MERGE_DIR/onto" 2>/dev/null \
|| cat "$REBASE_APPLY_DIR/onto" 2>/dev/null)
# The "incoming" commit being applied
git log -1 --format='%H%n%s%n%n%b' "$REBASE_HEAD"
Locate ticket context, in this order:
.claude-work/{ticket-id}/ticket.md.claude_resolve/{ticket-id}/ticket.mdfeature/ABC-123-...) → infer ticket IDgit log -1 ORIG_HEAD --format=%s if available)Display a one-line summary before touching anything:
Rebase: {BRANCH} onto {ONTO}
Stopped at: {short-sha} {subject}
Ticket: {id} — {title (if known)}
Conflicts: {N} fichier(s)
For each conflicted file, follow this flow strictly. Process files sequentially — do not parallelize.
Read the file. A single file may contain several <<<<<<< ... ======= ... >>>>>>> blocks. Classify each block independently:
| Class | Definition |
|---|---|
| A — Imports/namespace | The block sits exclusively in use / import / from / namespace / require lines at the top of the file. No logic affected. |
| B — Cosmetic / mechanical | Both sides do the same thing in slightly different style (formatting, reordering of independent items, identical logic with different whitespace). |
| C — Real semantic conflict | At least one side changes runtime behavior, signatures, control flow, or data shape. |
If the file mixes classes, resolve each block independently and aggregate the summary at the file level.
grep -E '^use ' {file} | awk '{print $NF}' | sed 's/;//' | while read sym; do
short=$(basename "${sym//\\//}")
grep -q "\b$short\b" {file} || echo "UNUSED: $sym"
done
Adapt for JS/TS (import { X } from), Python (from x import Y), Go (import "...").Pick the version that matches the project's prevailing style (formatter config, neighboring code). Note the choice in the summary in one line.
Do all of the following before deciding:
git log -1 --format=full "$REBASE_HEAD"
git show --stat "$REBASE_HEAD"
git show "$REBASE_HEAD" -- "{file}"
git log -5 --format='%h %s' HEAD -- "{file}"
git blame -L {line-start},{line-end} HEAD -- "{file}"
main) or part of the feature being rebased?Then decide:
Clearly resolvable — one side is unambiguously correct given the ticket and the commit's intent (e.g. incoming adds the very behavior the ticket asks for; ours-side is a stale unrelated change from main that's compatible if combined):
Edit.Ambiguous, complex, or risky — anything where the choice would be a guess:
AskUserQuestion with:
Bias toward asking. A wrong auto-resolution can introduce a silent bug that survives the rebase and lands in the merge. The cost of one extra question is much lower than the cost of a buggy rebase.
After every block in the file is resolved, double-check no conflict markers remain before staging:
if grep -qnE '^(<<<<<<<|=======|>>>>>>>)' "{file}"; then
echo "ERREUR: marqueurs de conflit encore présents dans {file}"
exit 1
fi
git add "{file}"
Auto-detect the project's static tooling and run it. Do not consider the work done if any tool fails.
composer.json → check scripts.{lint,phpstan,psalm,cs} and binaries in vendor/bin/ (phpstan, psalm, php-cs-fixer, phpcs)package.json → check scripts.{lint,typecheck,check} and tsc/eslintpyproject.toml / mypy.ini / ruff.toml → mypy, ruff check.golangci.yml → golangci-lint runMakefile targets named lint, check, static, qa, analyseRun the detected tools sequentially. Prefer running them only on files touched during this rebase when the tool supports a file list:
TOUCHED=$(git diff --name-only "$ONTO"...HEAD)
If a tool fails:
Display a single consolidated report:
=== Résolution des conflits de rebase ===
Auto-résolus (sans question) :
- {file}: imports fusionnés, {N} inutilisés supprimés
- {file}: cosmétique, version "theirs" alignée sur le style du projet
Résolus avec analyse (à relire) :
- {file}:{lines}
Commit entrant : {sha} "{subject}"
Décision : pris theirs
Justification : le commit entrant ajoute le chemin d'erreur exigé
par le ticket {id} ; le côté "ours" était un refactor
local devenu obsolète après l'évolution de main.
Résolus par toi (instructions appliquées) :
- {file}:{lines}: {résumé du choix utilisateur}
Outils statiques :
✔ phpstan (level 8) — 0 erreur sur les fichiers touchés
✔ php-cs-fixer — propre
✔ tsc --noEmit — propre
[--with-tests]
Tests fonctionnels : {statut}
After printing the report, automatically run git rebase --continue unless any of these blockers apply:
--no-continue was passedAskUserQuestion and the user explicitly asked to stop and review.git/rebase-merge/interactive exists) and stopped on a non-conflict step (edit, break)If continuing:
git -c core.editor=true rebase --continue
The core.editor=true override prevents an interactive editor from blocking on the commit-message confirmation step. If the rebase stops again on a new conflict, re-enter the skill loop (Phase 0) on the new conflict set — fully sequential, no parallelism. Keep going until the rebase completes, the work tree is clean, or a blocker stops the loop.
Once the rebase completes (.git/rebase-merge and .git/rebase-apply both gone):
Rebase terminé. {N} commit(s) replayés.
État final : git log --oneline {ONTO}..HEAD
If a blocker stopped auto-continue, print the blocker reason and the manual next step:
Auto-continue désactivé : {raison}.
Quand tu es prêt :
git rebase --continue
--with-tests)Detect and run the project's primary test command:
composer test, vendor/bin/phpunit, vendor/bin/pestnpm test, npm run test:unit, pnpm test, yarn testpytestgo test ./...make test if presentRun the unit/functional suite — not the whole CI pipeline. If tests fail:
git checkout --ours/--theirs blindly — that short-circuits the per-block analysis the user explicitly asked for.git rebase --abort automatically — that throws away the work. Auto---continue is fine (the user opted in by default), but --abort is destructive and always requires explicit user confirmation.git restore to "make things cleaner". Destructive git is forbidden globally.git show $REBASE_HEAD -- {file} in full. This analysis is the whole point of the skill.[ -d .git/rebase-merge ] or any other .git/... path directly. In a worktree, .git is a file, not a directory, and the check silently always returns false — so the skill thinks no rebase is in progress when one is. Always go through git rev-parse --git-path rebase-merge (and friends).User-facing messages and the final report in French. Commands, code, log keys, and the AskUserQuestion option labels can stay in English where it reads more naturally.
Begin with $ARGUMENTS:
git rebase --continue unless a blocker applies (Phase 4). If a new conflict surfaces, loop back to Phase 0 sequentially.--with-tests, run the functional suite once the rebase has fully completed (Phase 5)tools
--- name: deep-review description: Performs deep code review via an isolated fresh agent (triple perspective, anti-bias). Use when the user asks for an in-depth review of current branch changes, or when invoked by /resolve step 08. Do NOT use for reviewing PRs from GitHub (use review-pr skill instead) or for a quick correctness scan with effort levels (use bundled /code-review instead). argument-hint: [--ticket <id>] [--base <branch>] [--fix] [--severity <level>] allowed-tools: Read, Glob, Grep,
development
Synchronize the markdown test plan in docs/qa/ with the current state of the codebase. Use after adding or modifying features to keep the plan up to date, or to bootstrap a test plan for the first time. Do NOT use to execute tests (use /qa-run instead) and do NOT use to design product specs (use /express-need instead).
tools
Execute the markdown test plan in docs/qa/ via Playwright MCP and create a ticket on each failing scenario. Use after /qa-sync, before a release, or to validate a feature end-to-end. Do NOT use to design or update scenarios (use /qa-sync instead) and do NOT use for visual regression (use visual-verify agent instead).
development
Onboard a project repository to the Codemate VPS multi-project hosting stack (vps-infra, Hetzner-hosted, shared Traefik + per-project rootless Docker). Use when the user asks to "deploy this project to the vps", "onboard on codemate-vps", "add this repo to the production VPS", "setup GHA deploy to my VPS", or when the user is clearly preparing a project (PHP/Symfony, Node, Python, Go, static) for hosting on codemate.consulting. Produces a production compose.yml, a GitHub Actions deploy workflow, and a clear out-of-repo checklist covering Ansible inventory, DNS (Gandi), GitHub secrets, and VPS .env seeding. Do NOT use for the vps-infra repo itself (which hosts the Ansible roles) — this skill is for the downstream project repos.