先說HEAD
HEAD是一個頭指針,通常情況下指向不同的分支,每個分支對應一個commit(准確的說,每個分支對應多個commit,但是只有一個頂層的commit,而commit之間是簡單的線性關系。)
git checkout 其實是修改HEAD文件的內容,讓它指向不同的分支。
下面是一個一般的情況:
HEAD (refers to branch 'master')
|
v
a---b---c branch 'master' (refers to commit 'c')
既然checkout是修改HEAD,所以可以出現下面的情況:
HEAD (refers to commit 'b')
|
v
a---b---c branch 'master' (refers to commit 'c')
HEAD指向b,用git branch看看有幾個分支:
×HEAD detached from b
master
發現有兩個分支,可是我們沒有創建除了master以外的任何分支啊~
可以把HEAD detached from b理解為一個臨時的分支,並且這時候HEAD指針是游離普通分支之外的。
在這個臨時分支上可以進行git的一切操作:add commit 等等,像這樣:
HEAD (refers to commit 'f')
|
v
e---f
/
a---b---c branch 'master' (refers to commit 'c')
假如遠程庫中有一個master分支,一個用來開發的develop分支,這時候如果我們要向遠程庫推送,會發現無法推送。
因為HEAD不知道要把內容推送到哪個遠程分支上去。
那么問題來了,怎么把修改的內容提交到遠程庫呢?
由於本地沒有develop分支,所以需要先這樣:
git fetch origin develop:develop
在本地創建一個develop分支,並且把它和遠程develop關聯起來。現在再看看本地有哪些分支:
git branch
×develop
master
剛才的HEAD detached from b分支消失了! 在這個分支下修改的內容也不見了!
沒關系,進行下一步。
git reflog show HEAD@{now} -10
這個命令會把HEAD指針所有的動作顯示出來。從中可以清楚的看到,在指針中提交對應的commit id
找到需要恢復的commit ,記下前面的commit id
git branch temp efa64f5
新建一個名字叫temp的分支,用這個分支代替之前的臨時分支並且擁有想要恢復的commit,現在切換到temp下會發現一切都回來了
但是還是不能推送啊。原因是temp是我們本地的分支,遠程庫中並沒有這個分支。
git checkout develop
切換到從遠程庫拉取到的develop分支
git merge temp
將temp分支合並到develop分支上,有沖突就解決沖突。
最后:
git push origin develop
OK,推送到遠程庫。