前回のDay 24では、本番環境の緊急障害に対応する「Hotfix」の完全手順と、developへのマージバックによる先祖返り防止サイクルを学びました。
本日のDay 25は、現場のエンジニアなら誰しも一度は遭遇する波乱のシチュエーション——【仕様変更・機能のリリース順序入れ替え(チェリーピック)】を徹底解説します!
「次の定期リリースに向けて、機能A(AIレコメンド機能)と機能B(請求書PDF決済機能)を並行して開発していたが、突然クライアントや経営陣から『機能Aは仕様再検討で来月に延期!でも機能Bだけは契約上、明日のリリースにどうしても間に合わせてほしい!』と頼まれた……」
このような「リリース順序の逆転」や「特定機能だけの先行リリース」は、アジャイル開発でも受託開発でも日常茶飯事です。
Subversion (SVN) や Visual SourceSafe (VSS) で開発していた時代、これに対応するのはまさに悪夢でした。トランク(trunk)に時系列でコミットされた変更の中から、関係するファイル差分を手作業で洗い出し、別ブランチへ手動でコピペしてビルドする「手動リビジョンマージ」を行っていました。その結果、未完成な機能Aのコードが誤って混入したり、コピペ漏れによるコンパイルエラーや実行時例外が多発していました。
しかしGitなら、「git cherry-pick」という極めて強力な武器があります!
Gitのコミットは、独立した変更パッチとして管理されています。そのため、木になっている熟した美味しいさくらんぼをスプーンで摘まみ取るように、「機能Bに関する特定のコミットだけ」を狙い撃ちして、安全にリリースブランチや本番ブランチへ移植・複製することができます!
本日は、Git CLIおよびTortoiseGitを使ったチェリーピックの完全手順、C#プロジェクトにおけるサービスクラス抽出の実戦例、
dotnet testによる二次災害防止、そしてコンフリクト発生時の対処(--continue / --abort)まで、現場で即戦力となるプロフェッショナルの技術を余すところなくお伝えします!
① 導入・本日の達成目標
アジャイルやスプリント開発の現場では、ビジネス環境の変化や顧客からの要望によって、開発ロードマップが急遽変更されることが頻繁にあります。
「ブランチ全体を丸ごとマージすることはできないが、特定の機能コミットだけを今すぐ本番へ届けたい」。
この要求にスマートに応えられるかどうかが、一人前のGitエンジニアとしての腕の見せ所です。
- SVNの「差分手動適用の混乱・ファイル混在事故」とGitの「コミット単位の安全な摘み食い(チェリーピック)」の違いを理解する
git logで目的のハッシュを特定し、git cherry-pickで特定コミットを別ブランチへ安全に移植する3ステップを習得する- C#プロジェクトにおいて、未完成クラス(AI機能)を延期しつつ完成クラス(決済サービス)のコミットだけを抽出し、
dotnet testで検証する実戦手順を身につける - TortoiseGitのコミットログ画面から、マウス操作で視覚的にチェリーピックを実行する手順を理解する
- コンフリクト(競合)発生時の解消作法(
--continueと--abort)およびコミットハッシュが変わる仕組みを把握する
② 【図解】SVNのリビジョンマージ vs Gitのチェリーピック:なぜGitなら安全に「摘み食い」できるのか?
まず、従来のSVNにおける部分マージと、Gitのチェリーピックの構造的な違いを比較してみましょう。
集中型バージョン管理(SVN)では、中央リポジトリの trunk にすべてのコミットが直線的に並んでいました。
特定の修正だけを別ブランチ(リリース用ブランチなど)に反映したい場合、SVNの svn merge -c [リビジョン番号] を実行するか、変更されたソースファイルを手動で特定して別フォルダにコピペする手法が取られていました。
- 不要な差分の巻き込み: 1つのリビジョンに複数の変更が混在していたり、依存関係が曖昧なため、リリースしてはいけない未完成コードや実験的設定が誤って紛れ込む。
- 追跡不能なマージ履歴: どのリビジョンがどこへマージされたのか履歴グラフとして視覚化されず、後から「このコードはいつ誰が移植したのか?」が闇に葬られる。
- 手動コピペによるヒューマンエラー: 開発者が慌ててファイルを手動で上書きした結果、別の修正が先祖返りで吹き飛ぶ。
これに対し、Gitにおけるコミットは「親コミットからの完全な差分スナップショット」です。
Gitの cherry-pick は、指定したコミットの差分内容を自動的にパッチとして抽出し、現在チェックアウトしているブランチの先端に「まったく新しいコミット」として適用してくれます。
これにより、他のブランチの未完成なコードには一切影響を与えず、必要な機能コミットだけをクリーンかつ確実に抜き出すことができるのです。
③ 【図解】チェリーピックの仕組みと実行の3ステップ完全手順
Git CLIを用いたチェリーピックの基本操作は、極めてシンプルです。
ステップ1: 移植したいコミットのハッシュ値を確認する
まず、抜き出したいコミットが存在するブランチのログを確認し、コミットハッシュ(7桁程度の英数字)を控えます。
git log --oneline develop
# 出力例:
c7d8e9f feat(ai): AIレコメンドエンジンの初期実装 (※今回は延期)
b2c3d4e feat(invoice): 請求書PDF決済サービスの追加 (★これを先行リリースしたい!)
a1b2c3d docs: 仕様書ドキュメント更新
ステップ2: 移植先のブランチへ切り替える
コミットを受け取りたいブランチ(例: release/1.1 や main)へスイッチします。
git switch release/1.1
ステップ3: git cherry-pick を実行する
控えておいたコミットハッシュを指定して、チェリーピックを実行します。
git cherry-pick b2c3d4e
# 複数コミットを連続適用したい場合(スペース区切り)
git cherry-pick b2c3d4e f1a2b3c
# 範囲指定で一括適用したい場合 (古いコミット..新しいコミット ※古い側は含まない)
git cherry-pick a1b2c3d..b2c3d4e
チェリーピックで適用されたコミットは、変更内容やコミットメッセージは元と同じですが、「親コミット(直前のコミット)」が異なるため、新しいハッシュ値(SHA-1)が割り当てられます。
元のコミットが移動するのではなく、クローン(複製)が移植先ブランチの先端に生成されると理解してください。
④ 【実戦C#編】仕様変更による特定サービスクラスの抽出とdotnet test検証
実際のC#ソリューションでの具体的なケーススタディを見てみましょう。
Web APIプロジェクトにおいて、develop ブランチ上で次のような2つの新機能が追加コミットされていたとします。
AiRecommendationService.cs: OpenAI APIを呼び出すレコメンド機能(※外部API仕様が未確定のためリリース延期決定)InvoicePaymentService.cs: 請求書決済ロジック(※顧客要請により先行リリース決定)
C#プロジェクトでの抽出手順
未完成のAI機能が混ざらないよう、請求書決済機能のコミット(および単体テストのコミット)だけを release/1.1 にチェリーピックします。
git switch release/1.1
git cherry-pick 8f4a12b
# C#ソリューションのビルド確認
dotnet build --configuration Release
# 単体テストの実行(回帰テスト&新機能テスト)
dotnet test --no-build --verbosity normal
C#(ASP.NET Core)では、サービスクラス単体だけでなく
Program.cs でのDI登録(builder.Services.AddScoped<IInvoicePaymentService, InvoicePaymentService>();)が必要です。コミットを分ける際は、「サービスクラスの実装」と「Program.csへの登録」「単体テスト」が正しく1つの機能コミット(または関連コミット群)にまとまっていることが重要です。
もしDI登録のコミットをチェリーピックし忘れると、実行時に
InvalidOperationException: Unable to resolve service for type... が発生するため、チェリーピック直後の dotnet test 実行は必須の安全弁となります!
⑤ 【GUI操作】TortoiseGitでの右クリックチェリーピックと競合解消
Windows / エクスプローラー上で直感的に作業したい開発者のために、TortoiseGitでのチェリーピック手順とコンフリクト対策を確認しましょう。
TortoiseGitでの操作手順
- エクスプローラーで作業フォルダを右クリックし、移植先ブランチ(
release/1.1)にスイッチします。 - 右クリックメニューから [TortoiseGit] → [ログを表示 (Show Log)] を開きます。
- 画面左上のブランチ選択で「すべて参照 (All Branches)」または
developを選択し、コミット一覧を表示します。 - 移植したいコミットを右クリックし、[このコミットをチェリーピック (Cherry Pick this commit...)] を選択します。
- 確認ダイアログで [続行 (Continue)] を押すと、瞬時に現在のブランチへ変更が適用されます。
万が一コンフリクト(競合)が発生した場合の対処
もし移植対象のコードが、移植先ブランチの既存コードと同一箇所を変更していた場合、チェリーピックは一時停止してコンフリクト状態になります。
焦る必要はありません。Gitは安全のために停止しているだけです。
| コマンド | 説明と使い所 |
|---|---|
| git cherry-pick --continue | 競合ファイルをエディタやTortoiseGitマージで解決し、git add した後に入力してチェリーピックを再開・完了する。 |
| git cherry-pick --abort | 「競合が複雑すぎる!一旦元の状態に戻したい!」という時に実行。チェリーピック開始前の状態に完全ロールバックする。 |
| git cherry-pick --skip | 複数コミットを範囲指定した際、特定のコミットが既に適用済みなどの理由で不要な場合にスキップする。 |
⑥ チェリーピック運用の鉄則と「後からの全体マージ」の挙動
「チェリーピックしたコミットは、後から develop を main に正式マージしたときに重複してコンフリクトしないのか?」
これは多くのエンジニアが抱く疑問です。
Gitは内部的に「パッチID(変更内容のハッシュ)」を比較する仕組みを持っています。
そのため、後日
develop ブランチ全体を main や release にマージした際、Gitは「この変更はチェリーピックですでに適用済みである」と自動検知し、重複適用をスキップしてくれます!したがって、チェリーピックを行ったからといって将来のマージが破綻することはありません。
- コミットの粒度を小さく保つ: 1つのコミットに「AI機能」と「決済機能」が混ざっていると、チェリーピックで分離できません。普段から「1機能1コミット」を徹底しましょう。
- チェリーピックのログを残す:
git cherry-pick -x [ハッシュ]とオプション-xを付けると、コミットメッセージに「(cherry picked from commit ...)」という出処が自動記録され、チームメンバーが追跡しやすくなります。 - 迷ったらブランチ全体の再構築を検討: 10個も20個もチェリーピックを乱発する事態になったら、抽出ブランチを新設して必要な機能ブランチだけをマージする構成を検討しましょう。
📌 本日の講義まとめと実践チェックリスト
Day 25では、現場の仕様変更やリリース順序入れ替えに柔軟に対応する「チェリーピック」の真髄を学びました。
Google Antigravity や Claude Code などの最先端AIエージェントに「Issue #101 のバグ修正用ブランチを切り、C#コードを修正してテストを通し、PR(プルリクエスト)を作って」と一括指示する自動化シミュレーションを徹底解説。
人間が手を動かしていた定型業務をAIが完全自律代行する近未来の開発スタイルを体験しましょう!
コメント
コメントを投稿