スキップしてメイン コンテンツに移動

【Day 34】Windowsの大文字・小文字ファイル名変更トラブル(git mv)

Day 34 アイキャッチ
▲ 【Day 34】Windowsの大文字・小文字ファイル名変更トラブル(git mv)
👨‍🏫
皆さん、こんにちは! 本講座の専任講師です。
前回のDay 33では、改行コードの全行差分事故を恒久的に防ぐ .gitattributes の完全定義と、リポジトリの一括正規化手順を学びました。
続く本日のDay 34は、第7部「Windows & C# (.NET) 固有の落とし穴完全制覇」の第2弾――
すべてのWindows / C#開発者が一度は必ず絶叫する【Windowsの大文字・小文字ファイル名変更トラブル(git mv)】を徹底攻略します!
「Windowsのローカル環境やVisual Studioでは何の問題もなくビルドが通り、意気揚々とプルリクエストを作成したのに、GitHub Actions(Linux CI)が走った瞬間に謎のビルドエラーで落ちた…!」
「エクスプローラーやIDEで UserService.cs を userservice.cs にリネームしたはずなのに、Gitが全く差分を認識してくれない…!」
「ネットで見かけた git config core.ignorecase false を実行したら、同一フォルダに大文字と小文字のファイルが2重出現してリポジトリが壊れた…!」
このような怪奇現象は、Windows(大文字小文字を区別しない)とLinux / GitHub(厳格に区別する)というOSの基本思想の違いから発生します。
本講義では、Gitの内部フラグ core.ignorecase のメカニズムを解明し、事故を100%防ぐ git mv による確実な改名作法を完全マスターしていきましょう!

① 導入・なぜWindowsとLinux/GitHubで事故が起きるのか?

Windows上でC#開発を行っていると、ファイル名の大文字・小文字を意識する機会はほとんどありません。
Windowsの標準ファイルシステムである NTFS(または FAT32) は、「大文字・小文字を区別しない(Case-Insensitive)」 仕様になっているためです。
たとえば、UserService.cs というファイルが存在するフォルダで userservice.cs や USERSERVICE.CS を開こうとしても、Windowsはすべて同じファイルとして正常にアクセスできます。

Windows vs Linux「大文字・小文字」の悲劇
▲ 【図解①】Windows vs Linux「大文字・小文字」の決定的な違いが生む悲劇

しかし、Webサーバーやクラウド、そしてGitHub Actionsをはじめとする現代のCI/CD環境の大多数は Linux(ext4等) で動作しています。
Linuxは 「大文字・小文字を厳格に区別する(Case-Sensitive)」 ため、UserService.cs と userservice.cs は完全に「別の2つのファイル」として扱われます。

🚨 なぜローカルで動くのにCIでビルドエラーになるのか?
  • C#コード側: using MyApp.Services; やDI設定で userservice.cs を参照するようになった。
  • Windowsローカル: ファイルシステムが大文字小文字を無視するため、古い UserService.cs が残っていてもビルドが奇跡的に通ってしまう。
  • GitHub Actions (Linux): リポジトリ上に UserService.cs しか存在しない場合、Linuxコンパイラ(dotnet build)は「userservice.cs が存在しません!(CS2001エラー)」と判定して即座にビルドが爆発します。

② Gitのデフォルト設定「core.ignorecase」の罠

「じゃあ、エクスプローラーやVisual Studioでファイル名を小文字に変更してコミットすればいいのでは?」と誰もが思います。
しかし、実際にエクスプローラーで UserService.cs を userservice.cs に変更して git status を打ってみてください。

# エクスプローラーで UserService.cs を userservice.cs にリネームした直後
$ git status
On branch main
nothing to commit, working tree clean ← な、何も変わっていない扱い!?
なぜエクスプローラーでの改名はGitに無視されるのか?
▲ 【図解②】core.ignorecase の挙動とエクスプローラー改名の落とし穴

驚くべきことに、Gitは「変更なし(working tree clean)」と表示し、ファイル名の変更を完全に黙殺します!
この原因こそが、Windows環境でGitを初期化した際に自動的にオンになる設定 core.ignorecase = true です。

🔍 core.ignorecase が true になっている理由

GitはWindowsが「大文字小文字を区別しないOS」であることを知っているため、過剰な差分検知を防ぐ目的でデフォルトで core.ignorecase = true を設定します。
その結果、「大文字小文字しか違わないファイル名変更」は 同一ファイルのままと判断され、Gitのインデックス(ステージング領域)に登録されない のです。
開発者はリネームできたと思い込んでプッシュしますが、リモートリポジトリ(GitHub)上には古い大文字のまま残り続け、ローカルとリモートの致命的な乖離が発生します。

