← 上一章:【常見問題】合併過的分支要留著嗎? 下一章:另一種合併方式(使用 rebase) →
【狀況題】不小心把還沒合併的分支砍掉了,救得回來嗎?
上個章節「【常見問題】合併過的分支要留著嗎?」提到合併過的分支如果想留就留、想刪就刪,Git 的分支並不是複製檔案到某個目錄,所以不會因為刪掉分支檔案就不見。
但如果刪的是還沒合併的分支就不一樣了,先想像一下這個畫面:
cat
分支是從 master
分支出去的,目前領先 master
分支兩次 Commit,而且也還沒有合併。這時候如果試著刪掉 cat
分支,它會提醒你:
$ git branch -d cat
error: The branch 'cat' is not fully merged.
If you are sure you want to delete it, run 'git branch -D cat'.
「嘿!這個分支還沒全部合併喔」,雖然 Git 這麼貼心的提醒你,你還是依舊把它砍了:
$ git branch -D cat
Deleted branch cat (was b174a5a).
請先記一下這個訊息「Deleted branch cat (was b174a5a).」,待會可能會用到它。這時候的樣子會像這樣:
等等,我不是砍掉 cat
分支了嗎?怎麼東西還在?再次跟大家說明一下分支的觀念:
分支只是一個指向某個 Commit 的指標,刪除這個指標並不會造成那些 Commit 消失。
所以,刪掉分支,那些 Commit 還是在,只是因為你可能不知道或沒記下那些 Commit 的 SHA-1 值,所以不容易再拿來利用。現在原本領先 master
分支的那兩個 Commit 就跟空氣一樣,你看不到空氣,但空氣是存在的。既然它還存在,那就把它「接回來」吧:
$ git branch new_cat b174a5a
這個指令的意思是「請幫我建立一個叫做 new_cat
的分支,讓它指向 b174a5a
這個 Commit」,就是再去拿一張新的貼紙貼回去的意思啦。看一下現在的分支:
$ git branch
* master
new_cat
切換過去試試看:
$ git checkout new_cat
Switched to branch 'new_cat'
確認一下檔案列表:
$ ls -al
total 16
drwxr-xr-x 9 eddie wheel 306 Aug 19 04:14 .
drwxrwxrwt 95 root wheel 3230 Aug 19 04:06 ..
drwxr-xr-x 16 eddie wheel 544 Aug 19 04:14 .git
-rw-r--r-- 1 eddie wheel 0 Aug 19 04:14 cat1.html
-rw-r--r-- 1 eddie wheel 0 Aug 19 04:14 cat2.html
drwxr-xr-x 3 eddie wheel 102 Aug 17 15:06 config
-rw-r--r-- 1 eddie wheel 0 Aug 18 03:27 hello.html
-rw-r--r-- 1 eddie wheel 161 Aug 18 04:24 index.html
-rw-r--r-- 1 eddie wheel 11 Aug 17 14:56 welcome.html
cat1.html
跟 cat2.html
都回來了!
使用 SourceTree 也可以做這件事,點擊上面選單的「Branch」按鈕後會看到這個對話框:
在「New Branch」欄位填上「new_cat」或是任何你喜歡的名字,但 Commit 選擇「Specified commit」,並把原本舊的 cat
分支指向的 Commit 的 SHA-1 值 b174a5a
填上去,按下「Create Branch」後:
原本被砍掉的 cat
分支,就以 new_cat
的姿態轉生復活了!
我沒把剛剛刪掉的那個 cat 分支的 SHA-1 記下來怎麼辦?查得到嗎?
還是可以的,你可以從 git reflog
指令去翻翻看,Reflog 預設會保留 30 天,所以 30 天內應該都還找得到。Reflog 的使用方式,可參閱「【狀況題】不小心使用 hard 模式 Reset 了某個 Commit,救得回來嗎?」章節介紹。
【觀念】其實所謂的「合併分支」,合併的並不是「分支」…
如果你對 Git 的分支的觀念是正確的,你應該可以猜到知道下面這個指令在做什麼:
$ git merge b174a5a
Updating e12d8ef..b174a5a
Fast-forward
cat1.html | 0
cat2.html | 0
2 files changed, 0 insertions(+), 0 deletions(-)
create mode 100644 cat1.html
create mode 100644 cat2.html
咦?這訊息不是在合併分支的時候跳出來的訊息嗎?是的,所謂的「合併分支」,其實是合併「分支指向的那個 Commit」。分支只是一張貼紙,它是沒辦法被合併的,只是我們會用「合併分支」這個說法,畢竟它比較「合併 Commit」來得容易想像。
重要觀念!
分支只是一個指向某個 Commit 的指標。
Comments