Git 斷頭了!怎麼辦?

莫急~莫慌~莫害怕

wyatthoho
5 min readSep 23, 2021

前情提要

某天,我的 git graph 長這樣:

$ git log --oneline --graph --decorate
* d1017cd (HEAD -> master, origin/master) Delete content in temp.txt
* 7d729ae Add content to temp.txt
* 0ac097d Add temp.txt

原本我在 master 分支上的第三個 commit,我想回到第二個 commit 的時間點拿過去的東西,因此我執行了,

$ git checkout 7d729ae

當我拿完東西,我回到原本的第三個 commit,

$ git checkout d1017cd

接著我開心地繼續寫新東西,寫完,commit!

$ git commit -m "Add temp.py"

commit 完,push!

git push

燈冷~ push 失敗!還出現怪怪訊息

fatal: You are not currently on a branch.
To push the history leading to the current (detached HEAD)
state now, use
git push origin HEAD:<name-of-remote-branch>

討論

原因是,一旦 HEAD 離開分支尾端回到先前狀態時,git 會預設 user 打算離開目前分支,並開一條新的分支從舊的 commit 點分岔出來繼續開發。但是偏偏 git 並不會自己定義新的分支,導致 HEAD 沒有指向任何分支的窘境。這就叫 detached HEAD,斷頭啦!就算重新 checkout 回最後一個 commit,斷頭的狀況還是存在。

解決方法(一)

一旦回到舊時間點拿完東西,在產生 detached HEAD 之後,記得要隨即 chechout 回原本分支

$ git checkout master

如此一來斷頭狀態就解除了,可以再繼續開發下去。

解決方法(二)

若忘記 checkout 回原本分支就繼續往下走,狀態會變成:

$ git log --oneline --graph --decorate
* d9837b5 (HEAD) Add temp.py
* d1017cd (origin/master, master) Delete content in temp.txt
* 7d729ae Add content to temp.txt
* 0ac097d Add temp.txt

觀察 HEAD 指向的地方,在原本 master 的位置分岔出一條未定義的分支。要讓這條分支能落在 master 上,首先,給不小心岔出來的路徑配上一個正式分支,我暫且把它命名為 oops,

$ git branch oops d9837b5

再走到 oops 的位置,

$ git checkout oops

執行 rebase 指令,

$ git rebase master

rebase 指令能夠把 oops 接到 master 之後,如下:

$ git log --oneline --graph --decorate
* d9837b5 (HEAD -> oops) Add temp.py
* d1017cd (origin/master, master) Delete content in temp.txt
* 7d729ae Add content to temp.txt
* 0ac097d Add temp.txt

接著回到 master,

$ git checkout master

執行 merge 指令,

$ git merge oops

merge 指令能讓 master 走到跟新分支一樣的位置,如下:

$ git log --oneline --graph --decorate
* d9837b5 (HEAD -> master, oops) Add temp.py
* d1017cd (origin/master) Delete content in temp.txt
* 7d729ae Add content to temp.txt
* 0ac097d Add temp.txt

如此一來,斷頭之後的工作都成功轉移到 master 上。那麼分支 oops 已經不需要了,把它刪了吧~

$ git branch -d oops

此時狀態看起來乾乾淨淨,就好像什麼事也沒發生一樣!

$ git log --oneline --graph --decorate
* d9837b5 (HEAD -> master) Add temp.py
* d1017cd (origin/master) Delete content in temp.txt
* 7d729ae Add content to temp.txt
* 0ac097d Add temp.txt

趕緊 push 到遠端,

$ git push

大功告成!

$ git log --oneline --graph --decorate
* d9837b5 (HEAD -> master, origin/master) Add temp.py
* d1017cd Delete content in temp.txt
* 7d729ae Add content to temp.txt
* 0ac097d Add temp.txt

--

--

wyatthoho

在混亂的宇宙裡,我透過寫程式來認識秩序並建立安定。wyatthoho@gmail.com