git cherry-pick で複数のコミットを指定する2つの方法

試した環境

本題

git cherry-pickコマンドで複数のコミットを指定する方法を2つ記します。 一つはコミットを列挙する方法、もう一つはコミット範囲指定する方法です。

まず、例示するために以下の通り環境を作ります。

git init
echo 1st>1st.txt
git add -A
git commit -m "1st commit"
echo 2nd>2nd.txt
git add -A
git commit -m "2nd commit"
git switch -c subbranch
echo 3rd>3rd.txt
git add -A
git commit -m "3rd commit"
echo 4th>4th.txt
git add -A
git commit -m "4th commit"
echo 5th>5th.txt
git add -A
git commit -m "5th commit"
git switch master

git log --oneline --allで出力したものが以下の通りです。

a7c5ac6 (subbranch) 5th commit
412ad02 4th commit
c5b21e4 3rd commit
394abab (HEAD -> master) 2nd commit
61d8c02 1st commit

以下の各例示はこの状態からスタートします。

コミットを列挙して指定する

cherry-pick したいコミットを列挙して指定します。 スペース区切りで列挙します。

git cherry-pick subbranch~2 subbranch

git log --onelineで出力したものが以下の通りです。

b5faa69 (HEAD -> master) 5th commit
1803313 3rd commit
394abab 2nd commit
61d8c02 1st commit

上記のコマンド指定ではsubbranchブランチが現在指しているコミットとその2つ前のコミットの変更が反映されます。 4th commitは指定していないので取り込まれておりません。

コミット範囲を指定する

cherry-pick したいコミットが連続している場合はコミットの範囲を指定することも可能です。

git cherry-pick subbranch~2..subbranch

git log --onelineで出力したものが以下の通りです。

07a228c (HEAD -> master) 5th commit
0ca0c1a 4th commit
394abab 2nd commit
61d8c02 1st commit

3rd commit がないことに注意です。

この指定方法はドキュメントに以下の通り説明があります。

https://git-scm.com/docs/gitrevisions#_revision_range_summary

> <rev1>..<rev2>
> 
>     Include commits that are reachable from <rev2> but exclude those that are reachable from <rev1>. When either <rev1> or <rev2> is omitted, it defaults to HEAD.

要するに左側に指定したコミットは範囲に含まれません。 この表現方法はgit cherry-pick以外のコマンドで左側を分岐の始点とする場合とかに便利なのだろうと感じました。

参考

Git - git-cherry-pick Documentation

Git - gitrevisions Documentation