Gitのcherry-pickを使ってみる話

Gitを使う前は、Subversionを使っていたのですが、
お仕事で苦労したのは、社内用にガシガシ開発して、
それをベースに機能限定版みたいのを作る場合とかですね。

こういう場合のプロジェクト構成って、いくつか方法あると思ってて、
ライフゲーム(Google Play)の場合はこんな感じにしています。

.
├── LifeGameLib
├── LifeGameWallpaper   # 無料Ver.
├── LifeGameWallpaperEx # 有料Ver.
├── Release
└── keynote

これはこれで良いのかなって思ってますが、
有料Ver.に行った修正を無料Ver.に反映するには、
マージツールとか使ったりして、結構面倒臭い作業をしています。

で、最近も似たような作業をしたのですが、
その時は、git cherry-pickを使ってみたので紹介してみようと思います。

まずは、フォルダ構成から。

.
├── AppFull
├── AppLite
└── Repo
    ├── AppFull
    └── AppLite

次に、AppFullリポジトリでガシカシ開発を行います。
$ cd AppFull
$ git init
$ echo aaa >> readme.txt
$ git add readme.txt
$ git commit -m "初回コミット"
$ echo bbb >> readme.txt
$ git commit -a -m "bbbを追加"
$ echo ccc >> readme.txt
$ git commit -a -m "cccを追加"
$ echo ddd >> readme.txt
$ git commit -a -m "dddを追加"
$ echo eee >> readme.txt
$ git commit -a -m "eeeを追加"

これで一通りの作業が終わったとします。
次に、これらをリモートリポジトリにプッシュします。

まずは、”Repo/AppFull”を共有リポジトリとして初期化。
$ cd ../Repo/AppFull
$ git init --bare

次に、リモートリポジトリとして追加してプッシュ。
$ cd ../../AppFull
$ git remote add origin ../Repo/AppFull
$ git push -u origin master

今度は、機能限定版であるAppLiteリポジトリに取り掛かります。
$ cd ../AppLite
$ git clone ../Repo/AppFull .

次に、機能に相当する”ccc”と”ddd”を削って、コミットします。
$ cat readme.txt
aaa
bbb
eee
$ git commit -a -m "cccとdddを削除"

先ほど同様に、リモートリポジトリを追加してプッシュします。
$ cd ../Repo/AppLite
$ git init --bare
$ cd ../../AppLite
$ git remote set-url origin ../Repo/AppLite
$ git push -u origin master

これで、originのURLを”Repo/AppLite”に変更して、
リモートリポジトリにプッシュするところまで完了しました。

ここまでが今回の準備作業です。
次に、AppFullリポジトリをガシガシ開発します。
$ echo fff >> readme.txt
$ git commit -a -m "fffを追加"
$ echo ggg >> readme.txt
$ git commit -a -m "gggを追加"
$ git push

そして、機能限定版の方に”fff”を追加するとします。
さて、どうしましょう?

まずは、AppLiteリポジトリに移動して、
“Repo/AppFull”をfullという名前で、リモートリポジトリとして追加します。
$ cd ../AppLite
$ git remote add full ../Repo/AppFull

次に、リモートリポジトリfullの情報を取得します。
$ git fetch full

そして、git guiを使って、
[リポジトリ]-[すべてのブランチの履歴を見る]を選択します。
そして、”fff”を追加したときのコミットのハッシュを選択してコピーします。
この場合も、最初の4桁が他と重複しないのであれば、その4桁だけで十分です。
そして、以下のコマンドを実行してマージします。(*1)
$ git cherry-pick 2a04
[master cae68da] fffを追加
1 file changed, 1 insertion(+)

無事、マージできたことを確認します。
$ cat readme.txt
aaa
bbb
eee
fff

あとは、プッシュするだけですね。
$ git push

最後に、fullをリモートリポジトリから削除します。
$ git remote remove full

これで、リポジトリ間のマージが完了しました。
経験上、機能限定版のようにカスタマイズVer.を何パターンも作る場合は、
同じリポジトリにブランチを作って管理する方法も考えられますが、
メジャーバージョンアップする頃には原形をとどめてないとか、
納品して落ち着いたらハードディスクの片隅に追いやりたいとか、
そういうのもあって、リポジトリごと分けちゃった方がいいのかなって思ってます。
もちろん、リリースしてしばらくメンテしなきゃいけない場合は別ですが。

という訳で、「こんな方法もあるよ」程度に読んで頂ければと思います。

おしまい。

(*1) 2a04は、コピーしたハッシュをペーストしたものです

Leave a Comment