今作業しているブランチで変更・追加を行ったファイルを列挙したい。
具体的には、 lint チェックの対象を作業中のファイルだけに絞って省力化したい、というイレギュラーじみたケースのためにやってみました。
master
と作業中ブランチとで差があるファイルを列挙
次のコマンドで master
と HEAD
(作業中ブランチ)とで差があるもののファイル名を列挙できます。
git -c core.quotepath=false diff master HEAD --name-only
-c core.quotepath=false
を付けているのは、取得したファイル名を他コマンドのパラメータにする目的があるのでこの時点でエスケープとかやってほしくなかったからです。
master
と HEAD
はベースにするブランチ・対象にするブランチで読み替えましょう。
ただし、このコマンドでは master
に対しての作業中ブランチのファイルだけでなく、作業中ブランチに対して差がある master
のファイルも出てきてしまいます。
master
ではなく master
から作業中ブランチを生やしたベースコミットから差があるファイルを列挙
GitHub の Pull Request みたいにベースコミットからその作業中ブランチで変更したファイルだけを列挙したいです。
なのでベースコミットを見つけてくればよい。
git -c core.quotepath=false diff `git show-branch --merge-base master HEAD` HEAD --name-only
さっきのコマンドの master
を git show-branch --merge-base master HEAD
に置き換えただけです。
読みづらいので、シェルスクリプトの中で使う場合は次のように一度変数に入れたほうがよいでしょう。
BASE_COMMIT=`git show-branch --merge-base origin/master HEAD`
git -c core.quotepath=false diff $BASE_COMMIT HEAD --name-only
列挙したファイル名を他コマンドのパラメータにする
こんな事し出した目的は、 Pull Request に含まれるファイルだけを対象に lint チェックかけたかったからでした。
そこで最終的に出来上がったのが次のようなシェルスクリプトです。
#!/bin/bash -eux
BASE_COMMIT=`git show-branch --merge-base origin/master HEAD`
files=()
while read file
do
files+=("${file}")
done < <( git -c core.quotepath=false diff $BASE_COMMIT HEAD --name-only | grep -E '\.md"?$' )
if [ ${#files[@]} -gt 0 ]; then
npm run lint "${files[@]}"
fi
本当はスクリプトの実行パスの正規化のために cd `dirname $0`
とか他にもやってるんですが割愛してます。
今回チェックしたいのは Markdown のドキュメントだったので grep -E '\.md"?$'
でファイルをさらに絞り込んでます。
ファイル名に空白が含まれたりして面倒くさかったんですが、参考記事などのおかげでエスケープとか深く考えずになんとかなりました。
そういうわけで、できあがったスクリプトを CI で動かしています。