iT邦幫忙

第 11 屆 iThome 鐵人賽

DAY 20
1
Software Development

用樂高玩轉 GIT 版本控制系列 第 20

Day 20 - 與中心溝通出現障礙 繼續談 git push, fetch, pull

Day 19 的時候,我們提到可以使用 git pushgit fetch 兩個指令把本地的 GIT 儲存庫狀態物件與遠端的共用儲存庫做 GIT 的物件狀態同步及更新,看起來也似乎很美好,但實務上的使用都這麼美好嗎?

一、在樂高的世界遇到同步問題該怎麼做?

讓我們回到 Day 18 的樂高製作手冊與共用儲存空間的故事。現在我們參與共用專案的夥伴有兩個人,分別是 A 與 B,今天 A 開始了這個共用專案的計畫,這是一個要打造樂高直升機的計畫,首先 A 先把直升機專案的部分製作手冊分享到共用儲存區上,B 也複製了一份手冊,並開始基於 A 提供的手冊版本,繼續根據自己的專長新增手冊的內容,而 A 也持續的在編修這本直升機專案的手冊。

這時候 B 先完成了新的功能需求,並且也更新了共用儲存區的樂高手冊;而 A 因為埋首於專案上,遲遲未到共用儲存區了解有沒有新的進度,這時候直接把基於上一次分享到共用儲存區的功能,又新增了新的功能,並且再次到共用儲存區分享,這時候看到 B 已經搶先一步有了更新了,那 A 該怎麼辦?

A 這時候首先要了解 B 提供的新功能需求做了什麼,而後評估自己目前完成的新功能,能不能接著從 B 目前提供,如果可以,那 A 就可以把 B 提供的新手冊內容,與自己的手冊直接合併在一起,也就完成這次的新手冊功能更新,等 B 再次來到共用儲存區查看時,就可以發現 A 也提供了同樣的功能,並且把 A 的新手冊取回。

有沒有覺得這劇情跟之前 Day 12Day 13Day 14 談到的 git mergegit rebase 有點像?沒錯的,其實在 GIT 版本控制的環境下,與共用儲存中心的訊息同步、 GIT 物件更新等,最重要的指令不外乎 git pushgit fetch ,物件同步完畢之後,其實就還是 git mergegit rebase 的合併概念。

我們回到 GIT 的情境下,繼續看上面樂高手冊的例子,在 GIT 環境下會是怎麼一回事。

二、GIT 共用儲存區同步有狀況

狀況一:本地及遠端有 HASH A、B,本地新製作了 HASH C,遠端有新的 HASH D,這時候執行 git fetch

這時候本地端跟遠端的共用儲存區更新狀態,發現遠端多了一個 HASH D,且就接續在 HASH B 之後,這時候一樣還是會把 HASH D 複製到本地,並且更新 origin/master 這個分支貼紙,移動到 HASH D 的位置。

git fecth hash d

如果單看本地端的儲存庫分支標籤變化,就會是如下圖的動畫呈現:

git fecth repo change

狀況二:那要怎麼解決呢?

在把物件更新到本地之後,其實就是 Day 12Day 13 提到的 git merge 的內容範圍了,所以這時候,我們只需要執行以下的 GIT 指令 git merge origin/master,就可以把遠端的 GIT 物件跟本地的物件合併在一起。

git merge origin/master

狀況三:有什麼指令可以一起做掉? git pull

一定都要執行 git fetch 而後才能 git merge 嗎?如果我每次都信任遠端給我的新物件,那能不能直接有個指令可以一次完成這兩個指令?有,他叫做 git pull,執行起來大概如下動畫:

git pull

從動畫中可以發現, git pull 也就是 git fetch + git merge origin/master 的連續技。

一般情況如果本地沒有新的 commit,其實 git pull,會啟用 Day 13 提到的 fffast-forward,在畫面上的執行效果大概如下:

git pull with ff

在同樣的情境下, git pull 在本地的儲存庫與分支的變化,看到的大概這樣子:

git pull with local commit change

狀況四:如果本地跟遠端都有 HASH A、B,遠端有 HASH C 的情況下,本地又新增了 HASH D,此時 Push 會發生什麼事情?

共用儲存庫通常會罵你,給你一個警告,並且不讓你把目前的這個 HASH C 推出,提醒你必須先解決遠端已經有新物件存在這件事情。動畫大致上如下:

git push with alert

而如果這邊以 apple 這個分支模擬,在 CLI 的畫面上,通常可以看到這個警告訊息:

git push reject

狀況五:同樣的情況,如果硬是要推出去呢?

可以執行 git push,但必須要再加上一個參數也就是 git push -f 這個 -f 的概念其實也就是 --force

git push force

正常來說,會拜託不要這樣,如果你很肯定的這樣強制的更新共用儲存庫的 GIT 物件狀態,並不會造成其他一起使用這個儲存庫的人困擾,或者是在團隊可以承受,已知應該怎麼做、怎麼處理的狀況下才這樣做。而,目前大部分的 GIT Server 其實都有建立直接 push 某些分支,礙於權限設定,是會被阻擋的。

總結:

GIT 的本地與遠端操作,還有與遠端的物件合併,透過 Day 19 與今天的說明之後,希望可以讓有一起使用 GIT 共同開發的邦友們,不在害怕與團隊一同使用 GIT。其實 GIT 的本地和遠端同步,最重要的就 git pushgit fetch,當了解這兩個指令之後,其他都只是分支的合併操作而已。


上一篇
Day 19 - 與共同儲存中心開始溝通 談 git push 與 git fetch
下一篇
Day 21 - 如何讓 GIT 的線圖更整齊好閱讀,談 GIT 合併的各種方法
系列文
用樂高玩轉 GIT 版本控制30

尚未有邦友留言

立即登入留言