The Will Will Web

記載著 Will 在網路世界的學習心得與技術分享

如何在 Windows 使用 Git 版控時可以區分檔案名稱大小寫

今天被問到一個關於 Git 版控的問題,同事提到我們有個網站專案的 Repo 裡面有個 *.svg 檔案,之前 git commit 的時候使用 helloWorld.svg 這樣的檔名,但是部署的時候發生錯誤,客戶告知必須用英文小寫的檔名才能正常運作,所以他就來修改一下檔案名稱,結果卻發現 Git 怎樣都無法修改檔名大小寫部分,問我該怎麼辦。這篇文章我就來跟各位說明這個問題的來龍去脈與解決方法。

關於忽略檔名大小寫的預設值

你只要輸入以下命令,就可以查詢 Git 所有設定的說明:

git config --help

其中有個 core.ignoreCase 設定,可以用來告訴 Git 是否要區分檔名路徑的大小寫,其預設值為 false,但可能有些特殊情況會讓你的預設值並不是 false

問題發生的原因

有許多 檔案系統 (Filesystems) 本身就是不區分大小寫的 (case insensitive),像是 APFS (Apple File System), HFS+ (HFS Plus), FAT (File Allocation Table), NTFS (New Technology File System) 等等,都是不區分大小寫的檔案系統。其實並非 "Windows" 就是不區分大小寫,而是「檔案系統」本身決定了檔名是否要區分大小寫,其實 Windows 是可以區分檔名大小寫的。

事實上,當你透過 git clonegit init 的時候,Git 會自動判斷你現在所在的檔案系統是否支援區分大小寫,如果你使用 Windows 常見的 NTFS 或 FAT 檔案系統,那麼預設你的 .git\config 會有以下預設值:

[core]
        repositoryformatversion = 0
        filemode = false
        bare = false
        logallrefupdates = true
        ignorecase = true

這裡有個 core.ignorecase 核心設定預設被寫入了 true 的值,但你若在 Linux 或 macOS 底下執行 git clonegit init 的話,預設的 .git/config 並不會有 ignorecase = true 這條設定!

也因此,當你在 Windows 透過 Git 版控時,自然就會忽略所有檔名路徑的大小寫差異,這會讓你永遠無法更新版控中的檔名路徑大小寫

解決方案 1

如果你去查了設定,很有可能你會這樣設定:

git config --global core.ignorecase false

因為一般來說,我們通常會把 Git 組態設定在 --global 全域等級,不過我們在 Windows 作業系統執行 git config core.ignorecase 的話,你會發現永遠得到 true 的結果,也就是怎麼設定都無效。

其實 Git 組態有三個等級,依照優先權排序分別是 --local > --global > --system 等等,而這裡的 --local 就是設定在 本地儲存庫 (Local Repo) 的 .git\config 檔案中,其優先權是最高的。因此,解決這個問題的方法,則是執行以下命令才對:

git config --local core.ignorecase false

如此一來你在執行 git status 的時候,就會判斷檔名大小寫了! 👍

請注意:千萬不要在有區分大小寫的檔案系統中,使用 core.ignorecase=true 設定,這可能會造成許多未知的錯誤! 🔥

除此之外,還有一個冷門的 Git 命令可以用,那就是「一次性」的組態調整,你只要在 git 命令後面立刻接上一個 -c core.ignorecase=false 參數,該命令無論你要執行 statuscheckout 都可以自動區分檔名大小寫,但這個設定對 git clonegit init 是無效的。如下範例:

git -c core.ignorecase=false status

解決方案 2

另一種解決方法,則是使用 git mv 命令,強迫 Git 變更「檔案名稱」,而且此命令會自動忽略 core.ignorecase 組態設定,直接使用你在命令列使用的大小寫來當作檔名。其命令執行的範例如下:

git mv README.md ReadMe.md

上述命令可以強迫將 README.md 修改為 ReadMe.md 檔名,而且儲存在 Git 儲存庫中的檔名也會因此改變!👍

解決方案 3

還有一種可能會發生的問題,那就是你的同事已經更新了檔名大小寫,但是你的 Windows 電腦上的檔名卻一直都沒有變更大小寫。

此時你可以透過以下步驟重置工作目錄:

  1. 請確認工作目錄是乾淨的 (所有檔案都已經加入版控)
  2. 刪除工作目錄下所有檔案 (切勿刪除 .git 資料夾)
  3. 執行 git reset --hard 重置工作目錄

如此一來,所有檔名大小寫都會符合原始碼版控中的所有檔名,這個技巧在 Windows 只對 NTFS 檔案系統才有效喔! 👍

解決方案 4

還有一種可能會發生的問題,那就是你的 Git Repo 中同時有兩個相同檔名不同大小寫的檔案,這樣的 Repo 在 Windows + NTFS 是無法正確顯示檔案的,只有一個檔案會被取出到工作目錄,另一個則會自動標示為 deleted 狀態。假設我們有兩個檔案在版控中,分別是 README.mdReadMe.md,假設你想刪除 ReadMe.md 檔案,其解決問題的步驟如下:

  1. 你無法確認工作目錄是乾淨的,因為永遠會少一個檔案 (因為有兩個同名但檔名大小寫不同的檔案)
  2. 請直接執行 git rm ReadMe.md 命令,此時你用 git status 會被告知刪除了兩個檔案,一個是 staged 狀態,另一個是 not staged 狀態
  3. 接著直接執行 git commit -m "移除重複檔案",並立刻執行 git reset --hard 重置工作目錄,問題就可以迎刃而解!

後記

其實跨平台開發已經成為常態,一個開發團隊中有成員使用 Windows、有成員使用 macOS 屢見不鮮,不單單後端開發經常都可以跨平台,前端的開發團隊更是如此。如果你有使用 CI/CD 對專案進行自動化建置與部署,也有非常高的機率會遇到各種不同作業系統平台的狀況。因此,我建議大家要開始重視「檔名路徑大小寫」的問題,如果可以,請盡量以「小寫」命名,否則很容易會遇到鬼打牆的狀況。

像是本篇文章提到的問題,在我們公司最近一年就遇到了兩次,我原本以為這個問題應該很簡單,但是第一次遇到此問題的人,還是可能會卡關卡很久,所以才出現撰寫這篇文章的契機,希望大家下次遇到這種狀況可以更快的解決問題! 😊

相關連結

留言評論