どこでも見れるメモ帳

とあるSEの備忘録。何かあれば気軽にコメントください〜

マージコミットを含む大きめのgitブランチをcherry-pickで別ブランチに持っていくには

はじめに

f:id:ni66ling:20150726174614p:plain:w500
マージコミットを含む大きめのgitブランチを,別のブランチに持って行きたい状況が発生したのでメモ*1
取り込みたいブランチを1コミットにまとめ,これを取り込み先ブランチにcherry-pickマージする方法を記す*2
なお,複数コミットを1コミットにまとめる方法について,一般にはgit rebaseでsquashやfixupを用いることが多い*3が,マージコミットに対してはうまくいかなかった*4
そこで,ここでは取り込みたいブランチについて差分パッチを作成し適用するという方法をとった.

やりかた

# Xを1コミットにまとめるための一時的なブランチ(B_dummy)を作成
git checkout A1
git checkout -b B_dummy

# B1〜B3をパッチ化(参考[3])
git diff --binary A1..B3 > X.patch

# パッチをB_dummyにあて(参考[4]),B1〜B3を1コミット(=X)にまとめる
git apply X.patch
git add [target files]
git rm [target files]
git commit -m 'this is X: patch A1..B3'

# 別ブランチA'1に移動し,トピックブランチB'を作成し,Xをcherry-pickで持ってくる
git checkout A'1
git checkout -b B'
git cherry-pick X

参考

*1:ある機能セットを別プロジェクトのリポジトリに適用したいとか,エンタープライズ系で個別カスタマイズを一式持って行きたいとか,そういう状況

*2:以前は純粋にcherry-pickマージのみで行っていた.でもこれだとcherry-pick対象のリビジョン数が数百,数千になると,同じ箇所で生じるコンフリクト解消が地味にシンドかった

*3:参考[1]

*4:git rebaseのオプションで--interactiveと--preserve-mergesを併用し,その中でsquash/fixupを行うとエラーが生じてしまう.参考[2]