Git

Gitで大文字小文字の変更を反映する【Gitへ/ローカルへ】

WindowsMacはファイルシステムとして大文字小文字を区別しないため、Gitは大文字小文字の変更を検知しないのがデフォルトとして設定されます。

$ git config -l --local | grep core.ignorecase
core.ignorecase=true

設定を確認するとignorecase: 大文字小文字の無視がtrueと大文字小文字を無視する設定となっています。
これにより、ファイル名やディレクトリ名の大文字小文字を変更しても差分として検出されず、反映できません。
しかしながらLinux上ではしっかり区別されるため、きっちり合わせておきたいものです。

本記事では、大文字小文字の変更をGitやローカルに反映する手順を紹介します。

大文字小文字の変更をGitに反映する

方法1. IDE上で操作する

まず、IDEを使っている場合、一番簡単な方法はIDE上で変更することです。
難しいことを考える必要なく、普通にGitに反映してくれます。

JetBrains製のIDEでの例: ファイル名を右クリックしてリファクタリングから名前を変更する(ショートカットでも可)

方法2. git mvを使う

リポジトリ上のファイル削除時にrmではなくgit rmを使うのと同様、ファイルの移動時もgit mvを使うことでGit操作もしてくれます。
ただし、ディレクトリの場合はgitがディレクトリを動かしてくれないので少し面倒です。

// ファイルの場合
git mv abc.txt Abc.txt

// ディレクトリの場合
git mv abc/* Abc/
mv abc Abc

方法3. ignorecase=falseにする

下記のようにすることで、ファイル名の大文字小文字を区別するように変更できます。

git config core.ignorecase false

ただしGitのキャッシュ機能があるため割と扱いが難しく、この設定だけで完全に解決はできません。
基本的には方法1か2を使用することをお勧めします。

リモートでの大文字小文字の変更をローカルに反映する

他の人が大文字小文字を変更したのでpullしたが反映されない場合、少し手間がかかります。
1ファイルなら直接変更するのが早いですが、「どこを変更されたか分からない」「数が多い」などの場合は以下の手順で対応できます。

// ※余分な変更は事前にcommitやstashなどして無くしておくこと!!
// 大文字・小文字の変更を検知するように変更
% git config core.ignorecase false
// 変更が検知されたファイル、ディレクトリ名を一時的に変更
% git status --porcelain | awk '{print $2}' | sed 's:/*$::' | xargs -I {} mv {} {}_tmp
// ステージング
% git add .
// 戻す
% git reset --hard

// (必要なら)大文字・小文字の変更無視の設定を戻す
% git config core.ignorecase true

解説

あえて一度パスの差分を出して戻すことでGitのパスに合わせています。

  1. まずgit config core.ignorecase falseで大文字小文字の無視にfalseを設定して大文字・小文字の変更を検知するように変更します。
    この時点でgit statusを見ると、Untracked filesに変更されたファイルやディレクトリが表示されるかと思います。
  2. 次のコマンドでファイル名を一時的に変えています。以下コマンドを分解して解説します。
    • git status --porcelainで簡略表示しています。
    • 簡略表示していても先頭に邪魔な ?? がつくので| awk '{print $2}'で各行2番目の要素だけ取ってきてパス部分に絞り込みます。
    • | sed 's:/*$::'でディレクトリの場合の末尾の/を取ります。こうしないとこの後のmvコマンドがdir_tmpへのリネームとしたいのにdir/_tmpへの移動となってコケてしまいます。
    • | xargs -I {} mv {} {}_tmpで検出された対象を_tmpという名前に変更します。差分を出すためにやっているので差分が出れば_aでも1でもなんでもよいです。
    • (この時点でgit statusをみると、元のパスのdeleteと_tmpが付いたUntracked filesという組み合わせになっています。)
  3. git add .を行うことでステージングすると、deleteとUntracked filesが結び付けられ、Git上での大文字小文字がついたファイルパスのものが「大文字小文字が異なり_tmpが付いたファイルへrenamedされた」という扱いになります。
  4. ここでgit reset --hardを行うことで「元に戻す」つまり_tmpがなくなると同時にGit上と一致する大文字小文字のファイルパスへ戻されます。

まとめ

以上の方法で、Gitやローカル環境での大文字小文字の変更を適切に反映することができます。
特に複数人での開発や異なるOS間での作業を行う際に、大文字小文字の扱いには注意が必要です。これらの手順を参考にして、効率的かつ正確にファイル管理を行いましょう。

-Git