webネタ

Webエンジニアが業務に関係することをメモしていく

gitの便利なfilterまとめ

gitのfilterは、checkout時 と add時 に任意のフィルターをかけることができる。

  • svnでやってた $Id$ みたいな変数の展開したり
  • コードを自動で整形したり
  • 任意のコマンド/スクリプトを実行できる

概念図

出元

$Gcid$にコミットIDを埋め込むフィルターを作ってみる

やりたいこと

git checkout時に指定ファイルの、

echo "$Gcid$"echo "$Gcid: bcc4bbe68b26a65a1597752a$"に展開。

git add時は逆に、

echo "$Gcid: bcc4bbe68b26a65a1597752a$"echo "$Gcid$"に戻す。

手順

  1. gitの設定でfilterを定義 (.git/config)
  2. フィルターの対象を定義 (.gitattributes)
  3. フィルター時に実行するスクリプトを用意 (embed-commit-id.rb)
  4. フィルターされるファイルを用意 (fuga.sh)
  5. 試す
.
├─ .git/config (~/.gitconfigでも/etc/gitconfigでも)
├─ .gitattributes
├─ embed-commit-id.rb
└─ fuga.sh

1. gitの設定でフィルターを定義 (.git/config)

フィルターの設定をする。

$ vi .gitconfig

[filter "embed-commit-id"]
  smudge = ruby embed-commit-id.rb
  clean = perl -pe \"s/\\\\\\$Gcid[^\\\\\\$]*\\\\\\$/\\\\\\$Gcid\\\\\\$/\"

2. フィルターの対象を定義 (.gitattributes)

フィルターをかけるファイルを指定する。

$ vi .gitattributes

fuga.sh filter=embed-commit-id

3. フィルター時に実行するスクリプトを用意 (embed-commit-id.rb)

smudgeフィルターで実行するスクリプト

$ vi embed-commit-id.rb

#! /usr/bin/env ruby

puts STDIN.read.gsub('$Gcid$', '$Gcid: ' + `git rev-parse HEAD`.strip + '$')

4. フィルターされるファイルを用意 (fuga.sh)

フィルターされるファイルに、変数を埋め込む。

$ vi fuga.sh

echo "$Gcid$"

ここで一旦全部コミットしておく

5. 試し

変数は未展開

$ cat fuga.sh
echo "$Gcid$"

checkoutする

$ rm fuga.sh
$ git checkout fuga.sh

チェックアウトを経由するとフィルターにより展開される

$ cat fuga.sh
echo "$Gcid: 3c6c5646726ba5948a9c0198f856bdce0be330de$"

変更してaddしてみる

$ echo "fuga" >> fuga.sh
$ git add fuga.sh

addするとフィルターにより変数が元に戻り差分が出ない

$ git diff --cached
 echo "$Gcid$"
+fuga

(もちちんcheckoutじゃなくてcloneでも同様の効果が得られる)

まとめ

スタイルチェック通らないとaddできないようにするとか、

任意のスクリプトをcheckout/add時に動かせるので色んなことが出来そう。