--ignore-revオプションで特定コミットをgit blameから除外する
はじめに
突然ですがみなさんはgit blame
してますか?
私は毎日git blame
しています!
git blame
した結果、その差分をコミットしたのは過去の自分と知るのは日常茶飯事です。
git blame
はコードリーディングの強力な味方ですが、LinterやFormatterをコードベース全体に適用すると、差分の情報がそれらで上書きされてしまい情報量が減ってしまいます。
そのような場合はgit history
で歴史を遡るしかないのでしょうか?
いいえ、git v2.23から追加された--ignore-rev
オプションで指定したコミットをblameから除外することができるようになりました。
git blame --ignore-rev
の使い方
--ignore-revにコミットハッシュを渡すとそのコミットはblameから除外されます。
# コミットハッシュは架空のものです
$ git blame --ignore-rev MyF4EkvOZNVKKJKqJv2pV8a2PBKWsyxfK4lTlMya
blame.ignoreRevsFile
を設定して常にIgnoreされるようにする
毎回--ignore-rev
を指定していては開発者体験が良くありません。
そんなあなたにgit-configのオプションが存在します。
git config --global blame.ignoreRevsFile .git-blame-ignore-revs
.git-blame-ignore-revs
にはコミットハッシュを羅列するだけですがそれが何をIgnoreするのかコメントをつけるとわかりやすいでしょう。
# Prettierで全コードをフォーマット
MyF4EkvOZNVKKJKqJv2pV8a2PBKWsyxfK4lTlMya
ignoreRevsFileは任意のファイル名を指定することが可能ですが、GitHubは.git-blame-ignore-revs
のファイル名で作成するとWeb UIのblameでIgnoreしてくれるため、特別な理由がない限りこのファイル名がおすすめです。
GitLabも同じファイル名で対応するかどうかが議論されています。
blame.markIgnoredLines
を設定してIgnoreされた箇所に?マークをつける
--ignore-rev
またはblame.ignoreRevsFile
指定時にblame.markIgnoredLines true
を設定するとIgnoreされた場合に?マークをつけてお知らせしてくれます。(後述)
git config --global blame.markIgnoredLines true
やってみる
実際に動かして動作を確認してみます。
下準備
$ mkdir hoge && cd hoge
$ cat << EOF > fuga
foo
bar
bazz
EOF
$ cat fuga
foo
bar
bazz
$ git init
コミット作成
# コミット1回目
$ git add fuga
$ git commit --author 'Zenn<zenn@example.com>' -m 'Initial commit'
[main (root-commit) 552350b] Initial commit
Author: Zenn <zenn@example.com>
1 file changed, 3 insertions(+)
create mode 100644 fuga
$ git blame fuga
^552350b (Zenn 2023-02-09 19:34:44 +0900 1) foo
^552350b (Zenn 2023-02-09 19:34:44 +0900 2) bar
^552350b (Zenn 2023-02-09 19:34:44 +0900 3) bazz
# コミット2回目
# barの前にスペースを2個追加
$ gsed -i 's/bar/ bar/g' fuga
$ git add fuga
$ git commit --author 'Zenn2<zenn2@example.com>' -m 'Second commit'
[main 5306907] Second commit
Author: Zenn2 <zenn2@example.com>
1 file changed, 1 insertion(+), 1 deletion(-)
$ git blame fuga
^552350b (Zenn 2023-02-09 19:34:44 +0900 1) foo
53069075 (Zenn2 2023-02-09 19:54:10 +0900 2) bar
^552350b (Zenn 2023-02-09 19:34:44 +0900 3) bazz
# コミット3回目
$ gsed -i 's/bazz/changed/g' fuga
$ git add fuga
$ git commit --author 'Zenn3<zenn3@example.com>' -m 'Third commit'
[main e85f232] Third commit
Author: Zenn3 <zenn3@example.com>
1 file changed, 1 insertion(+), 1 deletion(-)
$ git blame fuga
^552350b (Zenn 2023-02-09 19:34:44 +0900 1) foo
53069075 (Zenn2 2023-02-09 19:54:10 +0900 2) bar
e85f2322 (Zenn3 2023-02-09 19:55:36 +0900 3) changed
git blame --ignore-rev
2回目のコミットをIgnoreします
$ git rev-parse HEAD^1
530690759d090e1af427abfc444a15fe817ca80a
$ git blame --ignore-rev 530690759d090e1af427abfc444a15fe817ca80a fuga
^552350b (Zenn 2023-02-09 19:34:44 +0900 1) foo
^552350b (Zenn 2023-02-09 19:34:44 +0900 2) bar
e85f2322 (Zenn3 2023-02-09 19:55:36 +0900 3) changed
2行目の bar
はコード差分がありますが1回目のコミットのZennがコミットとして表示されています。
blame.ignoreRevsFile
$ cat << EOF > .git-blame-ignore-revs
530690759d090e1af427abfc444a15fe817ca80a
EOF
# --globalオプションをつけていないのでこのリポジトリのみ有効な設定
$ git config blame.ignoreRevsFile .git-blame-ignore-revs
$ git blame fuga
^552350b (Zenn 2023-02-09 19:34:44 +0900 1) foo
^552350b (Zenn 2023-02-09 19:34:44 +0900 2) bar
e85f2322 (Zenn3 2023-02-09 19:55:36 +0900 3) changed
blame.markIgnoredLines true
git config blame.markIgnoredLines true
/Users/takanobuhoshino/Downloads/hoge% git blame fuga
^552350b (Zenn 2023-02-09 19:34:44 +0900 1) foo
^?552350 (Zenn 2023-02-09 19:34:44 +0900 2) bar
e85f2322 (Zenn3 2023-02-09 19:55:36 +0900 3) changed
2行目のコミットハッシュに?
が挿入されていることがわかります。
(^
はboundary commitでこの場合は初回のコミットを指すマーク)
blame.markUnblamableLines true
について
--ignore-rev
のオプションにはblame.markUnblamableLines
もありますが、どのような機能か説明から理解できなかったので公式ドキュメントの説明を添えるにとどめます。
Mark lines that were changed by an ignored revision that we could not attribute to another commit with a * in the output of git-blame[1].
GitLens利用時の注意点
便利な--ignore-rev
ですが人気のVSCode拡張機能であるGitLens利用時に問題がありました。
blame.ignoreRevsFile
を設定している場合に、指定したファイルが存在しない場合はGitLensのblameが正常に機能しませんでした。
Issueが上がっていますが解決はしていないためGitLensユーザーの方は設定に気をつけましょう。
まとめ
--ignore-rev
オプションを使うことでgit blame
から特定のコミットを除外することができました。
はじめににも書いたように、特にLinterやFormatterをリポジトリに全体に適用したケースに有効なオプションです。
blameに支障が出るから実行に躊躇しているような方はぜひ設定してみてください。
参考資料
Discussion