⚠️ 【厳禁】安易に core.ignorecase = false にしてはいけない!

インターネットの記事の中には「git config core.ignorecase false にすれば大文字小文字を検知してくれる」と書かれているものがありますが、Windows環境でこれを実行するのは極めて危険です!
OS側のファイルシステム(NTFS)は大文字小文字を同一とみなすのに対し、Git側だけが別物として扱うため、同一フォルダ内に大文字版と小文字版の2重ファイルが存在すると誤認され、ブランチの切り替えやマージの際にファイルが消失したり上書きされたりする壊滅的な破損を引き起こします。

③ 安全・確実な解決策!「git mv」を使った改名作法

では、Windows上で大文字・小文字のファイル名変更をGitに正しく認識させるにはどうすればよいのでしょうか?
その絶対的な正解が、Git専用の移動・改名コマンド git mv を使用することです!

大文字・小文字を安全に改名する「git mv」の確実な手順
▲ 【図解③】安全・確実にファイル名を改名する「git mv」の作法(直接変更&2段階改名)

方法A: git mv による直接改名(最新Git推奨)

近年の Git for Windows(v2.x以降)では、git mv を使えば大文字小文字のみの変更であっても直接リネームを認識できるよう改良されています。

# git mv で大文字から小文字へ直接改名
$ git mv UserService.cs userservice.cs

# ステータスを確認(renamed として即座にステージングされる!)
$ git status
Changes to be committed:
  renamed: UserService.cs -> userservice.cs

# コミットして完了
$ git commit -m "refactor: UserService.cs を userservice.cs に改名"
$ git push origin main

方法B: 環境に左右されない「確実な2段階改名」(プロの鉄板技)

古いバージョンのGit環境や、一部のGit GUIツール、または複雑なフォルダ階層において、git mv UserService.cs userservice.cs を実行すると fatal: destination exists というエラーで弾かれる場合があります。
そのような時でも100%確実に成功するのが、一時的な別名を経由する 「2段階改名」 です。

# ステップ1: 一時的な別名(_temp)に退避改名
$ git mv UserService.cs UserService_temp.cs

# ステップ2: 一時名から目的の小文字名へ改名
$ git mv UserService_temp.cs userservice.cs

# ステータス確認(Git内部で自動的に UserService.cs -> userservice.cs の1つの改名に統合される!)
$ git status
Changes to be committed:
  renamed: UserService.cs -> userservice.cs

$ git commit -m "refactor: UserService.cs を userservice.cs に安全改名"

④ SVN比較 & C# (.NET) 現場での実践テクニック

🏛️ SVN(Subversion)との比較:ファイル名大文字小文字の歴史

Subversion時代、Windows上でファイル名の大文字小文字を変更しようとすると、「すでに同じ名前のファイルが存在します」という競合エラーが発生し、コミットも更新もできなくなって作業コピーを泣く泣く再チェックアウトした経験を持つベテラン開発者は多いはずです。
Gitにおいてもファイルシステムの壁は存在しますが、Gitは 「インデックス(ステージング領域)という論理的な管理層」 を持っているため、git mv を通じてインデックスを明示的に更新でき、SVNのようにリポジトリ全体がロックされて破壊されるリスクを綺麗に回避できます。

チーム全員で大文字・小文字トラブルを防ぐ3大鉄則
▲ 【図解④】チーム全員で大文字・小文字トラブルを防ぐ3大鉄則

C# / Visual Studio 現場で守るべき3大鉄則

  1. Visual Studioのリファクタリング機能(F2)後は必ず git status を確認する
    クラス名を UserService から userservice に変更する際、Visual Studioは親切に「ファイル名も変更しますか?」と聞いてくれます。
    しかし、Visual Studio内部のGit連携バージョンによってはエクスプローラー同様にファイル変更がGitに伝わらないことがあります。リファクタリング後は必ずターミナルやGit変更ウィンドウで renamed がステージングされているか確認しましょう。
  2. GitHub Actions等のCIで「Linuxランナー(ubuntu-latest)」を常時稼働させる
    Windowsデスクトップアプリ(WPF/WinForms)でない限り、Web API(ASP.NET Core)やクラスライブラリのビルドテストはCI上で runs-on: ubuntu-latest を設定しましょう。
    Linux上で dotnet build を走らせることで、大文字小文字のミスやパスの区切り文字違いをプルリクエストの段階で100%自動検知できます。
  3. TortoiseGitを使う場合は「名前を変更」メニューを利用する
    エクスプローラー上で右クリックし、「TortoiseGit」→「名前を変更...(Rename)」を選択して変更すれば、TortoiseGitが内部で安全に git mv 相当の処理を実行してくれます。

