Detached head git как исправить

Detached head means you are no longer on a branch, you have checked out a single commit in the history (in this case the commit previous to HEAD, i.e. HEAD^).

If you want to delete your changes associated with the detached HEAD

You only need to checkout the branch you were on, e.g.

git checkout master

Next time you have changed a file and want to restore it to the state it is in the index, don’t delete the file first, just do

git checkout -- path/to/foo

This will restore the file foo to the state it is in the index.

If you want to keep your changes associated with the detached HEAD

  1. Run git branch tmp – this will save your changes in a new branch called tmp.
  2. Run git checkout master
  3. If you would like to incorporate the changes you made into master, run git merge tmp from the master branch. You should be on the master branch after running git checkout master.

Community's user avatar

answered Apr 19, 2012 at 13:32

ralphtheninja's user avatar

ralphtheninjaralphtheninja

126k20 gold badges111 silver badges121 bronze badges

34

If you have changed files you don’t want to lose, you can push them. I have committed them in the detached mode and after that you can move to a temporary branch to integrate later in master.

git commit -m "....."
git branch my-temporary-work
git checkout master
git merge my-temporary-work

Extracted from:

What to do with commit made in a detached head

Community's user avatar

answered Dec 9, 2013 at 20:05

Toni Gamez's user avatar

Toni GamezToni Gamez

6,7891 gold badge22 silver badges18 bronze badges

9

A solution with no temporary branch or merge commit

How to exit (“fix”) detached HEAD state when you already changed something in this mode and, optionally, want to save your changes:

  1. Commit changes you want to keep. If you want to take over any of the changes you made in detached HEAD state, commit them. For example:

    git commit -a -m "your commit message"
    
  2. Discard changes you do not want to keep. The hard reset will discard any uncommitted changes that you made in detached HEAD state:

    git reset --hard
    

    (Without this, step 3 would fail, complaining about modified uncommitted files in the detached HEAD.)

  3. Check out your branch. Exit detached HEAD state by checking out the branch you worked on before, for example:

    git checkout master
    
  4. Take over your commits. You can now take over the commits you made in detached HEAD state by cherry-picking, as shown in my answer to another question.

    git reflog
    git cherry-pick <hash1> <hash2> <hash3> ...
    

answered Jun 11, 2013 at 13:23

tanius's user avatar

taniustanius

13.1k3 gold badges49 silver badges61 bronze badges

3

Detached head means:

  1. You are no longer on a branch,
  2. You have checked out a single commit in the history

If you have no changes: you can switch to master by applying the following command

  git checkout master

If you have changes that you want to keep:

In case of a detached HEAD, commits work like normal, except no named branch gets updated. To get master branch updated with your committed changes, make a temporary branch where you are (this way the temporary branch will have all the committed changes you have made in the detached HEAD), then switch to the master branch and merge the temporary branch with the master.

git branch  temp
git checkout master
git merge temp

Peter Mortensen's user avatar

answered Aug 29, 2016 at 0:39

Razan Paul's user avatar

Razan PaulRazan Paul

13.6k3 gold badges69 silver badges61 bronze badges

2

HEAD is a pointer, and it points — directly or indirectly — to a particular commit:

Attached  HEAD means that it is attached to some branch (i.e. it points to a branch).
Detached HEAD means that it is not attached to any branch, i.e. it points directly to some commit.

enter image description here

In other words:

  • If it points to a commit directly, the HEAD is detached.
  • If it points to a commit indirectly, (i.e. it points to a branch, which in turn points to a commit), the HEAD is attached.

To better understand situations with attached / detached HEAD, let’s show the steps leading to the quadruplet of pictures above.

We begin with the same state of the repository (pictures in all quadrants are the same):

enter image description here


Now we want to perform git checkout — with different targets in the individual pictures (commands on top of them are dimmed to emphasize that we are only going to apply those commands):

enter image description here


This is the situation after performing those commands:

enter image description here

As you can see, the HEAD points to the target of the git checkout command — to a branch (first 3 images of the quadruplet), or (directly) to a commit (the last image of the quadruplet).

The content of the working directory is changed, too, to be in accordance with the appropriate commit (snapshot), i.e. with the commit pointed (directly or indirectly) by the HEAD.


So now we are in the same situation as in the start of this answer:

enter image description here

answered Sep 27, 2019 at 23:29

MarianD's user avatar

MarianDMarianD

12.7k12 gold badges41 silver badges54 bronze badges

7

If you made changes and then realized that you are on a detached head, you can do: stash -> checkout master -> stash pop:

git stash
git checkout master   # Fix the detached head state
git stash pop         # Or for extra safety use 'stash apply' then later 
                      #   after fixing everything do 'stash drop'

You will have your uncommited changes and normal “attached” HEAD, like nothing happened.

answered Jan 1, 2015 at 22:40

mojuba's user avatar

mojubamojuba

