Why did git set us on (no branch)?
This morning we pulled from our repo, and git put us on (no branch).
I don't understand this, why did this happen? And how to 开发者_如何学Cget out of it without losing our changes?
"Not currently on any branch" means you have a detached head, i.e. your HEAD pointer is directly referencing a commit instead of symbolically pointing at the name of a branch.
You can get into this situation by checking out a commit by SHA1, or when you’re in the middle of a rebase, or when a merge fails. It’s hard to say what you may have done to get into this situation by accident.
It’s said that you may lose your changes when you switch from a detached HEAD to some branch, but the reflog will always keep track of where your HEAD moved. In fact, Git 1.7.5 will warn you when switching from a detached HEAD will lose commits. The only time you can really lose work is when you have uncommitted changes, which you may want to commit or stash.
A simple way to see what happened is git reflog
or git log -g --decorate
for a more verbose listing. The --decorate
option will label every SHA1 with the names of all the branches that point at it. If the SHA1 of your current HEAD is exactly the same as master, then you don’t have to do anything but git checkout master
to get back on track. Otherwise, see if the SHA1 is pointed to by some other branch. If not, you may wish to create a branch to hang on to it.
Another good command is git branch -av
, which will similarly list all branches and what they point to, so you can see what your (no branch)
is really supposed to be.
It is hard to tell without more details.
git pull
fetches changes from the remote repository and then does a merge. It can be configured to do a rebase instead of a merge (either with by doing git pull --rebase
, or by configuring a true value for branch.<branch_name>.rebase
for the branch into which you are pulling).
If you started out on a branch, any merge-type pull will always leave you on that branch. On the other hand, the rebase command always works by using a temporarily detached HEAD (aka “no branch”). If you were left in this state during a rebase-type pull, then it is because the rebase portion of the pull encountered conflicts and it is waiting for you to resolve them and use rebase --continue
(or --skip
, or --abort
).
By default, the reflog stores every update that is made to HEAD (there can also be one for each branch). You can view the reflog with git reflog show
(or git log -g
for a more verbose view). It might help you determine how you got into this state.
If you are in the middle of a rebase (you have a .git/rebase-apply
directory), then it probably stopped to let you resolve some conflict(s). Use git status
to check for “unmerged” entries. Any such entries should have conflict markers embedded in the files (assuming that they are plain text files). You should edit them to resolve the conflict(s) and them mark them as merged by running git add
on them. Then run git rebase --continue
to continue with the rebase. You may run into more conflicts that should be handled in a similar way (edit, add, continue). If you decide that you no longer need a particular commit, you can skip it with git rebase --skip
. You can abort the whole rebase with git rebase --abort
. All of these rebase commands are listed in the error message when a rebase stops due to any conflict. Once all the pending commits have been applied (or skipped), your original branch will be updated with the final new commit and your HEAD will be reattached to it (if you abort, your HEAD will be reattached without updating the branch).
If your detached HEAD is not due to conflicts incurred in the middle of a rebase, then your HEAD was detached at some point prior to the pull. You will need to evaluate the current state of the tree to decide what you want to do. You might use git show-branch --current --all
or git log --graph --oneline --decorate --all
or a graphical tool like gitk
to find out how your current (detached) HEAD relates to your other branches. If you decide that you want to keep the contents of your HEAD, then you can you can make a new branch for them with git branch new_branch_name
. If you want to overwrite an existing branch, then use git branch --force existing_branch_name
. Then use git checkout branch_name
to reattach your repository's HEAD to a branch.
Note that, in case of a "git pull --rebase
" run while the HEAD
is detached, Git tried to find the upstream branch of the detached HEAD
(which by definition does not exist) and emitted unnecessary error messages.
This is no longer the case with Git1.8.0.1 (26th November 2012)
See this commit.
精彩评论