macOSでgit commitがPermission deniedになる原因とワークアラウンドな解決策
macOS環境でgit commitを実行した際に、突然以下のようなエラーメッセージに遭遇したことはありませんか?
$ git commit
error: could not create temporary file: Permission denied
fatal: failed to write commit objectこれは、Gitがコミットオブジェクトを書き込むための一時ファイルを作成しようとした際に、権限の問題で失敗していることを示しています。
この記事では、このPermission deniedエラーを解消するためのトラブルシューティング手順を、安全なものから順にご紹介します。
まず、問題がGit本体で起きているのか、あるいはコミット前に実行されるスクリプト(Gitフック)が原因なのかを切り分けます。
以下のコマンドを実行して、Gitフックを一時的に無効化してコミットを試みてください。
git commit --no-verify -m "test commit to check hooks"もしこのコマンドでコミットが成功した場合、原因はGitフックにあります。
リポジトリの.git/hooks/ディレクトリ内にあるpre-commitなどのフックスクリプトを確認してください。スクリプト内で一時ファイルを生成する処理(例: Linterや整形ツールが一時ファイルを作成する)があり、その書き込み先ディレクトリ(/tmp、$TMPDIR、リポジトリ内のtmp/など)の権限が不適切になっている可能性が高いです。該当するスクリプトと、それが利用するツールの設定を見直しましょう。
--no-verifyでもエラーが解消しない場合、Gitが使用する一時ディレクトリ自体の問題が考えられます。
macOSは、セキュリティ上の理由からユーザーごとに固有の一時ディレクトリを/var/folders/配下に作成し、そのパスを環境変数$TMPDIRに設定します。このディレクトリの権限が何らかの理由でおかしくなったり、ディレクトリ自体が破損したりすると、Gitは一時ファイルを作成できずにエラーとなります。
まず、現在の$TMPDIRのパスを確認し、書き込みが可能かテストしてみましょう。
# $TMPDIR のパスを確認
echo $TMPDIR
# /var/folders/xx/yyyyyyyyzzzzzzzzzzzzzzzz/T/ のようなパスが表示される
# 書き込みテスト
touch "$TMPDIR/testfile"もしtouchコマンドの時点でPermission deniedエラーが出る場合、$TMPDIRが壊れている可能性が高いです。
env TMPDIR=/private/tmp応急処置として、より一般的な一時ディレクトリである/private/tmp(/tmpのシンボリックリンク先)をGitの操作時だけ明示的に指定することで、コミットを成功させることができます。
env TMPDIR=/private/tmp git commit -m "commit with a temporary fix"毎回envコマンドを打つのは手間なので、ワークアラウンドの恒久的な対策を設定しましょう。
お使いのシェルの設定ファイル(例: ~/.zshrc, ~/.bash_profile)に以下の行を追記します。これにより、ターミナルセッション全体で使われる一時ディレクトリが/private/tmpになります。
export TMPDIR=/private/tmp設定を反映させるために、ファイルを保存した後にsource ~/.zshrcを実行するか、ターミナルを再起動してください。
影響をGitコマンドだけに限定したい場合は、エイリアスを設定するのがおすすめです。同様に、シェルの設定ファイルに以下を追記します。
alias git='env TMPDIR=/private/tmp git'これにより、gitと入力した際に自動でenv TMPDIR=/private/tmpが付与されるようになります。
git commit時のPermission deniedエラーは焦りがちですが、上記の手順で切り分けていくことで、ほとんどの場合解決できます。まずはフックを疑い、次にmacOS特有の$TMPDIRの問題を確認してみてください。
以上、git commitのPermission deniedエラーを一時的に解決した、現場からお送りしました。