• SIS Lab
  • >
  • Blog
  • >
  • Git pre-commitフックでFrontmatterの「更新日時」を自動更新する

Git pre-commitフックでFrontmatterの「更新日時」を自動更新する

更新日:2022.09.01 作成日:2021.02.11

今までブログ記事コンテンツの「更新日時」はgitの履歴情報を元にしていました。 たとえば、Hugoの場合はenableGitInfo = trueとすると、Gitの履歴情報からMarkdownの最終更新日時を自動で取得してlastmodとして割り当てられていました。

しかし、GitHub ActionsでHugoのビルドを行う際に、全履歴を取得するのをやめたことで、Markdownlastmodの項目を見るように変更しています。

今後はlastmodをメンテナンスする必要があるため、いちいち「更新日時」を手動更新するのではなく、gitpre-commitフックを利用して更新日時を自動更新する方法を調べました。

Git hooksとは

git hooksとは特定のアクションが発生した時に、カスタムスクリプトを実行する方法を指します。

git hooksは、クライアントサイドとサーバーサイドの2つに分類できます。

クライアントサイドのコミット時フック(コミットプロセスに関する)には主な4つがあります。

  • pre-commit
    • コミットメッセージが入力される前に実行
  • prepare-commit-msg
    • コミットメッセージエディターが起動する直前、デフォルトメッセージが生成された直後に実行
  • commit-msg
    • コミットメッセージを保存した一時ファイルへのパスをパラメータに取る
  • post-commit
    • コミットプロセスが全て完了した後に実行

今回はpre-commitフックを利用して、対象のMarkdownファイルをCommitした際に、更新日時を自動的に更新させます。

pre-commit shell script

次のShell Script.git/hooks/pre-commitとして作成して、chmod +xなどで実行権限を付与します。 あとは、git commitコマンドを実行した際には、自動的にlastmodが更新されるようになります。

 #!/bin/sh
 
 # Read YAML front matter in all the modified files for committing,
 # and replace "lastmod:" line to "lastmod: current date and time"
 
 git diff --cached --name-status | grep "^M" | while read a b; do
   cat $b | sed "/---.*/,/---.*/s/^lastmod:.*$/lastmod: $(TZ=Asia/Tokyo date "+%Y-%m-%dT%T")+09:00/" > tmp
   mv tmp $b
   git add $b
 done

Windowsの場合

ファイル先頭が#!/bin/shだとerror: cannot spawn .git/hooks/pre-commit: No such file or directoryというエラーが発生しました。 #!/bin/bashに変更することで動作することを確認しました。

#!/bin/bash 

git diff --cached --name-status | grep "^M" | while read a b; do
  cat $b | sed "/---.*/,/---.*/s/^lastmod:.*$/lastmod: $(TZ=Asia/Tokyo date "+%Y-%m-%dT%T")+09:00/" > tmp
  mv tmp $b
  git add $b
done

参考

まとめ

面倒でついつい更新をサボってしまうような処理は自動化するのがよいですね。 今回このスクリプトを用意したことで、今後は意識せずとも更新日時が更新されるようになります。

参考

Related contents