使用 Unity 從 git repo 安裝套件時顯示 Revision [...] could not be found. 的錯誤
15 September, 2023 - Tags: Unity, Git, Scoop
在使用 Unity 開發遊戲時,有些著名的套件像是 Extenject 不一定有發佈到 Asset Store 或是 OpenUPM 上面,這時另外一個選項是可以直接透過 git 去 clone 專案來安裝。然而,我之前在安裝時卻發現 Unity 會出現以下錯誤:
Could not clone [https://github.com/UniDi/UniDi.git]. Make sure [HEAD] is a valid branch name, tag or full commit hash on the remote registry.

然而 HEAD 很明顯是一個合法的 revision,而且我也嘗試換過使用 branch 或 tag,也都是得到類似的錯誤訊息。
後來有在 Unity 的 issue tracker 上找到有人回報類似的問題,且標註在我使用的版本此問題已經被修復了,但很顯然的在我的電腦上他就是不 work。不過底下留言有人提到:
Root of my issue was that I installed Git on Windows via scoop. And the way scoop handles the link to the Git executable was messing with Unity.
而根據他提供的方法,修改環境變數讓 shell 會直接抓到 git 執行檔確實是解決了我的問題,可以正常安裝 package 了。雖然問題順利解決,但我還是覺得不大舒服,因為這個做法導致我每次升級 git 都要更新 PATH,否則就會讓我的 shell 用到舊的版本,因此打算再深入一點瞭解這問題,找找有沒有其他的解決方案。
Shim 是什麼?
在上面那則留言有提到,scoop 安裝的 git 是個 link to the Git executable,雖然我以前就知道 scoop 安裝軟體時會做一些額外的操作,最後會把所有程式丟到一個叫 shims/ 的資料夾底下,但我並沒有認真去瞭解過 shim 到底是什麼。
後來我在 Chocolatey 的文件發現他們有詳細的介紹 shim 的概念,簡單來說它可以視為執行檔的 adapter,在實際跑目標執行檔之外做一些額外的操作,所以並非捷徑或 link,而 scoop 目前預設應是使用一個由 C# 撰寫的程式來做 executable shimming。
不過,shim 並非 scoop 或 chocolatey 專有的概念,如果有在使用 k8s 的話或許會聽過一個工具 - dockershim,它的出現是為了填補 k8s 所用的 CRI (Container Runtime Interface) 與 docker 之間的空白,讓 k8s 可以使用 docker 作為 container runtime,所以它的名字裡面也有個 shim。雖然現在它已經被移除了,有興趣的話可以閱讀官方的 blog瞭解它的歷史。
Scoop 的 shim 有什麼問題?
在瞭解 shim 的觀念這過程中,我發現 Scoop#4317 這個 issue 回報了跟我一樣的狀況,並且有其中一位 member 提到了 scoop 現在有提供其他的 shim 實作,詳情可參考 Scoop#3634。
這邊有兩個版本:
根據我爬完 #3634 跟兩個 repo README 的瞭解,他們的改進就是實作了正確的 signal handling,還有修正 shim 跟 child process 的生命週期問題,讓這些 shims 的行為更貼近直接執行目標執行檔。參考這邊的 issue comment,要切換 shim 實作只須執行:
scoop config shim kiennq
scoop reset *
就可以把目前系統上的 shims 切換成 kiennq 以 C++ 實作的版本了,而根據我的測試,這個做法可以解決 unity 無法 clone git repo 的問題。