如何保持 GitHub Fork 專案同步
原文:Keeping GitHub Forks in Sync
作者:beejjorgensen 發表時間:2018/1/13
譯者:陳 昌茂 發表時間:2018/8/29
(轉載請註明出處)
很多時候,你在 GitHub 上 Fork
了某個上游專案,還希望同步原專案作者在此後所做的變更。
雖然使用者很早就提交了 功能提議,但GitHub 到目前為止還不支援在 Web 介面上的同步操作。遺憾的是,可能以後也不會。
這很正常。本文通過命令介面操作,幾條命令可以就解決專案同步的問題。
前言
為方便行文,我們將專案的三個別名介紹如下:
origin
:代表遠端專案,即 GitHubFork
專案(克隆自上游專案,即upstream
)local
代表本地專案,即電腦上的本地專案(克隆自遠端專案)upstream
:代表上游專案,即被Fork
的 GitHub 專案。
有兩種方法使 origin
與 upstream
保持同步:
- 提交合並建議(PR)給
upstream
,上游專案的作者能在 GitHub 的 Web 介面上操作是否接受你的 PR。當然這通常很少發生,因為通常有成百上千的人克隆了他的專案,他不得不這麼做。(譯者認為「有用」的PR一般是會被接受的) - 把
upstream
的更新獲取併合併到local
,然後推送到你的origin
。這是最常用的方法。
什麼是 upstream
upstream
是很重要的設定,只需進行一次。
upstream
是遠端專案地址的別名,代表一個遠端專案的 URL 地址(類似 DNS 之於 IP 地址,可用 git remote
檢視,譯者注)。雖然可以每次在引用遠端專案的時候都使用完整的 URL 地址,但這是一個痛苦的體驗,所以我們用「別名」。
如你所見,origin
也是一個遠端專案的別名,在克隆專案的時候 git
命令會自動設定為被克隆專案 URL 地址。
如果你已經克隆了一個專案,可以使用 git remote -v
命令來檢視。
$ git clone git@github.com:MyName/My-Forked-Repo.git
[...cloning output...]
$ git remote -v
origin git@github.com:MyName/My-Forked-Repo.git (fetch)
origin git@github.com:MyName/My-Forked-Repo.git (push)
複製程式碼
可以設定多少個遠端專案別名,因為它們僅僅代表一些遠端專案的 URL 地址而已。讓我們來加一個「引用 」到上游專案,別稱為 upstream
。
$ git remote add upstream https://github.com/LambdaSchool/Original-Repo.git
$ git remote -v
origin git@github.com:MyName/My-Forked-Repo.git (fetch)
origin git@github.com:MyName/My-Forked-Repo.git (push)
upstream https://github.com/LambdaSchool/Original-Repo.git (fetch)
upstream https://github.com/LambdaSchool/Original-Repo.git (push)
複製程式碼
現在可以看到有2個遠端專案別名。
你可能注意到,遠端專案 URL 地址是 HTTPS 的。這是因為我們(大概)沒有上游專案的 SSH 訪問許可權,但這沒關係,因為我們只需要讀取許可權即可,並不需要寫入許可權。
同步你的 Fork
如上圖所示,我們把 upstream
的更新獲取併合併到 local
,然後推送到 GitHub 上的 origin
。操作完成後,local
和 origin
就與upstream
保持同步了。
下述操作,是假設將 local
的 master
分支與 origin
的 master
分支合併。如果合併其他分支,調整成對應的分支即可。
從 upstream
獲取更新
命令 git fetch
與 git pull
功能一致,區別是前者只獲取不合並。
有趣的是:
git pull
即是git fetch
命令和git merge
命令的簡寫。
執行如下命令,從 upstream
獲取更新:
$ git fetch upstream
[...fetch output...]
複製程式碼
合併 master
分支與 upstream/master
分支
上一步獲取了 upstream
的所有更新。這一步是如何合併這些更新。
1,執行如下命令,檢視本地是否已經提交了全部變更。
$ git status
On branch master
Your branch is up-to-date with 'origin/master'.
nothing to commit, working tree clean
複製程式碼
如果提示有暫存的變更,請參考這提交之後再繼續。
2,確保切換到本地的 master
分支,因為 master
分支是準備要合併的分支。(*號表明是當前的分支)
$ git checkout master
$ git branch
* master
複製程式碼
3,執行合併操作。下述命令中的 upstream/master
指 upstream
的 master
分支。(區別本地的 master
分支)
$ git merge upstream/master
[...merge output...]
複製程式碼
注意,如果提示輸入修訂日誌,請輸入「合併分支」或任何其他內容。(如果是 fast-forward
方式合併,無需輸入修訂日誌)
如果在合併過程中沒有看到任何衝突提示資訊,合併成功,那這會是合併過程中最開心的時刻。
否則在進行下一步前,先解決合併衝突。限於篇幅本文不涉及 如何解決合併衝突,但那會也不會是世界末日。
一個有用的快捷命令 git up
,如何設定請查閱 git-config 文件。
up = "!git remote update -p; git merge --ff-only
@{u}
"
使用快捷命令或多或少會使人忘記如何正確的使用 git pull
命令──不像 git pull
,git up
永遠不會讓你到一個提示,希望你解決一個合併衝突。
git up
從所有上游分支下載所有最新提交(修剪死分支),並嘗試將本地分支快速轉發到上游分支上的最新提交。如果成功,則沒有本地提交,因此沒有合併衝突的風險。如果存在本地(未重新整理)提交,則快進將失敗,從而可以在執行操作之前檢視上游提交。
上傳到 origin
在獲取和合並操作後,本地專案已經和上游專案保持同步。要使遠端專案也保持同步,還得執行如下命令:
$ git push
[...push output...]
複製程式碼
至此,此次同步工作完成!