前回の記事では git commit をトリガーに Ansible でローカルの Hugo を自動更新する仕組みを構築した。今回はその続きで、git push のタイミングで本番サーバへの同期も自動化した話を紹介する。
やりたいこと #
これまでは本番反映を手動で実行していたが、git push に統合し、push するだけで本番まで反映されるようにしたかった。
git に post-push フックはない #
git には post-commit のように「push 後」に処理を実行する post-push フックが存在しない。
代わりに pre-push フックを使う。これは push が実行される直前に呼ばれるフックで、処理が失敗(exit 1)すると push 自体を中止できる。
本番同期に失敗したまま GitHub へ push されるのを防げるため、むしろ都合がいい。
実装 #
.githooks/pre-push に本番同期の処理を記述し、実行権限を付与してコミットする。
chmod +x .githooks/pre-push
git add .githooks/pre-push
git commit -m "add: pre-push hook for production sync"完成したフロー #
git commit(files/*.md を含む)
→ post-commit hook → Ansible → ローカルプレビュー確認
git push
→ pre-push hook → Hugo ビルド → rsync → 本番同期
→ GitHub へ pushコミットしてプレビューを確認し、問題なければ push するだけで本番まで反映される。
本番を以前の状態に戻す #
誤った内容を push してしまった場合は、git revert で取り消しコミットを作って再度 push する。pre-push hook が発火するため、自動的に本番にも反映される。
# 直前の push を取り消す
git revert HEAD
git push特定のコミットまで戻したい場合は履歴を確認して対象を指定する。
# 履歴を確認
git log --oneline
# 指定コミットを取り消す
git revert <コミットハッシュ>
git pushgit revert は履歴を書き換えずに「取り消しコミット」を積む方法のため、安全に使える。
特定ファイルだけ戻す #
git revert はコミット単位の操作のため、1ファイルだけ戻すには使えない。その場合は git checkout で過去のバージョンを取り出す。
# 対象ファイルの変更履歴を確認
git log --oneline files/記事名.md
# 指定コミット時点の内容に戻す
git checkout <コミットハッシュ> -- files/記事名.md
# コミットして push → pre-push hook が発火して本番に反映
git add files/記事名.md
git commit -m "revert: 記事名を以前の状態に戻す"
git push別 PC でクローンした場合 #
core.hooksPath の設定はローカルにしか保存されないため、クローン後に一度実行が必要だ。
git clone <リポジトリURL>
cd <リポジトリ名>
git config core.hooksPath .githooksまとめ #
| やること | タイミング |
|---|---|
| ローカル Hugo へ自動デプロイ | git commit(post-commit hook) |
| 本番サーバへ自動同期 | git push(pre-push hook) |