git pre-commit フックを使って大きなファイルやコミットを探す
プラットフォームについて: Cloud、Server、および Data Center - この記事はすべてのプラットフォームに等しく適用されます。
サーバー*製品のサポートは 2024 年 2 月 15 日に終了しました。サーバー製品を利用している場合は、アトラシアンのサーバー製品のサポート終了のお知らせページにて移行オプションをご確認ください。
*Fisheye および Crucible は除く
要約
開発者が大きなコミットを作成していないこと、または、大きなファイルをコミットに入れていないことを確認する必要がある場合があります。git pre-receive フックで、これを実現できます。
本記事で説明している手順は、現時点でのものとなります。そのため、一部のお客様で特定の状況下で動作したという報告がありますが、正式にサポートされているわけではなく、お客様の特定のシナリオで動作することを保証するものではありません。
本番環境での実施の前に一通り非本番環境で検証し、成功しなかった場合にはサポートされている代替案にフォール バックしてください。
環境
ファイルやコミットがデフォルトの制限を超えているかどうかを確認する必要があるすべての git デプロイメント。このリポジトリを使用しているすべてのユーザーにこのフックを使わせたい場合は、フックの配布方法の詳細については「Standardize git hooks across a repository」を参照してください。
ソリューション
この pre commit フックは、個々のファイルやコミットが、limits 変数、commitlimit、filelimit で設定されているサイズを超えないようにします。commitlimit は、ステージングされたすべてのファイルのサイズを設定し、まとめて追加されます。filelimit は、各ファイルのサイズ制限をチェックします。これは、コミットまたはファイルのサイズの制限を妥当な値に設定することによって設定されます。デフォルトでは 10 で、これだとこのスクリプトは使用できません。
#!/bin/sh
commitlimit=$(git config hooks.filesizehardlimit)
filelimit=$(git config hooks.filesizehardlimit)
: ${commitlimit:=10}
: ${filelimit:=10}
list_new_or_modified_files()
{
# Only get the file name. Do not get deleted files.
git diff --staged --name-only --diff-filter=ACMRTUXB
}
unmunge()
{
local result="${1#\"}"
result="${result%\"}"
env echo "$result"
}
check_file_size()
{
n=0
while read -r munged_filename
do
f="$(unmunge "$munged_filename")"
h=$(git ls-files -s "$f"|cut -d' ' -f 2)
s=$(git cat-file -s "$h")
if [[ "$s" -gt $filelimit ]]
then
env echo 1>&2 "ERROR: size limit ($filelimit) exceeded: $munged_filename ($s)"
n=$((n+1))
fi
fs=$(($fs+$s))
done
if [[ "$fs" -gt $limit ]]
then
env echo 1>&2 "ERROR: hard size limit ($commitlimit) bytes exceeded: $munged_filename ($fs)"
fi
[ $n -eq 0 ]
}
list_new_or_modified_files | check_file_size
exit $n
サブモジュールを使用している場合、既知の問題があります。以下のエラーが確認できます。これは、スクリプトの git diff にサブモジュールからのハッシュを含めることができるためです。このエラーは無視できます。
fatal: git cat-file: could not get object info
コミットに失敗した場合に想定される出力は次のとおりです。
$ git commit -m "Another attempt at commit large file"
ERROR: size limit (10) exceeded: .githooks/pre-commit (746)
ERROR: size limit (10) exceeded: bitbucket-pipelines.yml (3278)
ERROR: hard size limit (10) bytes exceeded: (4024)
$