🌊

【Git】ファイル名の大文字小文字を変更する

2023/01/11に公開

概要

Gitは、デフォルトではファイル名の変更に関して、大文字⇔小文字の変更を検知しません。(ファイル名としては大文字と小文字は区別され、どちらも存在することが可能)

そのため、手元の環境でディレクトリ名を大文字から小文字に変更した場合、そのままだとリポジトリに変更が反映されません。

環境

$ git --version
git version 2.37.1 (Apple Git-137.1)

対処法

方法1:git rm --cachedを使う(おすすめ)

名前を変更した後に、古いファイル名をgit rm --cachedとして削除し、再度ステージしてコミットすると変更が認識されます。

$ mv Hoge.txt hoge.txt
$ git rm --cached Hoge.txt
$ git add hoge.txt
$ git commit -m "[rename] Hoge.txt -> hoge.txt"

ディレクトリ名の場合は

$ mv Hoge/ hoge/
$ git rm -rf --cached Hoge/
$ git add .
$ git commit -m "[rename] Hoge -> hoge"

方法2:git config --local core.ignorecase falseを使う(注意が必要)

ファイル名の大文字小文字の変更を無視する設定をfalseにします。すべてのプロジェクトで区別したい場合は以下のようにglobalで設定してしまっても良いでしょう。

注意点として、core.ignorecase falseを設定する場合でも、旧ファイル名のキャッシュの削除が必要です。(理由は後述)

設定

$ git config --local core.ignorecase false

操作

$ mv Hoge.txt hoge.txt
$ git rm --cached Hoge.txt
$ git add hoge.txt
$ git commit -m "[rename] Hoge.txt -> hoge.txt"

実験

実際に、Git管理下でファイル名を変更して検証してみましょう。

$ mkdir test && cd test
$ git init
$ touch Hoge.txt
$ git add . && git commit -m "Hoge.txtを追加"
$ git ls-files
Hoge.txt

Gitで監視しているファイルはHoge.txtであることが確認できます。

さて、ファイル名を変更してみましょう。

$ mv Hoge.txt hoge.txt
$ ls
hoge.txt

$ git status              
On branch main
nothing to commit, working tree clean

$ git ls-files                    
Hoge.txt

lsではhoge.txtが存在していることになっているのですが、gitではHoge.txtが存在していることになっています。(変更が検知されていない)

そこで、以下のように元のファイルのGit管理を削除します。

$ git rm --cached Hoge.txt 
rm 'Hoge.txt'

$ git status
On branch main
Changes to be committed:
  (use "git restore --staged <file>..." to unstage)
	deleted:    Hoge.txt

Untracked files:
  (use "git add <file>..." to include in what will be committed)
	hoge.txt

--cachedをつけないと、hoge.txtが削除されます。これは、Gitはhoge.txtはHoge.txtだと思っているためです。

$ git add hoge.txt
$ git status
On branch main
Changes to be committed:
  (use "git restore --staged <file>..." to unstage)
	renamed:    Hoge.txt -> hoge.txt

$ git commit -m "[rename] Hoge.txt -> hoge.txt"

すると、Git管理されているファイル名と実際のファイル名が一致します。

$ git ls-files
hoge.txt

これで、ファイル名の変更が完了です。

core.ignorecase falseを使う場合

以下のように設定します

$ git config --local core.ignorecase false

ファイルを作成しコミットします

$ touch Hoge.txt
$ git add .
$ git commit -m "[add] Hoge.txt"
[main ea4f41b] [add] Hoge.txt
 1 file changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 Hoge.txt

名前を変更してみます

$ mv Hoge.txt hoge.txt

すると、Gitはファイルの追加として検知します

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

nothing added to commit but untracked files present (use "git add" to track)

コミットしてみます

$ git add .
$ git commit -m "[rename] Hoge.txt -> hoge.txt

すると、GitとしてはHoge.txtも残っていることになっています。

$ git status
On branch main
nothing to commit, working tree clean

$ git ls-files
Hoge.txt
hoge.txt

このままリモートリポジトリなどにプッシュしてしまうと、二つのファイルが存在する状態が反映されてしまいます。

そのためcore.ignorecase falseを設定する場合でも、旧ファイル名のキャッシュの削除が必要です。

$ git rm --cached Hoge.txt
rm 'Hoge.txt'

$ git ls-files 
hoge.txt

結論

どちらの方法でも、キャッシュを削除しないといけないことには変わりないので、個人的には方法1がおすすめです!

GitHubで編集を提案

Discussion