有時候會需要 fork 某個 repository 來進行修改,而 fork 會強制設為公開。若自己修改的版本想轉成 private,但又想獲取原始 repository 的更新,可以使用 bare repository 與新增 remote 來達成。

本文章以 GitHub 做示範,其他平台的操作同理。

Clone Bare Repository

什麼是 Bare Repository?

一般的 clone 會把 remote 的檔案下載到工作目錄方便修改,而使用 git clone --bare 只會下載用於版本控制的檔案(平常放在 .git 裡面的檔案),主要用於 server 端避免 push 時衝突,或者用於備份、轉移 repository。

如果 server (remote) 是 non-bare,則 server 的資料夾會有實際的檔案。
當使用者 push 到 server 當前所在的 branch 時,git history 會更新,但工作目錄不會自動 checkout 到新的 commit,就會導致衝突。

Clone 指令

若已經 fork 到自己的帳號並做了一些修改,可以先將 repository 暫時改名,用更改後的名字進行以下操作,例如將 example 改為 example1。沒有的話直接 clone 想要 fork 的 repository 即可。

將 bare repository clone 到電腦(任意位置皆可,搬移完成就能刪除此目錄):

git clone --bare "https://github.com/<username>/example1.git"

此時會出現一個 example1.git 的目錄。

用 Mirror 方式 Push 到 GitHub

先在 GitHub 上建立一個空的 repository(假設叫 example),這就是要 push 的目標。

接著用 mirror 的方式將原始 repository 的 git 資訊完整複製到這個 repository:

cd example1.git
git push --mirror https://github.com/<username>/example.git

完成後就能把剛剛 clone 的 example1 刪除了,然後把 example clone 到自己的電腦(不加 --bare)就能開始自己的修改。

若在電腦已經 clone 過了,可以試試看 git fetch 是否正常運作。

與原始 Repository 保持同步

使用上面的方法後,新的 repository 是類似複製一份,而不是 fork。若還想與原始的 repository 同步,獲取最新的 commit,可以把它加到 remote。

在電腦上的 example 目錄內操作:

git remote add upstream https://github.com/<username>/<repo name>.git
git remote set-url --push upstream DISABLE

通常 repository 本身的 remote 會叫做 origin,現在多了一個 upstream,而這個 remote 移除了 push 功能,只留下 fetch。

這樣每次在 pull 的時候,就會同時從這兩個 remote 更新 commit,然後就能用 mergerebase 等方法把原始 repository 的新功能加到自己的 repository。

參考連接