Gitで権限変更を無視する完全ガイド!core.fileModeの設定方法

git

「何も変更してないのに、git statusで大量のファイルが変更されてる!」
「git diffを見たら、パーミッションだけが変わってる…」

こんな経験、ありませんか?特にWindowsとLinuxを行き来したり、WSL(Windows Subsystem for Linux)を使っている人にとっては、よくあるトラブルなんです。

実は、Gitにはファイルの実行権限の変更を「差分」として検出する機能があります。でも、開発環境によってはこの機能が邪魔になることも。この記事では、Gitで権限変更を無視する方法を分かりやすく解説します。

「本当は内容を変えてないのに、権限だけで差分扱いされる」という悩みを、コマンド1つで解決できますよ。


スポンサーリンク
  1. Gitが追跡する「権限」とは?
    1. Gitが記録する3つのモード
    2. 問題が起きる仕組み
  2. 権限変更を無視する必要があるケース
    1. ケース1:Windows + WSLの環境
    2. ケース2:複数のOSで開発
    3. ケース3:chmod -R 777をやってしまった
  3. core.fileModeで権限を無視する方法
    1. 基本コマンド:特定のリポジトリで無視
    2. コマンドの効果を確認
    3. グローバル設定:すべてのリポジトリで無視
  4. 設定内容を確認する方法
    1. 現在のリポジトリの設定を確認
    2. すべての設定を一覧表示
    3. 設定ファイルを直接確認
  5. 実際の作業例:設定前と設定後の比較
    1. 設定前の状態
    2. 設定後の状態
  6. サブモジュールがある場合の設定
    1. 各サブモジュールで設定
    2. 一括設定スクリプト
  7. 注意点とデメリット
    1. デメリット1:実行権限の管理ができなくなる
    2. デメリット2:本番環境との不整合
    3. デメリット3:チーム開発での混乱
  8. 推奨される使い方
    1. 推奨1:プロジェクト単位で設定
    2. 推奨2:READMEに記載
    3. 推奨3:実行権限が必要なファイルは明示的に設定
  9. よくあるトラブルと解決方法
    1. トラブル1:設定したのに差分が消えない
    2. トラブル2:Windowsでchmodが効かない
    3. トラブル3:pullできない(権限の衝突)
  10. 設定を元に戻す方法
    1. ローカル設定を元に戻す
    2. グローバル設定を元に戻す
    3. 設定を完全に削除
  11. 代替手段:.gitattributesを使う
    1. .gitattributesファイルで制御
  12. まとめ

Gitが追跡する「権限」とは?

まず、Gitがどんな権限を追跡しているのか理解しておきましょう。

Gitが記録する3つのモード

Gitは実は、3種類のファイルモードだけを記録しています:

100644(通常ファイル)

  • 所有者:読み書き可能
  • 他のユーザー:読み取り専用
  • 実行権限なし

100755(実行可能ファイル)

  • 所有者:読み書き・実行が可能
  • 他のユーザー:読み取り・実行が可能
  • シェルスクリプトなどに使用

120000(シンボリックリンク)

  • ファイルへのリンク(ショートカットのようなもの)

つまり、Gitは「実行できるかどうか」だけを気にしているんですね。所有者やグループなどの細かい情報は記録されません。

問題が起きる仕組み

LinuxやMacでは、ファイルシステムが権限情報を持っています。でも、Windowsは違うんです。

例えば:

  • Linuxで作った644のファイルをGitにコミット
  • Windowsでクローンすると、全ファイルが755扱いになってしまう
  • 「権限が変わった!」とGitが検出してしまう

こうして、何も編集していないのに大量の差分が発生するわけです。


権限変更を無視する必要があるケース

実際にどんな場面で権限の無視が必要になるのか、具体例を見てみましょう。

ケース1:Windows + WSLの環境

Windows上にあるファイルをWSL(Ubuntu等)から操作すると、パーミッションが自動的に変わってしまいます。

# WSLから確認すると...
$ git status
modified:   .gitignore
modified:   README.md
modified:   script.sh
(実際には何も変更していない)

$ git diff
old mode 100644
new mode 100755

すべてのファイルで権限が変わっているように見えますが、実際は内容は同じなんです。

ケース2:複数のOSで開発

チームメンバーがWindowsとMacとLinuxをそれぞれ使っている場合、権限の差分でコンフリクト(衝突)が発生することがあります。

$ git pull
error: Your local changes to the following files would be overwritten by merge:
    README.md
    config.json
Aborting.

内容は変わっていないのに、権限だけが違うためにマージできない状態になるんですね。

