這篇文章是 GitHub 作為 repo host,不過下列操作都沒有 depend on GitHub。或著說,就是不希望用 GitHub 的功能,所以才要有這些步驟,不然 pull request 應該可以解決大部分的狀況。
前情提要
假設 WTF 這個人有一個 foo 的 repo(以下寫作 WTF/foo
),用 GitHub 的 fork 功能產生一個 MyName/foo
的 repo。接著在自己的電腦上對 MyName/foo
作 git clone 也會產生一個 repo,姑且稱之 LOCAL/foo
。
為了簡化起見,所有 branch 一律都是 master
。另外,畫蛇添足補一句:master
只是慣用的 branch 名稱,一個 git repo 沒有 master
branch 也不會怎麼樣。
同樣為了簡化起見,以下也不討論 conflict 的狀況。
remote 設定
在 LOCAL/foo
下列出所有 remote:
git remote -v
以目前的前情提要,會得到
origin https://github.com/MyName/foo.git (fetch)
origin https://github.com/MyName/foo.git (push)
這個名為 origin
的 remote 是 git clone 時自動加上去的,後頭的 url 會隨著 git clone 時下的參數而有所改變(例如變成 git@github.com:MyName/foo.git
)。
所以,要先把 WTF/foo
加到 remote,讓後續操作方便一些:
git remote add wtfRemote https://github.com/WTF/foo.git
之後再作 git remote -v
就會多 wtfRemote
這個 remote 了。
開始 sync
假設 WTF/foo
之後又加了 8 個 commit,在 MyName/foo
的 GitHub 網頁上會提示你
This branch is 8 commit behind WTF:foo.
在 LOCAL/foo
要自己下 git status,而且得有設定過 upstream(在 git push 的時候加過一次 -u
、而且該次 git push 成功)。
這時候就先把 LOCAL/foo
跟 WTF/foo
作 sync,我會這樣下指令:
git pull --rebase wtfRemote master
加上 --rebase
是不希望出現 dummy 的 merge commit,個人認為那還蠻討厭的。當然也有用 git config 來讓所有 git pull 行為都一併作 rebase 的方法,不過這裡按下不表。
如果順利做完 git pull,接下來就是讓 LOCAL/foo
跟 MyName/foo
作 sync,指令是:
git push origin master
如此一來,WTF/foo
增加的那 8 個 commit 內容就會出現在 MyName/foo
與 LOCAL/foo
。
番外篇(?)
如果前情提要不是這樣子,而是在自己的電腦上對 WTF/foo
作 git clone,然後才 push 上 MyName/foo
,要怎麼辦?
答案是:概念是一樣的,只不過變數名字對應的意義不一樣。
這個時候 LOCAL/foo
的 origin
會指向 WTF/foo
。所以要新增的 remote 是 MyName/foo
,其餘步驟都相同。
就跟 master
這個 branch 是約定成俗的道理是一樣的,origin
這個 remote 也是約定成俗地代表 clone 的來源,也就只有這樣。對於 git 的中心思想來講,repo / branch 都沒有主從關係,彼此之間的地位都是一樣的。就像 MyName/foo
是 WTF/foo
fork 出來,但是要把 MyName/foo
的東西 push 回去 WTF/foo
也完全沒什麼不對(基本上 pull request 就是在幹這件事情)。也就不要執著於 master
、origin
字面上的意思,只要搞清楚現在到底是要用哪一個東西、對哪一個目標作什麼事情就好。