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エラーを一時的に解決した、現場からお送りしました。