考えられる原因#1-行終了の正規化
これが発生する可能性のある状況の1つは、問題のファイルが行末の正しい構成なしでリポジトリにチェックインされた場合(1)、リポジトリ内のファイルの行末が正しくないか、行末が混在している場合です。確認するにgit diff
は、行末の変更のみが表示されることを確認します(これらはデフォルトでは表示されない場合があります。git diff | cat -v
キャリッジリターンをリテラル^M
文字として表示してみてください)。
その後、誰かが行末を正規化するために設定を追加.gitattributes
または変更した可能性があります(2)。core.autocrlf
またはグローバル構成に基づいて.gitattributes
、Gitは、要求された行終了正規化を適用するローカル変更を作業コピーに適用しました。残念ながら、何らかの理由でgit reset --hard
これらの行の正規化の変更を元に戻すことはできません。
解決
ローカル行末がリセットされる回避策では、問題は解決しません。ファイルがgitによって「表示」されるたびに、正規化が再適用され、同じ問題が発生します。
最良のオプションは、リポジトリ内のすべての行末を正規化して、.gitattributes
それらの変更をコミットすることにより、gitに正規化を適用させることです。「 gitfilter-branchで行末を修正しようとしていますが、運がない」を参照してください。
本当にファイルへの変更を手動で元に戻したい場合、最も簡単な解決策は、変更されたファイルを消去してから、それらを復元するようにgitに指示することですが、この解決策は一貫して100%機能しないようです。時間(警告:変更したファイルに行末以外の変更がある場合は、これを実行しないでください!!):
git status --porcelain | grep "^ M" | cut -c4- | xargs rm
git checkout -- .
ある時点でリポジトリ内の行末を正規化しない限り、この問題が発生し続けることに注意してください。
考えられる原因#2-大文字と小文字の区別
2番目に考えられる原因は、WindowsまたはMac OS/Xでの大文字と小文字の区別です。たとえば、次のようなパスがリポジトリに存在するとします。
/foo/bar
これで、Linux上の誰かがファイルをコミットし/foo/Bar
(おそらくビルドツールまたはそのディレクトリを作成したものが原因で)、プッシュします。Linuxでは、これは実際には2つの別々のディレクトリになっています。
/foo/bar/fileA
/foo/Bar/fileA
WindowsまたはMacでこのリポジトリをチェックアウトするfileA
と、リセットできない変更が発生する可能性があります。これは、リセットするたびに、Windowsのgitがチェックアウトし/foo/bar/fileA
、Windowsでは大文字と小文字が区別されないため、の内容が上書きfileA
さ/foo/Bar/fileA
れ、「変更」されるためです。
別のケースは、リポジトリに存在する個々のファイルである可能性があり、大文字と小文字を区別しないファイルシステムでチェックアウトすると重複します。例えば:
/foo/bar/fileA
/foo/bar/filea
そのような問題を引き起こす可能性のある他の同様の状況があるかもしれません。
大文字と小文字を区別しないファイルシステムのgitは、実際にこの状況を検出し、有用な警告メッセージを表示する必要がありますが、現在は表示されません(これは将来変更される可能性があります。この説明と、git.gitメーリングリストの関連する提案されたパッチを参照してください)。
解決
解決策は、gitインデックス内のファイルのケースとWindowsファイルシステム上のケースを揃えることです。これは、実際の状態を表示するLinuxで実行することも、非常に便利なオープンソースユーティリティGit-Uniteを使用するWindowsで実行することもできます。Git-Uniteは必要なケースの変更をgitインデックスに適用し、それをリポジトリにコミットできます。
.gitattributes
(1)これは、問題のファイルの定義がなく、Windowsを使用していて、デフォルトのグローバル設定を使用している人が原因である可能性がcore.autocrlf
ありますfalse
((2)を参照)。
(2)http://adaptivepatchwork.com/2012/03/01/mind-the-end-of-your-line/