ケース3:chmod -R 777をやってしまった

「動かないから、とりあえず全部に実行権限つけちゃえ!」というのは危険です。でも、一度やってしまうと…

$ git status
modified:   file1.txt
modified:   file2.txt
modified:   file3.txt
...(数百ファイル)

画像ファイルやテキストファイルまで実行可能になってしまい、すべてが差分として検出されます。


core.fileModeで権限を無視する方法

それでは、実際に権限変更を無視する設定をしていきましょう。

基本コマンド:特定のリポジトリで無視

まず、今作業しているリポジトリだけで権限を無視する場合はこちら:

git config core.fileMode false

たったこれだけです!

コマンドの効果を確認

設定が反映されたか確認してみましょう:

# 設定を確認
$ git config core.fileMode
false

# 差分を確認
$ git status
On branch main
Your branch is up to date with 'origin/main'.

nothing to commit, working tree clean

さっきまで大量にあった差分が消えましたね。

グローバル設定:すべてのリポジトリで無視

「今後作る全てのリポジトリで権限を無視したい」という場合は、--globalオプションを付けます:

git config --global core.fileMode false

これで、今後クローンしたり作成したりするすべてのリポジトリに適用されます。

注意:
既存のリポジトリには自動で適用されません。既存のリポジトリで使いたい場合は、それぞれのリポジトリで個別に設定する必要があります。


設定内容を確認する方法

「ちゃんと設定できたかな?」という時は、以下のコマンドで確認できます。

現在のリポジトリの設定を確認

git config core.fileMode

出力がfalseなら、権限を無視する設定になっています。

すべての設定を一覧表示

git config --list | grep filemode

これで、ローカル設定とグローバル設定の両方を確認できますよ。

core.filemode=false

設定ファイルを直接確認

設定は、実際には以下のファイルに保存されています:

リポジトリごとの設定

.git/config

グローバル設定

~/.gitconfig(Linux/Mac)
C:\Users\ユーザー名\.gitconfig(Windows)

テキストエディタで開くと、こんな感じで記載されています:

[core]
    filemode = false

実際の作業例:設定前と設定後の比較

実際にどのように動作が変わるのか、具体例で見てみましょう。

設定前の状態

# ファイルの権限を変更
$ chmod 755 script.sh

# Gitで確認すると...
$ git status
On branch main
Changes not staged for commit:
  modified:   script.sh

$ git diff
diff --git a/script.sh b/script.sh
old mode 100644
new mode 100755

権限変更が「差分」として検出されています。

設定後の状態

# 権限無視の設定を有効化
$ git config core.fileMode false

# 同じように権限を変更
$ chmod 755 script.sh

# Gitで確認すると...
$ git status
On branch main
nothing to commit, working tree clean

$ git diff
(何も表示されない)

権限変更が無視され、差分として認識されなくなりました!


サブモジュールがある場合の設定

プロジェクトにGitサブモジュールが含まれている場合は、それぞれのサブモジュールにも個別に設定が必要です。

各サブモジュールで設定

# メインリポジトリで設定
git config core.fileMode false

# サブモジュール1で設定
cd submodules/module1
git config core.fileMode false
cd ../..

# サブモジュール2で設定
cd submodules/module2
git config core.fileMode false
cd ../..

面倒ですが、サブモジュールごとに.git/configが独立しているため、個別設定が必要なんです。

一括設定スクリプト

複数のサブモジュールがある場合は、シェルスクリプトで一括設定すると便利です:

#!/bin/bash
# すべてのサブモジュールでfileMode=falseに設定

git config core.fileMode false

