0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【Git】Config-based hooks の pre-push で引数を無視する

0
Posted at

Git 2.54 で導入された Config-based hooks によって、sh スクリプトや husky なしに手軽に Git hooks を構築できます。
同じイベントに複数のフックを設定したり、従来のフックと併用することもできます。

pre-commit は引数がないけど、pre-push は引数を渡されるので、無視する方法を考えました。

pre-push

pre-push イベントは git push を実行した際、リモート参照が更新された後、オブジェクトの転送が始まる前に実行されます。
「リモート名」(例:origin)と「URL」(例:git@github.com:user-name/repository-name.git)を引数にとり、0以外の値を返すと push を中断します。
公式リファレンス

2つの引数

これは複数のリモート先がある場合に活用されるのかな・・?
.git/hooks/pre-push.sample を見てみると、引数は受け取る必要があるので一旦変数に格納してるけど、実質読み捨てているようです。
WIP(作業中)で始まるコミットメッセージがあると中断するサンプルでした)

remote="$1"
url="$2"

Config-based hooks

Config-based hooks では引数に関するオプションなどがなさそうなので、コマンドの末尾に「 #」を追記して読み捨ててみます。

config を更新するコマンド

% git config hook.runHook true
% git config hook.pre-push-test.event pre-push
% git config hook.pre-push-test.command "npm test #"

.git/config の中身を確認

[hook]
	runHook = true
[hook "pre-push-test"]
	event = pre-push
	command = "npm test #"

package.json の test スクリプトで何かしらテストを呼ぶ

"scripts": {
    "test": "node --test"
}

無事、フックからテストコマンドが実行されました( Windows と Mac で確認)

% git push

> test
> node --test

「 #」を入れないと・・

% git config hook.pre-push-test.command "npm test"

引数が node --test に渡されて、エラーになる

% git push

> test        ┌─────────────── 不要な引数が渡される ───────────────┐ 
> node --test origin git@github.com:user-name/repository-name.git

Could not find 'origin, git@github.com:user-name/repository-name.git'
error: failed to push some refs to 'github.com:user-name/repository-name.git'

同じイベントに複数のフックを設定した場合

config に記載された順に実行され、最後に sh スクリプトもあれば実行されます。
git hook list <イベント名> でフック一覧を実行順に確認できます。

% git hook list pre-push
pre-push-lint        # config ファイル内で先に書かれている方
pre-push-test        # config ファイル内で次に書かれている方
hook from hookdir    # 従来の sh スクリプトは最後になる

一時的に無効にする

enabled プロパティで無効化できます

% git config hook.pre-push-lint.enabled false

.git/config

[hook "pre-push-lint"]
	command = "npm run lint #"
	event = pre-push
	enabled = false

リストには disabled がつく

% git hook list pre-push                
disabled        pre-push-lint
pre-push-test
hook from hookdir

復活させる時は true にするか、

% git config hook.pre-push-lint.enabled true

項目自体を削除(デフォルト true )

% git config --unset-all hook.pre-push-test.enabled

(おまけ)中断理由をメッセージに出したい

フックによりイベントが中断された際、ターミナルや Git ログなどにメッセージが欲しいなと思って、npm スクリプトをこうしてみました。

"scripts": {
    "test": "node --test || (echo [error] Test failed. >&2 && exit 1)"
}

|| で、node --test が失敗の時( exit 0 以外の時)に後続のサブシェルを実行。※
>&2 で stderr にリダイレクト。( stdout だと Git ログに出なかったので)
exit 1 であらためてフックに「失敗」を返す。
{} グループだと Windows でシンタックスエラーになったのでサブシェルにしました

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?