It's not clear from your question whether you made any new commits.
There are three things to do, depending on your situation:
- use
git checkout -b newbranch
and then rebase or merge
- just
git checkout master
, if you can (but see below)
- use
git stash
, then git checkout master
, then git stash apply
and eventually git stash drop
Which one to use depends mainly on whether you have already made new commits.
Necessary background information
When you're working within your own local repository, editing files, and getting ready to make new commits, there are really just three things that matter:
- Your current commit, a.k.a.,
HEAD
.
- Your current work-tree. The work-tree is where you do your work: edit files to modify them, create new files, or
git rm
some existing file both from the work-tree and ...
- Your current index. The index is where you build the next commit: every time you run
git add
, you copy a file from the work-tree into the index. This either updates the file that was already in it, or adds it as a new file. When you run git rm
, you remove the file from the index.
If you made commits
If you made new commits, this created a new branch, and the "detached HEAD" just means that your new branch has no name.
Eventually, when you decide you have things ready, you run git commit
. This makes a new commit, by turning the index—where you have added, updated, and/or removed some files—into a saved work-tree snapshot that you can look at again later as needed. It writes your log message into the commit, writes the current commit as the new commit's "parent", and then writes the new commit's ID—the big ugly SHA-1, deadc0decafe...
or whatever, into the branch.
In the ordinary, "on a branch" case, the place the new commit's ID goes is the branch name.
In the "detached HEAD" case, though, there is no branch name, so the new commit's ID goes directly into HEAD
.
We can draw this the same way we draw any set of commits on branches:
...--o--o--o--o--o <-- master
\
o <-- HEAD
This is what you get if you commit when in "detached HEAD" mode: your new commit is on a new branch. It just has no name. If you made multiple commits, they string together as usual:
...--o--o--o--o--o <-- master
\
o--o--o <-- HEAD
If you are in this situation, all you have to do is give your branch a name. Simply run git checkout -b newbranch
to create a new branch named newbranch
(put in any name you like), and now all the commits you've made are on the new branch.
Once you're on a normal, named branch, you can use all the usual means to bring these commits into the main line, such as using git rebase
or git merge
.
If you haven't made commits
If you have not made any new commits, you may be in extra-good luck. You may be able to just git checkout master
. Note: do not use --force
.
The same rule applies as before, that there are three things that matter: your current (HEAD
) commit, your current work-tree, and your current index. But now we get into an interesting part of Git: How git checkout
carries changes around. If you try to git checkout master
, what Git will do is compare the current commit—the detached HEAD
—to the tip commit on master
.
Let's draw that original chain of commits again but mark HEAD
with *
, and the tip commit on master with X
:
...--o--*--o--o--X <-- master
Ask yourself this: if you were Git, and you were trying to move from HEAD
to the tip of master
, and knowing that as Git, you can very easily tell which files are the same, and which are different, in any two commits ... what would be the fastest, easiest, laziest way move from *
to X
?
Remember that the index records what would go into the next commit, so it started out holding what's in *
(because you checked that out earlier). The work-tree also started out holding what's in *
. If none of those have changed, then the fastest-easiest-laziest way to move from *
to X
is: only replace, in the index and work-tree, the files that are different.
The tricky bit here is that even—or maybe I should say, especially—if you have made changes in the index and/or work-tree, Git still does the same thing. It tries to leave all your modifications in place. It can do this if (and only if) the files you've changed are the same in the current commit *
and the new target X
. It only needs to swap out the "changed-from-*
-to-X
" files (in both index and work-tree), so it leaves everything else alone. (See also Git - checkout another branch when there are uncommitted changes on the current branch.)
In this particular case, running git checkout master
reattaches your HEAD, making your current commit be the tip of master
, and carries all your changes along with you—and now you can git commit
, or keep editing, or whatever.
What if git checkout
complains?
If git checkout master
says that it can't do that—that it would overwrite your files—then you have only one sensible choice, which is to commit them. However, you can use a short-cut commit, via the git stash
command.
What git stash save
does is actually to make some commits, one for the index, and one for the work-tree.1 But they're commits that are on no branch. Having made those commits, the stash
command cleans up the index and work-tree so that they match the HEAD
commit. You can now git checkout
some other commit—such as the tip of master
—and then apply the saved stash:
git stash apply
Internally, applying the saved stash is a bit complicated, because it's more than one commit. For this particular purpose, though, you can ignore all of that: applying simply "smooshes up" the commits and does its best to make the same changes to the new current commit, i.e., the tip of master
.
The apply step uses the internal merge code, just like git rebase
does when rebase is copying commits. This means you may end up having to resolve merge conflicts. If you want to put this off, you can abort the attempt to use the stash, and because the apply has not dropped the stash, it's still in there, and you can apply it later, or turn it into its own branch.
If the apply goes well, though—usually it does—it's now safe to git stash drop
the stash. If you run git stash pop
, that combines the apply step and the drop step. I recommend keeping them separate in case you change your mind—once dropped, the applied stash is very difficult to recover.2 Not everyone is as cautious as I am, of course, and git stash pop
is pretty safe: it specifically doesn't drop the stash if it does not apply properly, for instance.
1Normally, it's just these two commits, but with -u
or -a
, it makes three commits. These commits have the form of a merge, so that it takes only one Git reference to record them, but they are not a normal merge in any sense.
2Since they are commits, they are recoverable for a little while—but since stash commits are on no branch, none of the usual means works at all, and the usual 30-day guarantee does not function at all.