📌 本日のまとめと最重要ポイント

  • Windows(NTFS)は大文字小文字を無視し、Linux/GitHubは厳格に区別する! このギャップが「ローカルで動くのにCIで爆発する」元凶。
  • WindowsのGitはデフォルトで core.ignorecase = true! エクスプローラーでの改名はGitに無視される。
  • 絶対に core.ignorecase = false にしてはいけない! 二重ファイル認識でリポジトリが破壊される。
  • 改名は必ず git mv または「一時名を経由する2段階改名」で行う!
  • GitHub ActionsでLinuxビルド(ubuntu-latest)を回し、事故を未然に完全ブロックせよ!
次回予告

【Day 35】巨大バイナリ・DLL・画像管理の決定版(Git LFS)

「リポジトリの容量が数GBに達してクローンが激重に…!」「インストーラーや重いアセットはどう管理する?」
SVNが得意だったバイナリ管理をGitで美しく実現する神ツール Git LFS(Large File Storage) の導入と運用を徹底解説します! 次回もお楽しみに!

コメント

このブログの人気の投稿

【Perfume】Perfume 3rd Tour 「JPN」さいたまスーパーアリーナに行って参りました~

Perfume 3rd Tour 「JPN」1月28日、29日の2daysで参戦して参りました。 ファンクラブ会員の選考抽選会に28日、29日の両日で申し込んでいたんですが、両方とも当選していたという嬉しい誤算。 仕事だぁ、なんだかんだと紆余曲折ありまして28日の参戦は危ぶまれていたのですが、なんとかかんとか28日は40分遅刻しながらも参戦、29日はフル参戦する事が出来ました(∩´∀`)∩

Perfume、2025年末で“コールドスリープ(活動休止)”へ──東京ドーム2daysの記録と、公式・各界・ファンの声

  1) 公式発表・基本情報 活動休止(コールドスリープ)を正式発表 2025年9月21日、公式サイト「 Perfumeより 」で、2026年から一度コールドスリープに入ると発表。再始動の意思(“新しいPerfume”として戻る)も明記。 Perfume Official Site 今後の運用告知(配信・上映など) 同21日付の「 今後のPerfumeに関して 」で、9/23(火・祝)東京ドーム公演の LIVESHIP全世界生配信 および 全国ディレイビューイング 決定を案内。特設サイトも併記。 Perfume Official Site +1 公式グッズ **「Perfume Calendar 2026」**発売決定(B2壁掛け/表紙+2カ月1枚×6枚+ポスター)。テーマは“フルーツ”。 Perfume Official Site 2) 東京ドーム2days(9/22・23)要点 公演タイトル: ZO/Z5 Anniversary “ネビュラロマンス” Episode TOKYO DOME 。日程・開場/開演・会場・物販等の実務情報は特設で公開。 Perfume Official Site 9/23公演を世界配信(LIVESHIP) /ディレイビューイング実施。 Perfume Official Site 海外向け報道(英語)も「 indefinite hiatus 」として広く配信。 The Times of India 国内英字メディアも速報。 朝日新聞 3) 現地レポ( メリ爺 )から見える空気 あなたの現地記録(9/24公開)を、ファクトと現場情景の両面で反映: 両日参戦 。22日は アリーナ 、23日は 1階席から俯瞰 。前日の発表を受け、開演前のザワつき→MC後に“いつもの一体感”へ。開演は22日 18:45 頃。オープニングは**P³ツアー東京ドーム(2020/2)**と同趣向で“回収”の演出。 メリ爺のゲーム万歳 MC所感 :解散ではなく前向きな休止で不安を和らげる内容。 かしゆか の涙、 のっち の気丈さ、 あ〜ちゃん の思い出語り──3人の結束と「 また戻る 」約束が強く刻まれた。 メリ爺のゲーム万歳 体感時間 : “3時間弱”級のボリューム ながら“過去一...

ニンテンドースイッチでオンラインゲームを遊ぶには?

モンスターハンターライズが発売になって、家族でモンハン楽しみたい人が増えたみたいですね。 某ブログの検索キーワードを調べると、モンハンを家族でやるにはどうしたらいいのか?を調べている人が沢山いるのがわかります。 ※これでも一部  家族で協力するにはSwitch2台、ソフトも2つ購入する必要があります。 1台のスイッチでは遊べませんし、ソフト1つでも遊べません。 でも、1台のスイッチで別々アカウントがあれば交代で遊ぶこともできますよ。セーブデータもしっかり分かれます。 Switchのオンラインゲームを家族で遊ぶ方法については以下の記事にまとめてますのでよろしければ参考にしてみてくださいね。 家族でモンスターハンターライズDL版のオンラインプレーを楽しむ方法