RIT Tech Blog

株式会社RITのエンジニアが知見を共有する技術ブログです。

Gitでディレクトリの大文字小文字の変更が認識されない

こんにちは、RITエンジニアの三浦です。

Gitでディレクトリの大文字小文字の変更を反映するのに苦戦したので、解決方法を記します。

原因

Macファイルシステムディレクトリの大文字小文字をデフォルトで区別しておらず、Gitの大文字小文字変更検知がこれに依存しているのが原因みたいです。 masyus.work

解決策

下流れでディレクトリの大文字小文字変更をnew fileではなく、renameとしてGitに認識させる必要があります。

  1. gitconfigでファイルの大文字小文字を区別するように設定を変更する
  2. 差分がrenameとなっていることを確認する
  3. commitする

具体的に見ていきます。

配下に2つのファイルを持つ小文字sampleディレクトリを大文字Sampleディレクトリに変更します。

sampleディレクトリ内に2つのファイルを作成してcommitしました。 この時点では、Gitにはファイルが正しく認識されています。

$ git ls-files
sample/test1.tsx
sample/test2.tsx

Gitはデフォルトの大文字小文字を区別していない状態です。

$ git config core.ignorecase
true

このとき、ディレクトリsampleをSampleに変更しても差分が認識されません。

$ mv sample/ Sample/
$ git status
On branch master
nothing to commit, working tree clean

理由は、Gitがデフォルトで大文字小文字を検知しない設定になっているためです。

$ git config core.ignorecase
true

Gitが大文字小文字を検知するよう変更します。

$ git config core.ignorecase false
$ git config core.ignorecase
false

差分(Sample/)が検知されるようになりました。

$ git status 
On branch master
Untracked files:
  (use "git add <file>..." to include in what will be committed)
        Sample/

これをインデックスに追加します。 しかしこれでは、ディレクトリを大文字に変更しただけなのに、ファイルの新規作成としてGitに認識されてしまっています。

$ git add .

$ git status
On branch master
Changes to be committed:
  (use "git restore --staged <file>..." to unstage)
        new file:   Sample/test1.tsx
        new file:   Sample/test2.tsx
nothing added to commit but untracked files present (use "git add" to track)

インデックスされているファイルを見てみます。

$ git ls-files
Sample/test1.tsx
Sample/test2.tsx
sample/test1.tsx
sample/test2.tsx

このままcommitすると同じファイルが2つずつできてしまうのがわかります。

方法①:renameで認識させたところだけをcommitする

git rm コマンドでインデックス上から不要なファイルを削除します。

$ git rm sample/test1.tsx
rm 'sample/test1.tsx'

$ git rm sample/test2.tsx
rm 'sample/test2.tsx'

インデックス上から削除されたことを確認します。

$ git ls-files           
Sample/test1.tsx
Sample/test2.tsx

このとき、git statusで初めてフォルダの変更がnew fileではなくrenameとして認識されます。

$ git status
On branch master
Changes to be committed:
  (use "git restore --staged <file>..." to unstage)
        renamed:    sample/test1.tsx -> Sample/test1.tsx
        renamed:    sample/test2.tsx -> Sample/test2.tsx

Changes not staged for commit:
  (use "git add/rm <file>..." to update what will be committed)
  (use "git restore <file>..." to discard changes in working directory)
        deleted:    Sample/test1.tsx
        deleted:    Sample/test2.tsx

最後にワーキングツリーの変更(deletedの2ファイル)はリセットしておきます。

$ git checkout .
Updated 2 paths from the index

これをcommitすることで、Github上で正しくディレクトリ名がリネームされていることが確認できました!

方法②:一度全く別のディレクトリ名に変更する

ディレクトリ名を一旦別の名前(_sample)に変更します。

$ mv sample/ _sample/
$ git add .
$ git ls-files
_sample/test1.tsx
_sample/test2.tsx
$ git status
On branch master
Changes to be committed:
  (use "git restore --staged <file>..." to unstage)
        renamed:    sample/test1.tsx -> _sample/test1.tsx
        renamed:    sample/test2.tsx -> _sample/test2.tsx

別の名前(_sample)から本来変更したかった名前(Sample)に変更します。

$ mv _sample/ Sample/
$ git add .
$ git ls-files
Sample/test1.tsx
Sample/test2.tsx
$ git status
On branch master
Changes to be committed:
  (use "git restore --staged <file>..." to unstage)
        renamed:    sample/test1.tsx -> Sample/test1.tsx
        renamed:    sample/test2.tsx -> Sample/test2.tsx

これをcommitすれば完了です!

まとめ

今後、ディレクトリの大文字小文字を変更するときは、git ls-filesでGitのインデックス上で正しくrenameとして認識されているかどうか常に確認するよう気をつけます。

また、チームで作業している場合に、別の人がこの変更をpullしたときも同様に大文字小文字が正しく変更されないので、事前に前述の手順でインデックス内のディレクトリの大文字小文字を変更しておく必要があります。

同じような事象で詰まっている方の助けになれば幸いです。