目的
cherry pick とはサクランボを摘み取るという意味で、「つまみ食い」「いいとこどり」
というような意味合いで使われることがあるようだ。
gitも同様に、他のブランチの特定のコミットだけをマージする、という機能がある。
それが git cherry-pick というわけだ。
実行してみる
git checkout master
git log --oneline
178bb3e M6
79e881b M5
cdfce70 M4
e4eddce M3
2e732c0 M2
b9d760c M1
git checkout sub
git log --oneline
ad1376f S2
29ac875 S1
e4eddce M3
2e732c0 M2
b9d760c M1
上記の通り、事前の環境を準備しておく。
M1というコミットは、M1.txtというファイルが存在していて、
その中身もM1という記載だけのファイルを意味する。
上記のログを図にしてみると、
M1---M2---M3---M4---M5---M6 masterブランチ
\
---S1---S2 subブランチ
このような状態になっている。
ここで、M6のみのコミットを、subブランチにマージしたいという状況が発生した場合、
subブランチにチェックアウトしたあと、masterブランチを普通にマージ処理してしまうと、
もれなく、M4、M5も一緒になってsubブランチにマージされてしまう。
そうではなく、M6という1つのコミットのみをスポットでsubブランチにマージさせたい。
それを実現するために cherry-pick を利用する。
ここでは、M6ではなく、M5 のみスポットでsubブランチにマージしてみる。
git checkout sub
git cherry-pick 79e881b
[sub dd0d059] M5
Date: Fri Oct 30 13:57:34 2020 +0900
1 file changed, 1 insertion(+)
create mode 100644 M5.txt
※79e881b←これはM5のコミットID
git log --oneline
dd0d059 M5
ad1376f S2
29ac875 S1
e4eddce M3
2e732c0 M2
b9d760c M1
上記の通り、M5のコミットのみがマージされ
M4は含まれてないことが確認できた。
実際のフォルダの中身を確認してみたところ、
M1.txt
M2.txt
M3.txt
M5.txt
S1.txt
S2.txt
が存在し、M4.txtが存在しないことを確認できたので、cherry-pickの動作が確認できた。
図で表すと下記のようになる。
M1---M2---M3---M4---M5---M6 masterブランチ
\
---S1---S2---M5 subブランチ
今度は、取りこみはするけれどコミットはしない。
というものを試してみる。
この場合は、-n オプションを付ければよい。
上記の状態から、subブランチにM4を取りこんでみようと思う。
git checkout sub
git cherry-pick -n cdfce70
※cdfce70←これはM4のコミットID
git log --oneline
dd0d059 M5
ad1376f S2
29ac875 S1
e4eddce M3
2e732c0 M2
b9d760c M1
上記の通り変動はなく、新たなコミットは生成されてないことが確認できた。
しかし、実際のフォルダの中身を確認してみたところ、
M1.txt
M2.txt
M3.txt
M4.txt
M5.txt
S1.txt
S2.txt
見てわかる通り、M4.txt が存在していた。
調べたりして学んだこと
- 他のブランチの中から必要なコミットだけをスポットで取りこむことができることを理解した
- コミットメッセージも引き継がれるようなので、git cherry-pick -e コミットID これで編集ができる