How this skill is triggered — by the user, by Claude, or both
Slash command
/git:rebase-stackThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
이 skill은 stacked PR에서 base branch가 merge된 후 나머지 branch들을 순차적으로 rebase하고 force push합니다.
이 skill은 stacked PR에서 base branch가 merge된 후 나머지 branch들을 순차적으로 rebase하고 force push합니다.
restack <base-branch> <branch1> <branch2> ...
Full chain을 입력합니다 — merge된 branch도 포함합니다.
예: restack develop feat/A feat/B feat/C → A가 이미 merge되었더라도 chain에 포함하여, B와 C를 정확히 rebase
먼저 저장소의 현재 상태를 확인합니다:
# Run in parallel
git status --porcelain
git fetch origin
git worktree list
확인 항목:
git branch --list <branch> 로 각 branch 존재 여부 확인git worktree list 출력에서 대상 branch가 없어야 함상태 확인 실패 시:
모든 branch의 현재 tip을 rebase 시작 전에 미리 저장합니다:
OLD_BRANCH1=$(git rev-parse <branch1>)
OLD_BRANCH2=$(git rev-parse <branch2>)
OLD_BRANCH3=$(git rev-parse <branch3>)
# ...
각 branch가 base에 이미 merge되었는지 감지합니다:
# regular merge / fast-forward 감지
git merge-base --is-ancestor <branch> <base-branch>
Squash merge 대응: --is-ancestor 검사가 실패하지만 실제로는 merge된 경우가 있습니다 (squash merge). 이 경우 rebase 계획 단계에서 사용자에게 AskUserQuestion으로 확인합니다:
❓ feat/A 브랜치가 develop에 이미 merge되었나요?
(squash merge는 자동 감지가 불가합니다)
[예 / 아니오]
merged/unmerged 판정 결과를 기반으로 rebase 대상 branch와 commit 수를 파악합니다:
# unmerged branch만 대상. 이전 branch 대비 commit 수
git log --oneline <prev-branch>..<branch>
계획을 사용자에게 보여줍니다:
📋 Rebase 계획:
⏭️ feat/A: merged → skip
1. feat/B (3 commits) → develop 위로 rebase (--onto develop $OLD_A)
2. feat/C (2 commits) → rebased feat/B 위로 rebase (--onto feat/B $OLD_B)
계속 진행하시겠습니까?
AskUserQuestion으로 확인을 받습니다. 사용자가 거절하면 종료합니다.
핵심 알고리즘 (--onto + old tip 기반):
current_target을 base-branch로 초기화하고, chain의 각 branch를 순서대로 처리합니다.
current_target = <base-branch>
for each bi in [branch1, branch2, ...]:
if bi is merged:
skip (current_target 변경 없음)
else:
old_parent = OLD tip of previous branch in chain
(첫 번째 unmerged branch이고 이전이 모두 merged이면:
git merge-base <bi> <base-branch>)
git rebase --onto $current_target $old_parent bi
current_target = bi
구체적 실행 예시 (develop → a → b → c, a가 squash merge됨):
# 사전 저장된 old tips
OLD_A=... OLD_B=... OLD_C=...
# a: merged → skip, current_target = develop
# b: unmerged, 이전 branch = a (merged)
# old_parent = OLD_A (a의 rebase 전 tip)
git rebase --onto develop $OLD_A b
# → a의 커밋 제외, b 자체 커밋만 replay
# current_target = b
# c: unmerged, 이전 branch = b
# old_parent = OLD_B
git rebase --onto b $OLD_B c
# current_target = c
old_parent 결정 규칙:
| 상황 | old_parent |
|---|---|
| 이전 branch가 chain에 존재 (merged/unmerged 무관) | 이전 branch의 OLD tip |
| chain의 첫 번째 branch이면서 unmerged | git merge-base <branch> <base-branch> |
각 rebase 완료 후 결과를 표시합니다:
✅ feat/B: develop 위로 rebase 완료 (abc1234 → def5678)
Rebase 중 충돌이 발생하면:
git diff --name-only --diff-filter=U
⚠️ feat/B를 rebase하는 중 충돌이 발생했습니다.
충돌 파일:
- src/components/UserList.tsx
- src/hooks/useUsers.ts
충돌을 해결한 후 알려주세요.
AskUserQuestion으로 "충돌을 해결하셨나요? (해결완료 / 중단)" 질문합니다.
사용자가 "해결했다"/"해결완료"라고 답하면:
git add .
git rebase --continue
git rebase --abort
중단 사유를 표시하고 skill을 종료합니다.
모든 rebase가 완료된 후 각 branch를 force push합니다.
안전 규칙:
--force-with-lease 사용 (안전한 force push)develop, qa, main branch로는 절대 push 금지 — 이 branch가 대상에 포함되어 있으면 건너뛰고 경고AskUserQuestion으로 확인🚀 Force push 준비:
다음 branch들을 force push합니다:
1. feat/B → origin/feat/B
2. feat/C → origin/feat/C
각 branch를 force push하시겠습니까?
사용자가 확인하면:
git push --force-with-lease origin <branch1>
git push --force-with-lease origin <branch2>
각 push 결과를 표시합니다:
✅ feat/B → origin/feat/B push 완료
✅ feat/C → origin/feat/C push 완료
모든 작업 완료 후 최종 결과를 보고합니다:
🎉 Restack 완료!
📊 결과:
✅ feat/B: develop 위로 rebase 완료 + push 완료
✅ feat/C: feat/B 위로 rebase 완료 + push 완료
📐 최종 Stack 구조:
develop
└── feat/B (3 commits)
└── feat/C (2 commits)
restack develop feat/auth-api feat/auth-ui feat/auth-tests
결과:
feat/auth-api를 develop 위로 rebase (--onto develop $(merge-base) feat/auth-api)feat/auth-ui를 rebased feat/auth-api 위로 rebase (--onto feat/auth-api $OLD_API feat/auth-ui)feat/auth-tests를 rebased feat/auth-ui 위로 rebase (--onto feat/auth-ui $OLD_UI feat/auth-tests)develop → A → B → C 에서 A가 develop으로 squash merge된 후:
restack develop feat/A feat/B feat/C
결과:
feat/A: merged → skipfeat/B: git rebase --onto develop $OLD_A feat/B (A의 커밋 제외, B 자체 커밋만 replay)feat/C: git rebase --onto feat/B $OLD_B feat/Cdevelop → A → B → C → D 에서 A, B가 순차 merge된 후:
restack develop feat/A feat/B feat/C feat/D
결과:
feat/A: merged → skipfeat/B: merged → skipfeat/C: git rebase --onto develop $OLD_B feat/C (current_target은 develop, old_parent는 B의 old tip)feat/D: git rebase --onto feat/C $OLD_C feat/D--force-with-lease를 사용하여 다른 사람의 push를 덮어쓰지 않도록 합니다--onto의 upstream으로 사용합니다npx claudepluginhub flex-hyuntae/claude-plugins --plugin gitProvides advanced Git rebase patterns for linear history, stacked PRs, commit cleanup, and converting merge-heavy branches using --reapply-cherry-picks, --onto, and interactive workflows.
Builds, publishes, synchronizes, validates, merges, and cleans up stacked pull requests without corrupting branch topology.
Rebases the current feature branch onto the base branch (main/master/develop) to keep it up-to-date and prevent merge conflicts.