git-rebase-sync について
現在のフィーチャーブランチを最新のベースブランチに rebase するワークフローのスキルです。履歴を書き換える前に確認を求め、意図が不明な競合では質問します。
主な機能
- 01rebase 前のバックアップタグ作成
- 02履歴変更前の確認
- 03スタックブランチの検出と更新
- 04質問による競合解決
- 05rebase 後の検証と安全な push
活用シーン
- 01最新のベースブランチへの追従
- 02意図が不明な競合の解決
- 03依存するローカルブランチを伴う rebase
インストール
コマンドをコピーしてターミナルで実行します。
$
npx skills add https:/ / github.com/ alleneubank/ claude-code --skill git-rebase-syncインストール後、Claude Code で/git-rebase-syncを入力して読み込まれたか確認します。
詳細
git-rebase-sync
git rebase を使って機能ブランチを最新の origin/{base_branch} に同期する必要がある場合に、このスキルを使用します。意図が曖昧な場合は、明確な確認質問を行って競合を解決します。
目標
- 現在のブランチを、指定されたベースブランチ(通常は
devやmainなどのリポジトリのデフォルトブランチ)にリベースします。 - 推測せず、意図を確認して競合を解決します。
- バックアップ参照、履歴を書き換えるコマンドの実行前の確認、安全なプッシュなどの安全策を維持します。
厳守事項
- 別の機能ブランチを作成したり、そこに切り替えたりしないでください。明示的に依頼された場合を除き、現在のブランチ名のまま作業してください。
- 履歴を書き換えるコマンド(
git rebase ...、git push --force*)を実行する前に、実行するコマンドを正確に表示し、確認を待ってください。 - リベースを開始する前に、ローカルのバックアップ参照(注釈付きタグを推奨)を作成してください。明示的に依頼された場合を除き、バックアップ参照をプッシュしないでください。
git push --force-with-leaseを優先し、通常の--forceは決して使わないでください。- 正しい競合解決方法が不明な場合は、作業を止め、対象を絞った質問をしてください。製品の動作をでっち上げないでください。
ワークフロー
1) ベースブランチとブランチを特定する
- 現在のブランチを確認します。
git branch --show-current
- リベース先のベースブランチを確認します。
- 指定がない場合は、GitHub のデフォルトブランチを使用します。
gh repo view --json defaultBranchRef --jq '.defaultBranchRef.name'
- 指定がない場合は、GitHub のデフォルトブランチを使用します。
- 最新の情報を取得します。
git fetch origin
2) 事前の安全確認
- 作業ツリーがクリーンで、進行中の操作がないことを確認します。
git status
git statusでマージ、リベース、チェリーピックが進行中と示された場合は、作業を止め、中止するか続行するかを確認してください。
3) ローカルのバックアップ参照を作成する(プッシュしない)
- 現在の
HEADに注釈付きタグを作成します。git tag -a {branch_name}-rebase-backup-$(date +%Y%m%d-%H%M%S) -m "pre-rebase backup" HEAD
- 復旧用に、タグ名を
{backup_ref}として記録します。
4) リベースモードを選択する(通常モードまたはマージを保持)
- ブランチにマージコミットが含まれているか確認します。
git rev-list --count --merges origin/{base_branch}..HEAD
- マージコミットがある場合は、
--rebase-mergesで保持するか、通常のリベースでフラット化するかを確認してください。
5) スタックされたブランチを検出する(リベースに追従するか)
他のローカルブランチが、書き換え対象の範囲(origin/{base_branch}..HEAD)内の中間コミットを指している場合があります。段階的な NN-description スタックではよくある状況です。通常のリベースではそれらのコミットが書き換えられ、スタックされたブランチはリベース前の古いコミット上に取り残されます(それらをベースにしたオープン中の PR もすべて同様です)。手順 6 のデフォルトである --update-refs を使うと、それらのブランチも書き換え後のコミットに移動します。リベースによって引き継がれるブランチを報告できるよう、一覧を取得してください。
# Branches pointing into the range being rewritten — these get orphaned by a
# plain rebase and require --update-refs to follow the rewrite.
cur=$(git branch --show-current)
git for-each-ref --format='%(refname:short)' refs/heads | while read -r br; do
[ "$br" = "$cur" ] && continue
if git merge-base --is-ancestor "$br" HEAD \
&& ! git merge-base --is-ancestor "$br" origin/{base_branch}; then
echo "stacked: $br ($(git rev-parse --short "$br"))"
fi
done
- リベース前に、検出したスタックされたブランチを報告してください。
- 別のワークツリーでチェックアウトされているブランチは
--update-refsの対象外となり(Git はチェックアウト中のブランチを移動しません)、リベース後に手動で確認できるよう、そのブランチを明示してください。
6) リベースを実行する(確認が必要)
- 書き換え対象の範囲内にあるコミットを指すスタックされたブランチが取り残されず、書き換えに追従するよう、デフォルトで
--update-refsを使用します。 - 実行するコマンドを正確に表示し、確認を待ってください。
- デフォルト:
git rebase --update-refs origin/{base_branch}
- マージを保持する場合:
git rebase --rebase-merges --update-refs origin/{base_branch}
- デフォルト:
- この設定をフラグなしで永続的なデフォルトにするには、
git config --global rebase.updateRefs trueを実行します。
7) 競合への対応ループ
競合が発生した場合:
- コンテキストを収集します:
git status- status の出力から競合しているファイルを特定します。
- 競合しているファイルごとに:
- ファイルを開き、周辺のコードと意図を把握します。
- 最小限で機械的な競合解決を優先します:
- 機能ブランチで意図的に置き換える場合を除き、upstream の変更を維持します。
- 必要に応じて、手作業で編集するのではなく、ジェネレーター(ロックファイル、コード生成)を再実行します。
- 意図が曖昧な場合は、次のような具体的な質問を1つだけします:
- 「upstream の新しい動作 X と、機能の動作 Y のどちらを維持しますか?」
- 「このファイルは生成されたもので、再生成しても問題ありませんか。それとも手動で解決しますか?」
- 解決を適用し、解決済みのファイルのみをステージします:
git add <file...>
- 続行します:
git rebase --continue
- 解決のリスクが高すぎる、または不明確な段階に達した場合:
- 停止して確認します。必要に応じて、リベースの中止を提案します。
競合時に役立つコマンド:
- 現在の競合箇所を確認する:
git diff - 再適用中のコミットを確認する:
git show - 元に戻す必要がある場合:
git rebase --abort(これは安全なため、破壊的なリセットより優先してください)
8) リベース後の検証
- 新しいコミット範囲を表示します:
git log --oneline --decorate origin/{base_branch}..HEAD
- 手順5のスタックされた各ブランチが、書き換え後の範囲に移動したことを確認します。
git rebase --update-refsは「Updated the following refs with --update-refs」という概要を出力します。移動したブランチの参照は、上記のログで新しいコミットのデコレーションとしても表示されます。移動しなかったもの(たとえば、別のワークツリーでチェックアウトされているもの)があれば、手動で対応できるよう記録します。 - 利用可能であれば、適切なリポジトリのチェック(テスト、型チェック、Lint)を実行します。
9) 更新したブランチをプッシュする(確認が必要)
- ブランチがすでに origin に存在する場合、リベースによって履歴が書き換えられるため、プッシュには force-with-lease が必要です。
--update-refsが移動するのはローカル参照のみです。通常のgit pushで更新されるのは現在のブランチだけです。origin にも存在するスタックされた各ブランチ(手順5)を、それぞれ個別に force-push する必要があります。- 正確なコマンドを表示し、確認を待ちます:
- 現在のブランチ:
git push --force-with-lease origin HEAD:{branch_name}
- origin に存在する、移動した各スタックブランチ(ブランチごとに繰り返します):
git push --force-with-lease origin {stacked_branch}
- 現在のブランチ:
- 別のワークツリーでチェックアウトされているためにスキップされたブランチは移動していません。プッシュ前に確認してください。
復旧
- 問題が発生した場合は、
{backup_ref}を使用してリベース前の状態に戻します。 - 正確なコマンドを提示したうえで私が明示的に確認するまでは、破壊的なコマンド(例:
git reset --hard)を実行しないでください。
コメント
Markdown 対応