for dir in submodules/*; do
    if [ -d "$dir/.git" ]; then
        cd "$dir"
        git config core.fileMode false
        cd ../..
        echo "設定完了: $dir"
    fi
done

注意点とデメリット

便利な機能ですが、使用にあたってはいくつか注意点があります。

デメリット1:実行権限の管理ができなくなる

core.fileMode=falseにすると、意図的な実行権限の変更も追跡されなくなります。

例えば:

  • シェルスクリプトに実行権限を付けたい
  • セキュリティ上、実行権限を外したい

こういった正当な権限変更も、Gitが無視してしまうんです。

デメリット2:本番環境との不整合

開発環境でfileMode=falseにしていると、本番環境にデプロイした時に問題が起きることがあります。

# 開発環境では実行できたのに...
$ ./deploy.sh
bash: ./deploy.sh: Permission denied

本番環境では権限がないため実行できない、というトラブルが発生する可能性があります。

デメリット3:チーム開発での混乱

チームメンバーによって設定が違うと、混乱を招きます。

  • Aさん:fileMode=true(デフォルト)
  • Bさん:fileMode=false

この状態だと、Bさんの環境では問題なくても、Aさんの環境では権限の差分が大量に出てしまいます。


推奨される使い方

それでは、どのように使うのがベストなのでしょうか?

推奨1:プロジェクト単位で設定

グローバル設定ではなく、プロジェクトごとに判断して設定しましょう。

# グローバルではなく、ローカルで設定
git config core.fileMode false

こうすることで、本当に必要なプロジェクトだけで無視できます。

推奨2:READMEに記載

チームで開発している場合は、プロジェクトのREADME.mdに設定方法を書いておきましょう。

## 開発環境のセットアップ

このプロジェクトでは、OSによる権限の差異を防ぐため、
以下のコマンドを実行してください:

\`\`\`bash
git config core.fileMode false
\`\`\`

これで、新しいメンバーが参加した時もスムーズです。

推奨3:実行権限が必要なファイルは明示的に設定

fileMode=falseにしても、実行権限が必要なファイルはgit update-indexで明示的に設定できます:

# 特定のファイルだけ実行権限を設定
git update-index --chmod=+x deploy.sh

# コミット
git commit -m "Add execute permission to deploy.sh"

これなら、必要な権限だけをGitで管理できますね。


よくあるトラブルと解決方法

実際に遭遇しやすいトラブルとその解決策をまとめました。

トラブル1:設定したのに差分が消えない

症状:

$ git config core.fileMode false
$ git status
modified:   script.sh
(まだ差分が出る)

原因:
既にステージングエリア(インデックス)に変更が追加されている状態です。

解決方法:

# ステージングエリアをリセット
git reset HEAD

# または、変更を破棄
git checkout -- .

トラブル2:Windowsでchmodが効かない

症状:

$ chmod 644 file.txt
$ ls -l file.txt
-rwxrwxrwx 1 user user 0 Dec 11 10:00 file.txt
(権限が変わらない)

原因:
WindowsのファイルシステムはLinuxのような詳細な権限を持っていません。

解決方法:
これは正常な動作です。core.fileMode=falseに設定することで、この違いを気にせずに済むようになります。

トラブル3:pullできない(権限の衝突)

症状:

$ git pull
error: Your local changes would be overwritten by merge.

原因:
リモートとローカルで権限が違うため、マージできない状態です。

解決方法:

# 一時的に変更を退避
git stash

# pullする
git pull

# core.fileModeを設定
git config core.fileMode false

# 退避した変更を戻す(これで権限の差異は無視される)
git stash pop

設定を元に戻す方法

「やっぱり権限も追跡したい」という場合は、設定を元に戻せます。

ローカル設定を元に戻す

git config core.fileMode true

グローバル設定を元に戻す

git config --global core.fileMode true

設定を完全に削除

# ローカル設定を削除
git config --unset core.fileMode

# グローバル設定を削除
git config --global --unset core.fileMode

設定を削除すると、Gitのデフォルト動作(権限を追跡する)に戻ります。


代替手段:.gitattributesを使う

core.fileMode以外にも、権限を制御する方法があります。

.gitattributesファイルで制御

プロジェクトのルートに.gitattributesファイルを作成して、ファイルごとに細かく制御できます:

# すべての.shファイルに実行権限を保証
*.sh text eol=lf

# 特定のファイルだけ追跡
deploy.sh binary

この方法なら、チームメンバー全員で同じ設定を共有できますよ。


まとめ

Gitで権限変更を無視する方法、しっかり理解できましたか?最後に重要なポイントをおさらいしましょう。

権限を無視する基本コマンド:

# 現在のリポジトリで無視
git config core.fileMode false

# すべてのリポジトリで無視(グローバル)
git config --global core.fileMode false

設定の確認:

git config core.fileMode

こんな時に使おう:

  • Windows + WSLで開発している
  • チームで複数のOSを使っている
  • 権限の差分が大量に出て困っている

注意点:

  • 実行権限の管理ができなくなる
  • 本番環境との不整合に注意
  • チームで設定を統一する

おすすめの使い方:

  • プロジェクト単位で設定
  • READMEに設定方法を記載
  • 必要なファイルはgit update-indexで個別設定

この設定を使えば、「何も変更してないのに差分が出る」というストレスから解放されますよ。ただし、セキュリティ上重要な権限管理が必要なプロジェクトでは、慎重に判断してくださいね。

それでは、快適なGitライフをお楽しみください!

コメント

タイトルとURLをコピーしました