iT邦幫忙

第 11 屆 iThome 鐵人賽

DAY 26
2
Software Development

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

Day 26 - GIT 狀況題 03 不小心把還沒合併到主分支的分支刪除了,該怎麼辦?

今天的狀況題是這樣的,某一個開發者,因為手上管控的分支太多,一個不小心把還沒合併到主分支且也沒有更新到遠端的分支刪除了,應該要怎麼救回這個分支?

情境概略可以這樣模擬,剛開始 feature 還有兩個 commit,最後一個 commit 的 commit message 為「add feature 2」。

開始 feature 還有兩個 commit

但不小心刪除 feature 分支之後,只剩下 master 的兩個 commit。

只剩下 master 的兩個 commit

怎麼刪除尚未合併的分支?

一般的情境下,刪除尚未合併的分支,無論是 SourceTree 或 CLI 底下,都會提示警告訊息,如 SourceTree 會提示,並且詢問是否「Force delete」的選項:

詢問是否「Force delete」的選項

在 CLI 底下如透過一般的刪除指令 git branch -d feature 則是提醒「error: The branch ‘feature’ is not fully merged.」如果真的要刪除,則必須使用 git branch -D feature 才能夠刪除。

必須使用 git branch -D feature 才能夠刪除

那這個參數 -D 是什麼意思呢?根據 git help branch 查詢所得到的內容,-D 參數代表著原本的 --delete --force 也就是強制刪除。

-D 參數代表著原本的 --delete --force

一般實務上,會預設使用 -d 參數作為刪除分支用,也是為了避免如今天所要談的案例發生,所以,如果有習慣性使用 -D 參數刪除分支的邦友,建議將習慣改回使用 -d 參數,避免一些麻煩。但如果還是發生了呢?

解法一:透過刪除時的資訊,再次把分支建立回來

步驟一:

一般來說,在刪除分支的時候,訊息尾端都會提示剛刪除的分支所在的 HASH Code 是什麼,如下圖,顯示刪除前 feature 分支,在 0f3eb49 這個位置。找到這個 HASH Code 很重要。

刪除前 feature 分支,在 0f3eb49 這個位置

步驟二:

還記得 Day 08 的時候,提到 GIT 的 branch 分支是什麼概念嗎?在 GIT 的版本控制系統裡,branch 只是一張可以移動的標籤貼紙,當該 branch 有新的 commit 產生時,自動移動到新的 commit 所對應的 HASH Code。所以,分支被刪除了,其實,也只是這張標籤貼紙,被撕掉了,背後的 commit 及 HASH Code 都還在

因此,這時候,我們只要針對目標的 HASH Code 重新貼上標籤貼紙即可。在上一個步驟中,我們記下了 0f3eb49 這個 HASH Code,是被刪除的 feature 最後的所在位置,因此,我們只要執行指令:

git checkout -b feature 0f3eb49

就可以救回 feature 這個分支,重新把 feature 這個可移動的標籤貼紙重新貼回。上面的指令是什麼意思呢?git checkout -b feature 代表的是,建立 feature 這個分支,並且切換 HEAD 到 feature 分支。如果在 feature 後面再加上 HASH Code,則代表在該 HASH Code 建立分支,並且切換過去。

透過 git checkout -b feature xxxx

如果不要切換過去呢?那可以執行:

git branch feature 0f3eb49

git checkout -b feature 0f3eb49 建立分支的效果一樣,但不會把目前的 HEAD 切換到新建立的分支上。

解法二:如果找不到刪除時留下的紀錄,那該怎麼找回呢?

步驟一:

可以透過指令 git reflog 查詢過去關於分支切換、建立、commit 新增等等的資訊紀錄,如下圖,是這篇文章製作的範例所留下來的紀錄:

git reflog

git reflog 的指令操作上,可以透過鍵盤的上下鍵或 jk 兩鍵,往上或往下移動選擇,也可以透過點選 / 斜線後,輸入關鍵字作搜尋,透過搜尋找到最後的 feature 分支上的 commit 對應的 HASH Code,搜尋結束之後,輸入 q 鍵即可離開。

git reflog 使用及搜尋

搜尋的這時候,大家就會開始覺得,平常把 commit message 寫得好很重要,讓標題可以搜尋的到,就顯得非常重要。

步驟二:

其實找到對應的 HASH Code 之後,方法可以跟解法一一樣,直接透過 git checkout -b featuregit branch feature 後面接上找到的 HASH Code就好。但這邊其實也可以透過 Day 24 的狀況題 01 一樣的方法,可以透過 git rebasegit mergegit cherry-pick --ff 等三個指令,三個方法,把 feature 移動到想移動的分支。這邊就以 rebase 的方式,標示指令。

git checkout -b feature
git rebase 0f3eb49

上面的指令是假設,目前在 master 分支,也就是原本 feature 的基點。因此在原本的基點建立 feature 分支之後,只需要再把 feature 這個分支標籤貼紙,透過 fast-forward 的方法移動到需要移動的位置即可。(什麼是 fast-forward,詳見 Day 13 談關於 git 的 merge 機制 )

總結:

這一篇談了兩件事情,一是在刪除分支時,建議預設使用 -d 指令,真的很明確的知道有需求,才使用 -D 參數,強制刪除。二是,再次的強調,GIT 的分支概念,只是一個可移動的標籤貼紙,把貼紙撕掉之後,本體的 HASH Code 及對應的 Commit 是還可以找到的。


上一篇
Day 25 - GIT 狀況題 02 建立了分支之後,忘記 checkout 就 commit,該怎麼處理?
下一篇
Day 27 - GIT 團隊協作 談 流程管理 01 GitFlow
系列文
用樂高玩轉 GIT 版本控制30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

1 則留言

0
CookieTsai
iT邦新手 5 級 ‧ 2019-11-14 13:57:50

寫得真不錯 推一個 0w0

墨嗓 iT邦研究生 4 級 ‧ 2019-11-14 15:06:49 檢舉

/images/emoticon/emoticon41.gif

我要留言

立即登入留言