11.8k9 gold badges51 silver badges71 bronze badges

4

Here’s what I just did after I realized I was on a detached head and had already made some changes.

I committed the changes.

$ git commit -m "..."
[detached HEAD 1fe56ad] ...

I remembered the hash (1fe56ad) of the commit. Then I checked out the branch I should have been on.

$ git checkout master
Switched to branch 'master'

Finally I applied the changes of the commit to the branch.

$ git cherry-pick 1fe56ad
[master 0b05f1e] ...

I think this is a bit easier than creating a temporary branch.

answered Aug 2, 2014 at 23:33

Philippe Gerber's user avatar

Philippe GerberPhilippe Gerber

17.4k6 gold badges44 silver badges40 bronze badges

6

When you check out a specific commit in git, you end up in a detached head state…that is, your working copy no longer reflects the state of a named reference (like “master”). This is useful for examining the past state of the repository, but not what you want if you’re actually trying to revert changes.

If you have made changes to a particular file and you simply want to discard them, you can use the checkout command like this:

git checkout myfile

This will discard any uncommitted changes and revert the file to whatever state it has in the head of your current branch. If you want to discard changes that you have already committed, you may want to use the reset command. For example, this will reset the repository to the state of the previous commit, discarding any subsequent changes:

git reset --hard HEAD^

However, if you are sharing the repository with other people, a git reset can be disruptive (because it erases a portion of the repository history). If you have already shared changes with other people, you generally want to look at git revert instead, which generates an “anticommit” — that is, it creates a new commit that “undoes” the changes in question.

The Git Book has more details.

answered Apr 19, 2012 at 13:32

larsks's user avatar

larskslarsks

267k40 gold badges382 silver badges386 bronze badges

1

Since “detached head state” has you on a temp branch, just use git checkout - which puts you on the last branch you were on.

yyny's user avatar

yyny

1,58317 silver badges20 bronze badges

answered Nov 20, 2015 at 19:30

Mike's user avatar

MikeMike

1,8642 gold badges24 silver badges42 bronze badges

3

you probably did git reset --hard origin/your-branch.

Try to just git checkout your-branch

answered Apr 1, 2020 at 11:00

Johnny Cage's user avatar

Johnny CageJohnny Cage

5,2662 gold badges11 silver badges7 bronze badges

0

