Gitにはファイルのパーミッションを管理する機能がある…のはいいのですが、Windows上から扱っていると確認も設定も面倒なものです。自動化できるパターンのものは自動化したいものです。
背景事情
- Gitコミットから連動してサーバデプロイを行う環境を構築している
- この際に、
.some_hooks/以下に置いた、パーミッション755のスクリプトファイルを自動実行する - なお、
.some_hooks/に644のファイルを置いているとデプロイ時にエラーとなる
実際に、毎回パーミッションを正しく設定するのは面倒だし、忘れてデプロイエラーとなる事故をやらかしたことも何度かありました。
また、簡易的に作ったものなので、ファイル名にスペースや改行文字が入る、過激な環境での動作は想定していません。
Git Hooksとは
Gitには、Git Hooksといって、「特定の操作をしたときにスクリプトを実行する」機能があります。今回はコミットするタイミングで手を入れたいので、pre-commitが適当です。
なお、Git HooksはGitの管理フォルダのhooksサブフォルダの中に置きますが、Hooks自体はGit管理されないことには要注意です。
書いたコード
コードにすれば意外とシンプルでした。
# !/bin/bash
git diff --name-only --diff-filter=d --cached | grep '^\.some_hooks/' | xargs git update-index --add --chmod=+x
まず、最初のgit diff --cachedでステージングされた変更との差分を抽出します。--diff-filter=dは「削除された変更は除外」ということで、これを除外しないと削除したファイルのパーミッションを変えてステージングしようとしてしまい、エラーとなります。--name-onlyは文字通り、ファイル名だけ抽出するオプションです。これで、「ステージングされた、新規作成(の可能性がある)ファイル1の、改行区切りのリスト」を取れました。
次にこのリストをgrepに流して、「.some_hooks/で始まるもの」、すなわち「.some_hooks/以下にあるもの」だけを抽出します。
最後にこのリストをxargsで引数リストに変換して、Gitのパーミッション変更コマンドへ流し込めば、ミッションコンプリートです。
感想
細かいコマンドをつないで1つの動作を作る、Unix哲学の奥深さをまた1つ感じました。
外部リンク
-
Git list of staged files - StackOverflow(
git diff --name-only --cachedの情報元) - (よく忘れるので)gitのパーミッション操作の復習 - Qiita
-
中身を書き換えただけのファイルも取得されてしまいますが、ファイル移動など細かなパターンまで逐一指定するのが煩雑になるのと、そしてあとでパーミッション書き換えの操作を行っても特に問題ないので放置しています。 ↩