git rev-listの基本的な使い方とユースケース
はじめに
先日、以下の記事でも紹介したように全てのコミット数を取得するのにgit rev-list
というコマンドを初めて使った。
GitHubActionsでリポジトリ内の全てのコミット履歴を取得できるようにする
せっかくなので使い方をちゃんと調べてみようと思ったので基本的な使い方と使えそうなオプションをまとめておく。
また、実際にどういった場面で使うことになりそうかも考えてみた。
基本的な使い方
まず、git rev-list
というコマンド自体は指定したブランチ(またはコミット)から親ブランチをたどって到達できるコミットオブジェクトを逆年代順にリスト表示させるものだ。
例えば、以下のようにmain
ブランチを指定すると以下のようになる。
$ git rev-list main
# 出力結果
ebf897c26a983f936c2c280e5a50e171fa8e1dc0
a4df745d848e0992dd3a208332be48febf997241
0ed481ad7d21138c79a3785737830d5bd8018093
ブランチ以外にもコミットも指定することができる。上の出力の2番目のコミットオブジェクトを渡してみる。
$ git rev-list a4df745d848e0992dd3a208332be48febf997241
# 出力結果
a4df745d848e0992dd3a208332be48febf997241
0ed481ad7d21138c79a3785737830d5bd8018093
ブランチ(コミット)は複数指定すると、集合のような操作が可能になる。
例えば、以下ではhoge
とfuga
からたどれるコミットの和集合からhoga
からたどれるコミットを除いたものを出力できる。
git rev-list hoge fuga ^hoga
また、<commit1>..<commit2>
でブランチ(コミット)をつなげることでその範囲のコミットオブジェクトを取得できる。これは上記の集合操作から考えると、^<commit1> <commit2>
と同じ操作であるので省略形ととらえることもできる。
つまり、以下はどちらも同じ結果になる。
$ git rev-list origin..HEAD
$ git rev-list HEAD ^origin
さらに、<commit1>...<commit2>
のように.(ドット)
を3つつなげる記法もあるようだ。ドキュメントには結果はthe symmetric difference between the two operands
になると書いているが正直よく分からない。
以下の両者が同じ意味になると書かれているので、マージベースを除いた差分を出力するということなんだろうか?有識者の方がいらっしゃれば教えてください。
$ git rev-list A B --not $(git merge-base --all A B)
$ git rev-list A...B
とりあえず以上が基本的な使い方になる。
使えそうなオプション
せっかくなのでオプションもざっと見ておく。
--count
コミット数を出力する。総コミット数を出力するのに便利。
$ git rev-lsit --count HEAD
-<number>
, -n <number>
, --max-count=<number>
出力するコミットオブジェクトの数を制限する。コミット数が多くなってきた場合に便利だ。
$ git rev-list -5 HEAD
--since=<date>
, --after=<date>
コミットオブジェクトの日付を指定することができる。
$ git rev-list --after='2022-10-10' HEAD
$ git rev-list --after='1 hour ago' HEAD
$ git rev-list --after=1.hour.ago HEAD
--author=<pattern>
, --committer=<pattern>
author/commiterを指定できる。
$ git rev-list --author=okaryo HEAD
--merges
マージコミットだけ出力できる。
$ git rev-list --merges HEAD
ユースケース
コミットオブジェクトだけ見ていても何も生まれない(よね?)。
実際は他の何かと組み合わせて使うのだろう。的外れかもしれないがユースケースを考えてみた。
コミット数を知りたい
rev-list
単体で実現できるが、実際に自分もこれで初めてrev-list
を知ったので割とメジャーなユースケースなんじゃないだろうか。
$ git rev-list --count HEAD
複数のコミットをまとめてcherry-pickしたい
自分の場合は、コミットハッシュを使用するのはcherry-pick
するときなのでこういった使い方もできそうに思った。これなら一つずつcherry-pick
する必要はなくなって便利かも。
# コミットする場合
$ git rev-list --reverse branch1..branch2 | git cherry-pick --stdin
# コミットせずにcherry-pickのみ
$ git rev-list --reverse branch1..branch2 | git cherry-pick -n --stdin
特定のファイルに対する直近の変更内容を確認する
コミットハッシュを利用する場面としてgit diff
もあるだろう。これと組み合わせることで特定のファイルに対する直近の変更内容を確認することもできそうだ。
ちなみに--
はファイルパスを渡すための識別子だ。
$ git diff $(git rev-list -1 HEAD -- package.json)^ -- package.json
おわり
個人的にはあまり使ってこなかったrev-list
だが、ドキュメントには
rev-list is a very essential Git command, since it provides the ability to build and traverse commit ancestry graphs.
と書かれていてとても印象的だった。まだ自分には想像もつかない力がrev-list
にはあるのだろう。
Gitにはこれ以外にもたくさんのコマンドがあるし、まだまだGit道は奥が深そうだ。