本章介绍一下Git HEAD detached及其对应的解决办法。

1. 什么是HEAD

Git中的HEAD可以理解为一个指针,我们可以在命令行中输入cat .git/HEAD查看当前HEAD指向哪,一般它指向当前工作目录所在分支的最新提交:

git-head-show

当使用git checkout <branch_name>切换分支时,HEAD会移动到指定分支:

git-head-checkout

但是如果使用的是git checkout <commit-id>,即切换到指定的某一次提交,HEAD就会处于detached(游离)状态。

git-head-detached

2. HEAD游离状态的利弊

HEAD处于游离状态时,我们可以很方便地在历史版本之间互相切换。比如需要回到某次提交,直接checkout对应的commit-id或者tag名即可。

它的弊端就是: 它在这个基础上的提交会新开一个匿名分支

git-head-commit

也就是说我们的提交是无法可见保存的,一旦切到别的分支,游离状态以后的提交就不可追溯了。

git-head-track

解决办法就是新建一个分支保存游离状态后的提交:

git-head-branch

3. 具体解决操作

1) 查看当前分支状况

$ git status
HEAD detached at e8c14b2
nothing to commit, working directory clean
$ git branch -v
* (HEAD detached at e8c14b2) e8c14b2 add module.py
  master                     d4d8f8a [ahead 2] Resolved conflict
  topic/wip                  d4d8f8a Resolved conflict
  wchar_support              954bdfd add new function: count_len(obj)

2) 新建一个temp分支,把当前提交的代码放到整个分支

$ git branch temp

$ git checkout temp
Switched to branch 'temp'

$ git status
On branch temp
nothing to commit, working directory clean

3) checkout要回到的那个分支

这里我们要回到master分支:

$ git checkout master
Switched to branch 'master'
Your branch is ahead of 'origin/master' by 2 commits.
  (use "git push" to publish your local commits)

4) 然后merge刚才创建的临时分支

通过merge操作把临时分支上的提交合并到master分支上来:

$ git merge temp
Merge made by the 'recursive' strategy.
 detached_head.txt | 1 +
 1 file changed, 1 insertion(+)
 create mode 100644 detached_head.txt

5) 查看合并后的结果,有冲突就解决

$ git status
On branch master
Your branch is ahead of 'origin/master' by 4 commits.
  (use "git push" to publish your local commits)
nothing to commit, working directory clean

6) 合并OK,就提交到远程

$ git push origin master
Username for 'https://github.com': ivanzz1001
Password for 'https://ivanzz1001@github.com':
To https://github.com/ivanzz1001/sample.git
 ! [rejected]        master -> master (fetch first)
error: failed to push some refs to 'https://github.com/ivanzz1001/sample.git'
hint: Updates were rejected because the remote contains work that you do
hint: not have locally. This is usually caused by another repository pushing
hint: to the same ref. You may want to first integrate the remote changes
hint: (e.g., 'git pull ...') before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for details.

7) 删除刚才创建的临时分支

$ git branch -d temp
Deleted branch temp (was 5266593).



[参看]

  1. Git HEAD detached