Being in “detached head” means that HEAD refers to a specific unnamed commit (as opposite to a named branch) (cf: https://git-scm.com/docs/git-checkout section Detached head).
In reality, this means that you have checked out a commit but there is no branch name associated with it.

You may choose to only create a new branch associated with your commit by

git branch new-branch-name.

This allows you to save your current state in a new branch named new-branch-name and not be in a detached head state anymore.

Or if you would like to come back to the previous state, you need to select the branch that was selected before by

git checkout @{-1}

answered Feb 15, 2019 at 15:16

Pat. ANDRIA's user avatar

Pat. ANDRIAPat. ANDRIA

2,3221 gold badge12 silver badges27 bronze badges

To further clarify @Philippe Gerber’s answer, here it is:

git cherry-pick

Before cherry-pick, a git checkout master is necessary in this case. Furthermore, it is only needed with a commit in detached head.

answered Dec 6, 2017 at 13:39

Timo's user avatar

TimoTimo

2,8563 gold badges29 silver badges27 bronze badges

Addendum

If the branch to which you wish to return was the last checkout that you had made, you can simply use checkout @{-1}. This will take you back to your previous checkout.

Further, you can alias this command with, for example, git global --config alias.prev so that you just need to type git prev to toggle back to the previous checkout.

answered Jan 22, 2016 at 11:09

David Brower's user avatar

David BrowerDavid Brower

2,8482 gold badges25 silver badges30 bronze badges

1

Detached head means you have not checked out your branch properly or you have just checked out a single commit.

If you encounter such an issue then first stash your local changes so that you won’t lose your changes.

After that… checkout your desired branch using the command:

Let’s say you want branch MyOriginalBranch:

git checkout -b someName origin/MyOriginalBranch

Leniel Maccaferri's user avatar

answered Jan 13, 2020 at 6:35

Dhirendra Gautam's user avatar

To add to @ralphtheninja’s answer. If you get this message after using git checkout master:

Please commit your changes or stash them before you switch branches.
Aborting

Then you can simply force the checkout using the -f flag as follows:

git checkout -f master

Apparently this will result in losing all the changes made in the detached mode. So be careful when using it.

answered Jan 25, 2022 at 20:12

Souhaib's user avatar

SouhaibSouhaib

1191 silver badge6 bronze badges

Git told me how to do it.

if you typed:

git checkout <some-commit_number>

Save the status

git add .
git commit -m "some message"

Then:

 git push origin HEAD:<name-of-remote-branch>

answered Jan 31, 2019 at 19:30

Sterling Diaz's user avatar

Sterling DiazSterling Diaz

3,7612 gold badges31 silver badges35 bronze badges

1

This approach will potentially discard part of the commit history, but it is easier in case the merge of the old master branch and the current status is tricky, or you simply do not mind losing part of the commit history.

To simply keep things as currently are, without merging, turning the current detached HEAD into the master branch:

  1. Manually back up the repository, in case things go unexpectedly wrong.
  2. Commit the last changes you would like to keep.
  3. Create a temporary branch (let’s name it detached-head) that will contain the files in their current status:
git checkout -b detached-head
  1. (a) Delete the master branch if you do not need to keep it
git branch -D master
  1. (b) OR rename if you want to keep it
git branch -M master old-master
  1. Rename the temporary branch as the new master branch
git branch -M detached-head master

Credit: adapted from this Medium article by Gary Lai.

answered Sep 29, 2020 at 16:37

alexhg's user avatar

alexhgalexhg

6707 silver badges11 bronze badges

0

I was in a similar situation.
For some reason I ended up with a detached head – I had made commits on the same path as the branch I thought I was on – eg HEAD was a child of the branch tag but for some reason the branch tag had stayed back at a historic commit… possibly because I had pushed??

It wouldn’t let me push because I wasn’t considered to be on the branch I thought I was on.

I didn’t want to change any of my history or do any cherry picking and I’d just spent about 8 weeks working on the branch so reset --hard was making me a bit nervous!

The solution was just to do the following:

git branch -f myStuckBranch HEAD
git checkout myStuckBranch

You need to do the checkout even though HEAD and myStuckBranch are now pointing at the same thing because you are still considered to be in the detached head state (not on a branch)

I’m not an expert with git (having mostly used mercurial which would never create this weird situation) but my understanding of this command is that it just says
“change myStuckBranch to point at HEAD”.

I routinely find myself using this command to merge in changes from master after fetching without having to swap my working directory – otherwise it tries to use the old (uninteresting) version of master:

git fetch
git branch -f master origin/master  -- err yeah don't just ignore what's been going on remotely - eg point my master at the real master
git merge master -- merge the changes into my local branch

It’s a bit annoying to have to manually have to do that all the time but still better than having to change your working directory just to update another branch in order to merge in changes from it.

answered Mar 31, 2021 at 14:41

JonnyRaa's user avatar

JonnyRaaJonnyRaa

7,3295 gold badges44 silver badges49 bronze badges

4

Normally HEAD points to a branch. When it is not pointing to a branch instead when it points to a commit hash like 69e51 it means you have a detached HEAD. You need to point it two a branch to fix the issue. You can do two things to fix it.

  1. git checkout other_branch // Not possible when you need the code in that commit hash
  2. create a new branch and point the commit hash to the newly created branch.

HEAD must point to a branch, not a commit hash is the golden rule.

answered Jan 5, 2020 at 7:39

Krishnadas PC's user avatar

Krishnadas PCKrishnadas PC

5,8012 gold badges53 silver badges50 bronze badges

1

This was a confusing thing to me when I started to work with git and later I figure out why this is happening and what is the best way to deal with such a situation.

The root cause for such occurrence is that normally git HEAD is always pointing to some branch and when you try to point the HEAD to some specific commit, you put HEAD into a detached HEAD state.

When HEAD is attached state –

cat .git/HEAD     # output--> ref: refs/heads/master or ref: refs/heads/main

When HEAD is detached state –

cat .git/HEAD     # output--> b96660a90cad75867453ebe1b8d11754bbb68b0e <commit hash>

Solution –

git stash           # Temporarily shelves (or stashes) changes
git branch          # Find your default branch
git switch master   # Point HEAD to master or main branch
git stash pop       # Apply all the changes you had previously

answered Sep 24, 2022 at 0:44

Aravinda Meewalaarachchi's user avatar

Git : You are not currently on a branch.

Time to time Git shows :

To push the history leading to the current (detached HEAD)
state now, use

git push origin HEAD:<name-of-remote-branch>

It means :

  • ” HEAD have no branch “

To fix that run 2 commands :

  1. git branch -f {{your_working_branch}} HEAD — set branch to your head
  2. git checkout {{your_working_branch}} — checkout==switch branch

answered Oct 11, 2022 at 3:21

Bruno's user avatar

BrunoBruno

6,3755 gold badges40 silver badges47 bronze badges

I wanted to keep my changes so, I just fix this doing…

git add .
git commit -m "Title" -m "Description"
(so i have a commit now example: 123abc)
git checkout YOURCURRENTBRANCH
git merge 123abc
git push TOYOURCURRENTBRANCH

that work for me

Paul Rooney's user avatar

Paul Rooney

20.6k9 gold badges39 silver badges61 bronze badges

answered Dec 4, 2018 at 22:11

CRLZXO's user avatar

When you’re in a detached head situation and created new files, first make sure that these new files are added to the index, for example with:

git add .

But if you’ve only changed or deleted existing files, you can add (-a) and commit with a message (-m) at the the same time via:

git commit -a -m "my adjustment message"

Then you can simply create a new branch with your current state with:

git checkout -b new_branch_name

You’ll have a new branch and all your adjustments will be there in that new branch. You can then continue to push to the remote and/or checkout/pull/merge as you please.

answered Mar 21, 2019 at 22:15

DZet's user avatar

DZetDZet

5393 silver badges10 bronze badges

Realizing I had a detached head without knowing how I managed to get it (like three commits away), I also found out that trying to merge, rebase or cherry-pick triggered hundreds of merge-conflicts, so I took a different approach:

  1. (Assuming everything is committed (working tree is “clean”))

  2. Save my commit messages: git log > /tmp/log

  3. Save my working tree: mkdir /tmp/backup && cp -a all_my files_and_directories /tmp/backup

  4. Revert to master: git checkout master

  5. Remove all the working files and directories: rm ...

  6. Use the backup: cp -a /tmp/backup/. .

  7. git add and git commit using messages from saved /tmp/log, maybe repeating it with different sub-sets of files…

The disadvantage is that you loose your commit history if one file was changed multiple times since master, but in the end I had a clean master.

answered Jul 27, 2020 at 12:21

U. Windl's user avatar

U. WindlU. Windl

3,33325 silver badges53 bronze badges

The detached HEAD means that you are currently not on any branch. If you want to KEEP your current changes and simply create a new branch, this is what you do:

git commit -m "your commit message"
git checkout -b new_branch

Afterwards, you potentially want to merge this new branch with other branches. Always helpful is the git “a dog” command:

git log --all --decorate --oneline --graph

answered Apr 21, 2020 at 10:00

gebbissimo's user avatar

gebbissimogebbissimo

2,0172 gold badges24 silver badges32 bronze badges

If you hate head and wanna go back to main instead:

git checkout main

If you love head but just wish main tracked it:

git checkout -B main HEAD

(This works with any branch name, not just main, and for any commit pointer, not just HEAD.)

(If you have uncommitted changes that you want to commit, commit them first.)

answered Feb 11 at 21:57

Sandra's user avatar

SandraSandra

2293 silver badges7 bronze badges

This works for me, It will assign a new branch for detached head :

git checkout new_branch_name detached_head_garbage_name

lenooh's user avatar

lenooh

10.3k5 gold badges58 silver badges49 bronze badges

answered Mar 17, 2020 at 17:06

Alok Gupta's user avatar

Alok GuptaAlok Gupta

1,78821 silver badges21 bronze badges

1

With git rebase you can move your HEAD to the desired commit

Suppose you have your branch in a detached state, like this:

* bfcb8f9 Commit 4
* 540a123 Commit 3
* 4356d64 Commit 2
| * fecb8d2 Commit 2
|/
| * 8012f45 Commit 2x
|/
| * 6676d15 (HEAD -> master) Commit 2 --amend
|/
* 1818f91 Commit 1

The detached head was created by rebasing by mistake, pointing to a detached commit, which was created previously due a git commit –amend command.

If you want to move your HEAD ref to the most recent commit, apply a rebase with the desired HASH commit you want to point to. In this example, the hash is of the most recent commit:

git rebase bfcb8f9

and this will leave your branch with its HEAD poiting to the desired commit (the most recent in this case):

* bfcb8f9 (HEAD -> master) Commit 4
* 540a123 Commit 3
* 4356d64 Commit 2 --amend
| * fecb8d2 Commit 2
|/
| * 8012f45 Commit 2x
|/
| * 6676d15 Commit 2
|/
* 1818f91 Commit 1

answered Jul 12, 2021 at 16:48

Edgar Alejandro Ramirez's user avatar

git pull origin master

worked for me. It was just about giving remote and branch name explicitly.

answered May 14, 2014 at 14:14

Amjedonline's user avatar

1

I came here because I had the HEAD detached at... message.

In my case it wasn’t due to some local changes because, on that system I never do any changes.

The reason for my message was: I accidently checked out origin/myBranch instead of myBranch.

So when checking out myBranch everything returned to normal.

answered Apr 21 at 18:44

Skeeve's user avatar

SkeeveSkeeve

7,0082 gold badges16 silver badges26 bronze badges

“Git detached head” is a weird error message to receive…

The following is a guest blog post written by Carlos Schults.

Newcomers to Git often get confused with some of the messages that the VCS tool throws at them. The “You are in ‘detached HEAD’ state” one is certainly one of the weirdest. After coming across this message, most people start furiously Googling “git detached HEAD,” “git detached HEAD fix,” or similar terms, looking for anything that might be of help. If that’s your case, you’ve come to the right place.

Here’s the first thing you should know: you haven’t done anything wrong. Your repo isn’t broken or anything like that. The expression “Detached HEAD” might sound somewhat bizarre, but it’s a perfectly valid repository state in Git. Sure, it’s not the normal state, which would be—you’ve guessed it!—when HEAD is attached. The second thing you need to know is that going back to normal is super easy. If you just want to do that and get on with your day, go to the “How Do I Fix a Detached Head in Git?” section of this post to see how it’s done.

But if you want to know more—and I guess you do—stick around and we’ll help you. What does HEAD mean in Git? What does it mean for it to be attached or detached? These are the kind of questions we’ll answer in this post. By the end of it, you’ll have a better understanding of Git’s fundamentals, and detached HEADs will never trouble you again. Let’s dig in.

Git Detached HEAD: Reproducing the “Problem”

Let’s start with a quick demo showing how to reach the detached HEAD state. We’ll create a repository and add some commits to it:

mkdir git-head-demo
cd git-head-demo
git init
touch file.txt
git add .
git commit -m "Create file"
echo "Hello World!" > file.txt
git commit -a -m "Add line to the file"
echo "Second file" > file2.txt
git add .
git commit -m "Create second file"

With the commands above, we’ve created a new folder with a new repository inside it. Then we created a new empty file and committed that with the message “Create file.” Next, we added a line to that file and committed the change, with the message “Add a line to the file.” Finally, we’ve created another file with one line of text and committed that as well. If you use the git log –oneline command, you’ll see something like this:

Let’s say that, for testing purposes, we need to see how things were at the time of the second commit. How would we do that? As it turns out, we can check out a commit the same way we’d check out branches. Remember, branches are just names for commits. So, based on the example output above, we’d run git checkout 87ec91d. Keep in mind that if you’re following along by executing these commands on your own system, the hash for your commits will be different from those in the example. Use the log command to find it.

After running the command, we get the “You are in ‘detached HEAD’ state[…]” message. Before we go on, make sure you keep this in mind: you get to the detached HEAD state by checking out a commit directly.

What Is a HEAD in Git?

What does HEAD mean in Git? To understand that, we have to take a step back and talk fundamentals.

A Git repository is a collection of objects and references. Objects have relationships with each other, and references point to objects and to other references. The main objects in a Git repository are commits, but other objects include blobs and trees. The most important references in Git are branches, which you can think of as labels you put on a commit.

HEAD is another important type of reference. The purpose of HEAD is to keep track of the current point in a Git repo. In other words, HEAD answers the question, “Where am I right now?”

For instance, when you use the log command, how does Git know which commit it should start displaying results from? HEAD provides the answer. When you create a new commit, its parent is indicated by where HEAD currently points to.

Are you in ‘detached HEAD’ state?

You’ve just seen that HEAD in Git is only the name of a reference that indicates the current point in a repository. So, what does it mean for it to be attached or detached?

Most of the time, HEAD points to a branch name. When you add a new commit, your branch reference is updated to point to it, but HEAD remains the same. When you change branches, HEAD is updated to point to the branch you’ve switched to. All of that means that, in these scenarios, HEAD is synonymous with “the last commit in the current branch.” This is the normal state, in which HEAD is attached to a branch.

A visual representation of our demo repository would look like this:

As you can see, HEAD points to the controller branch, which points to the last commit. Everything looks perfect. After running git checkout 87ec91d, the repo looks like this:

This is the detached HEAD state; HEAD is pointing directly to a commit instead of a branch.

Benefits of a Git Detached HEAD

Are there good reasons for you to be in the detached HEAD state? You bet there are!

As you’ve seen, you detach the HEAD by checking out a commit. That’s already useful by itself since it allows you to go to a previous point in the project’s history. Let’s say you want to check if a given bug already existed last Tuesday. You can use the log command, filtering by date, to start the relevant commit hash. Then you can check out the commit and test the application, either by hand or by running your automated test suite.

What if you could not only take a look at the past, but also change it? That’s what a detached HEAD allows you to do. Let’s review how the detached message starts:

You are in 'detached HEAD' state. You can look around, make experimental changes and commit them, and you can discard any commits you make in this state without impacting any branches by switching back to a branch.

In this state, you can make experimental changes, effectively creating an alternate history. So, let’s create some additional commits in the detached HEAD state and see how our repo looks afterward:

echo "Welcome to the alternate timeline, Morty!" > new-file.txt
git add .
git commit -m "Create new file"
echo "Another line" >> new-file.txt
git commit -a -m "Add a new line to the file"

We now have two additional commits that descend from our second commit. Let’s run git log –oneline and see the result:

This is what the diagram looks like now:

What should you do if you want to keep those changes? And what should you do if you want to discard them? That’s what we’ll see next.

How Do I Fix a Detached HEAD in Git?

You can’t fix what isn’t broken. As I’ve said before, a detached HEAD is a valid state in Git. It’s not a problem. But you may still want to know how to get back to normal, and that depends on why you’re in this situation in the first place.

Scenario #1: I’m Here by Accident

If you’ve reached the detached HEAD state by accident—that is to say, you didn’t mean to check out a commit—going back is easy. Just check out the branch you were in before:

git checkout <branch-name>

If you’re using Git 2.23.0 or newer, you can also use switch instead of checkout:

git switch <branch-name>

Scenario #2: I’ve Made Experimental Changes and I Want to Discard Them

You’ve entered the detached HEAD state and made a few commits. The experiment went nowhere, and you’ll no longer work on it. What do you do? You just do the same as in the previous scenario: go back to your original branch. The changes you made while in the alternate timeline won’t have any impact on your current branch.

Scenario #3: I’ve Made Experimental Changes and I Want to Keep Them

If you want to keep changes made with a detached HEAD, just create a new branch and switch to it. You can create it right after arriving at a detached HEAD or after creating one or more commits. The result is the same. The only restriction is that you should do it before returning to your normal branch.

Let’s do it in our demo repo:

git branch alt-history
git checkout alt-history

Notice how the result of git log –oneline is exactly the same as before (the only difference being the name of the branch indicated in the last commit):

We could just run git branch alt-history, and we’d be all set. That’s the new—and final—version of our diagram:

Getting Rid of the “Git Detached HEAD” Message

Before wrapping up, let’s share a final quick tip. Now that you understand everything about detached HEAD in Git and know that it’s not that big of a deal, seeing that message every time you check out a commit might become tiring. Fortunately, there’s a way to not see the warning anymore. Just run the following command:

git config advice.detached head false

Easy, right? You can also use the –global modifier if you want the change to apply to every repository and not only the current one.

Git Detached HEAD: Less Scary Than It Sounds

A message talking about heads not being attached doesn’t sound like your routine software error message, right? Well, it’s not an error message.

As you’ve seen in this post, a detached HEAD doesn’t mean something is wrong with your repo. Detached HEAD is just a less usual state your repository can be in. Aside from not being an error, it can actually be quite useful, allowing you to run experiments that you can then choose to keep or discard.

Carlos Schults is a .NET software developer with experience in both desktop and web development, and he’s now trying his hand at mobile. He has a passion for writing clean and concise code, and he’s interested in practices that help you improve app health, such as code review, automated testing, and continuous build.

Cover image for The "detached HEAD" state in Git: What it is and how to fix it

A common source of confusion when using Git is not knowing what it all means when you see an output like this:

You are in 'detached HEAD' state. You can look around, make 
experimental changes and commit them, and you can discard any 
commits you make in thisstate without impacting any branches 
by switching back to a branch.

Enter fullscreen mode

Exit fullscreen mode

What does it all mean?

To really understand what is happening, we need to look inside Git.

Git commits are immutable—meaning you can create new ones, but what’s already inside will never be changed. This is how our repository keeps data safe for us. The only way of making changes to the repository is by creating new commits.

Git commits gives us a stable, complete history of the changes to the repository. On top of this stable base, we have a dynamic part: branches. What can be surprising at first is that branches are just labels. They are pointing to one commit. They literally have no other data than the name and its position.

Anything besides that—for example,

  • special meaning of main or master,
  • patterns such as feature/<info>, or <branch-owner>/<description>
    —is just a convention the teams are using. From Git’s point of view, your main or master branch is no different than lorem-ipsum.

Current commit

HEAD is a pointer to the current commit—the place where you are in the repository right now. It is used as:

  • a reference point when you want to see the last changes to your working copy with git diff
  • a commit that will be used as a parent when you create a new commit

Your HEAD is a central piece of the state of your repository.

Normal state

The typical workflow with Git is as follows:

  • you are on some branch,
  • you create new commit, and
  • Git moves your branch to this new commit.

If you limit yourself to checking branches only, you will never leave this state. When you run git status, it tells you what branch you are on:

$ git status
On branch main
Your branch is up to date with 'origin/main'.

nothing to commit, working tree clean

Enter fullscreen mode

Exit fullscreen mode

Detached HEAD

So far, HEAD (current commit) and branch were in a normal, aligned state. Things get complicated when you check out something that is not a branch—for example, when you switch to a commit by its ID:

$ git checkout abc01e7

Enter fullscreen mode

Exit fullscreen mode

where abc01e7 is an ID of any commit in the repository—it can be inside of any of the branches, on top of one of them, or in another place of the repository history.

Because you are not on a branch anymore, the git status changes to:

$ git status
HEAD detached at abc01e7
nothing to commit, working tree clean

Enter fullscreen mode

Exit fullscreen mode

To call your attention to this situation, Git colors HEAD detached to red.

Why would you switch to commit instead of branch?

Because you can, and it can be sometimes useful. A common scenario is to see how the application worked a few commits earlier—for example, for troubleshooting. We noticed something wrong, such as a feature not working as expected, and we check out the last commit that we expect to work OK. In this way, we can pinpoint when exactly the issue was introduced.

How does it impact the work?

Because you are not on a branch, Git doesn’t have a branch to update when you create a new commit. So all the commits you a create there are stored but are left dangling: there is no way to easily reach them, and, as such, they are assumed to be unimportant. At some point, the garbage collector will remove them permanently from the repository.

How did it happen?

You left the branch and moved your HEAD elsewhere. It could happen:

  • by checkout of non-branch reference:
    • git checkout <commit ID>—as above
    • git checkout HEAD^—the last commit
    • git checkout <tag>—tags are similar to branches, but they are meant to be immutable and are not updated as branches
  • while your git rebase stopped halfway—due to conflict or to let you make changes to the commits,
  • during git bisect

How to fix it

Luckily, you get a bit of instruction directly in the CLI when you check out non-branch reference:

$ git checkout abc01e7
Note: switching to 'abc01e7'.

You are in 'detached HEAD' state. You can look around, make 
experimental changes and commit them, and you can discard any 
commits you make in this state without impacting any branches 
by switching back to a branch.

If you want to create a new branch to retain commits you 
create, you may do so (now or later) by using -c with the 
switch command. Example:

  git switch -c <new-branch-name>

Or undo this operation with:

  git switch -

Turn off this advice by setting config variable 
advice.detachedHead to false

Enter fullscreen mode

Exit fullscreen mode

Create a new branch

You can create a new branch, exactly in the point where you are—including all the commits that you maybe created from there. You can create the branch with the following syntax:

git switch -c <new-branch-name>

Enter fullscreen mode

Exit fullscreen mode

or the command form Git versions older then 2.23:

git checkout -b <new-branch-name>

Enter fullscreen mode

Exit fullscreen mode

Those commands create a new branch, and set it as your current branch.

Alternatively, you can just create a new branch on you current commit and stay in the detached HEAD state:

git branch <new-branch-name>

Enter fullscreen mode

Exit fullscreen mode

Switch to a branch and merge your commits

Alternatively, you can pick an existing branch and either merge your dangling commits or cherry-pick them. If you are not sure what those terms mean, then stick to creating a new branch, because it will allow you to do the same things, but in a less confusing setup.

How does it look in the tools

Besides the git status, how can you see this state?

You can see it on your Git tree graph

If you use git log --oneline --graph --decorate --all (something I recommend to define as a git tree alias) it will show your HEAD differently. When it’s on branch, the output looks like this:

$ git tree
* abc01e7 (HEAD -> main, origin/main) Add lorem ipsum to readme
* edd3504 Add readme

Enter fullscreen mode

Exit fullscreen mode

The HEAD points to the branch you are on with an arrow. When you are in “detached HEAD” state, main and HEAD are displayed separately, as an unrelated reference:

$ git tree
* abc01e7 (HEAD, origin/main, main) Add lorem ipsum to readme
* edd3504 Add readme

Enter fullscreen mode

Exit fullscreen mode

The difference is subtle but obvious when you know why you should pay attention to it.

GitHub desktop

At main branch:

Image description

“Detached head” state:

Image description

Can you see the difference in the middle part of the header? One is showing “Current branch”; while the other “Detached HEAD”.

Source tree

At main branch:

Image description

“Detached head” state:

Image description

It shows as the current branch HEAD.

Want to learn more?

Git has many confusing parts when you start using it, but it gets way simpler once you understand better the way it stores its data. If you are interested in learning more about Git, sign up here to get updates about my Git-focused content.

If you are one of the millions of developers who use Git, you may have come across the “detached HEAD state”. It is a strange phrase, but it’s not as alarming as it might sound. Here’s what it means. In Git, HEAD refers to the currently checked-out branch’s latest commit. However, in a detached HEAD state, the HEAD does not point to any branch, but instead points to a specific commit or the remote repository. If you want to keep the changes you made while in the detached HEAD state, you can solve this problem with three simple steps: creating a new branch, committing the changes, and merging the changes.

Git allows developers to maintain a history of changes (commits) to their code. It makes collaboration easier by allowing branching to keep code for different features separate and by seamlessly merging commits from multiple people. You can revert to previous commits in seconds if something goes wrong. It is fast, scalable, and has more commands and flexibility than older version control systems (VCS).

However, learning Git is more complicated than it was with older systems. Complex commands and a less intuitive user interface can sometimes lead to unwanted states, including the detached HEAD state. In this article, we will explore what the Git detached HEAD state is and some situations that cause it. Then, we will demonstrate how to save or discard changes in a detached head so you can quickly recover from the situation.

What is a normal HEAD state

Below is a diagram of the Git HEAD in a normal state, pointing to the latest commit in the main branch.

Git HEAD pointing to the latest commit in main

In this image, the HEAD points to the latest commit and current checked-out branch on every commit in the current branch.

HEAD is also a common state when working with multiple branches.

Git HEAD pointing to the latest commit in feature branch

In this situation, you have two branches, the main branch and a feature branch. Since you are checked out to the feature branch, HEAD points there. You can create this scenario with the following Git commands:

git branch feature
git checkout feature
git commit -m “checked out to feature”
git checkout Main
git commit
git commit -m “Latest commit”
git checkout feature

What does detached HEAD mean?

In Git, the detached HEAD state occurs when the HEAD does not point to a branch, but instead points to a specific commit or the remote repository.

In both of the diagrams in the previous section, HEAD points to the most recent commit in the currently checked out branch, which is its normal state. In Git, you can also check out a particular commit, which results in the detached HEAD state. Continuing from the previous scenario, if you check out to the first commit on the main branch, you will see that HEAD is now detached.

Git detached HEAD pointing to a previous commit

In this case, HEAD does not point to any branch—it references a commit.

Scenarios that can cause a detached HEAD state

You can find yourself in a detached HEAD state primarily through two scenarios:

  1. Checking out a specific Secure Hash Algorithm 1 (SHA-1) commit hash
  2. Checking out to a remote branch without fetching it first

We already demonstrated that if you check out the SHA-1 commit hash, you will be in the detached HEAD state. Another situation that causes a detached HEAD is checking out the remote branch. If you check out to the origin (main) branch, which is read-only, you will be in the detached HEAD state.

Some other scenarios can cause a detached HEAD as well. For example, checking out to a specific tag name or adding ^0 on any given branch causes the detached HEAD state.

How to save changes in a detached HEAD

If you find yourself a detached HEAD state and realize it quickly, you can quickly recover by checking out the previous branch. But what if you are in the detached HEAD state by mistake then perform commits over commits? If you are committing in the detached HEAD state, does that mean your changes are not saved?

Not at all. It just means you are not currently attached to any branch, and as a result, your HEAD is detached. To keep the changes made while in the detached HEAD state, use these three steps:

  • Create a new branch
  • Commit the changes
  • Merge the changes

Create a new branch

To save changes committed in a detached HEAD state, you first need to create a new branch.

Create and check out to a new branch

Continuing from the scenario described above, you create a new branch called temp-branch. As soon as you make the branch and check out to it, the HEAD is no longer detached.

Commit the changes

After checking out to the new branch, you can commit the changes, which Git will preserve.

Commit changes to the new branch

Merge the changes

Now, you check out to the branch where you want the changes. In this case, you want to merge the changes to the main branch. So, you first need to check out the main branch, then merge the changes from temp-branch and add the final commit message.

Merge changes to the main branch

With these simple steps, you have successfully preserved your changes and recovered from the Git detached HEAD state.

How to discard changes in a detached HEAD

If you want to discard the changes in the detached HEAD state, you only need to check out to the existing or previous branch. The commits on the detached HEAD state will not affect your existing branch, and Git will archive them.

The diagram below shows a situation in which, after going into the detached HEAD state, you make two commits that you do not want to keep. Then, you check out to the main branch. The dotted circles indicate that these commits are no longer part of any branch, and Git will delete them.

Discard changes in detached HEAD

Note that once Git prunes your detached HEAD state commits, there is no way to get them back. However, if they have not been deleted, you can check out to that SHA-1 commit hash, create a branch, and merge it to the desired branch to preserve the changes.

Conclusion

Git is a valuable developer tool and more popular than older versioning tools such as CVS and Subversion. That said, it can be more complex and challenging to master, and can sometimes lead to confusing situations such as the detached HEAD state.

If you find yourself in the detached HEAD state, remember that you can always preserve your changes by creating and checking out to a new branch, then committing and merging the changes in the desired branch. If you do not want to save the changes, you can simply check out to any branch, and Git removes those commits.

Also, Git 2.23 has a new command, git switch. This is not a new feature but an alternative command to git checkout so you can switch between the branches and create a new branch. To change from one branch to another, use git switch branchName to create a new branch, then switch to it using the git switch -c branchName command.

Although finding your code in the detached HEAD state is not ideal, you can use these methods to move or remove your commits and quickly get your project back on track.

“You are in ‘detached HEAD’ state” is not an error message and is nothing to be worried about.

This state means you are no longer on a branch, and it happens when an arbitrary commit is checked out instead of a branch.

If this state was unintentional and you want to “fix” the ‘detached HEAD’, you can go back to the branch you are expected to be on by runing the git checkout command.

Note: Any commits you make in ‘detached HEAD’ mode will get lost once you switch to the previous branch.

Return back to the previous branch from the ‘detached HEAD’ state:

$ git checkout -

If you have already committed some changes in the ‘detached HEAD’ and don’t want to loose them, you can save these changes in a temporary branch:

$ git checkout -b <temporary-branch-name>

Later that temporary branch can be integrated into some other branch, e.g. master:

$ git checkout master
$ git merge <temporary-branch-name>

Cool Tip: Move back and forth between two branches in Git! Read more →

Was it useful? Share this post with the world!

Добавить комментарий