【Git】変更していないのに勝手に変更されるファイルがある時の対処法

同じプロジェクトを使用OSがバラバラの複数のメンバーで共同開発した際などの

  • $ git pullしたら変更していないファイルに勝手にdiffが出てしまう
  • 修正しても保存するとdiffのある状態に戻ってしまう
  • importやソースコードの並び順が勝手に変わったり
  • 閉じタグのインデントが勝手に変わっているなど
  • checkout、reset、stashも効かない

問題の解決手段です。

そのdiff、どこから

もし以前までdiffが出ていなく、最近生じた問題だった場合は直近の(特に別OS使用者の)コミット履歴から同ファイルの変更がないか探します。

もしかすると既にremoteに上がっている変更がlocalでは差分として出てしまっているかもしれません。

原因として考えられるもの

改行コードの設定がバラバラかもしれません。

改行コードの推奨はLFです。

CRLFに統一する場合は後述する自動改行コード変換設定を事前にオフにするようアナウンスが必要かと思います。(どちらにせよ共通認識は必要ですが・・・)

ここでGitの自動改行コード変換設定の種類を見てみます。

自動改行の設定を見直す

確認

$ git config --global core.autocrlf

設定の種類は3つ。

core.autocrlf true input false
checkout時 CRLFへ変換 元のまま 元のまま
commit時 LFへ変換 LFへ変換 元のまま

メンバーの環境によっていずれかに統一するのが良いと思います。

(なおdiffが出るファイルをエディタで開いて改行コード設定がLFになっていてもそれには意味がないです)

「とにかくfalseに!」という記事が多いですが、実際にもう開発を始めてしまった・表題の現象が出てしまった場合は別の方法が良いかと。(新規ファイル作成時やエディタ側でもにょもにょしていた場合などに面倒)

個人的には「input」

git config --global core.autocrlf input

で全環境統一が分かりやすく安心だと考えます。

ちなみにGitHubのおすすめはConfiguring Git to handle line endings | GitHub Docs(opens new window)

これだとWindowsの推奨は「true」ですが、勝手にCRLFにされると困るものもありますよね・・・「input」もしくは「false」を推奨します。

(LF対応していないエディタ使用者はもうそんなにいないだろうと)

目の前の差分をなんとかする

設定しただけでは差分は消えないので、git cloneし直しが基本ですが、

diffを修正する作業で何とかなるかもしれません。

とはいえ既にGit登録されているファイルは修正を受け付けてくれないので、

  1. 差分修正をしたファイル(LF)をGit管轄外の場所で別途新規作成&保存
  2. diffの出ているファイルを削除
  3. 1で作成したファイルを格納

をします。

それで解決しなければcloneし直しで。

巻き戻りが無いよう、コミット履歴と照らし合わせて作業してね!

もっとやる

リポジトリごとのルールを記載する

GitHub Docsでは改行コードをどう扱うかを統一するため、.gitattributesに* text=autoを記載する例が紹介されています。

# Set the default behavior, in case people don't have core.autocrlf set.
* text=auto

# Explicitly declare text files you want to always be normalized and converted
# to native line endings on checkout.
*.c text
*.h text

# Declare files that will always have CRLF line endings on checkout.
*.sln text eol=crlf

# Denote all files that are truly binary and should not be modified.
*.png binary
*.jpg binary

* text=autoにすると変換を行うかどうかはGit任せになります。

この設定少し厄介で、

autocrlfが「false」の状態でこの.gitattributesを追加するとautocrlfの設定を無視してCRLFに変換されるそうです。ええ・・・

「input」なら問題なしです。

*.c text以降が例外の設定です。

safecrlfを設定する

確認

git config --global core.safecrlf

設定の種類は3つ。

core.safecrlf true warn false
改行コードが混在している場合、CRLF→LFに 変換しない 警告出つつ変換する 変換する
git add できない 警告は出るができる できる
末尾に改行がない状態でadd できない 警告は出るができる できる

「warn」もしくは「false」にしている場合、改行コードが混在しているファイルはLFに自動変換され、LFから元のCRLFと混在している状態には元に戻せません。

細心の注意を払うなら「true」に。

私は

git config --global core.safecrlf warn

にしています。

上記対応でもうまくいかない場合

filemodeの確認。ファイルパーミッションの変更まで感知しているかどうかの確認をします。

git config -l | grep filemode

ファイルパーミッションの変更を無視する場合は

git config core.filemode false

ですが、複数人で開発する場合は各人の設定を確認して統一した方が良いです。