Corporate Software
What is Git's detached HEAD state, and how do you fix it?

Short answer
Git’s detached HEAD state means the HEAD pointer in your repository is attached directly to a specific commit instead of to a branch name, and on its own it isn’t an error. It typically shows up after running something like git checkout <commit-hash> or git checkout <tag>,
and the terminal flags it with the message “You are in ‘detached HEAD’ state.”. If whatever you were looking at doesn’t matter, getting out is a single command: git switch <branch-name>. If you’ve committed something you don’t want to lose, you need to create a branch from where you stand first with git switch -c new-branch; otherwise the only path back to those commits closes the moment you move away.
What does detached HEAD state actually mean?
In normal day-to-day work, HEAD is a pointer to whichever branch you currently have checked out. Every new commit moves that branch forward, and HEAD moves with it automatically. When you run git checkout against a specific commit hash, a release tag, or an untracked remote reference, Git treats the move differently: you are no longer standing on a branch, you are standing on one single commit.
The terminal warning is describing exactly that. HEAD is no longer tied to any branch name; it points straight at that commit. According to Git’s own official documentation, this is “known as being in detached HEAD state,” and it simply means HEAD refers to a specific commit rather than to a named branch: nothing is broken, the reference has just changed shape.
The real risk is that any new commit you make there isn’t tracked by a branch. The instant you switch away, the one reference that pointed to those commits disappears. The files aren’t deleted immediately, but without a branch holding them, they become eligible for Git’s garbage collector over time.
What commonly puts you in detached HEAD state?
Four familiar actions account for most cases. Running git checkout <commit-hash> to inspect a specific commit is probably the most common one, closely followed by checking out a release tag with something like git checkout v2.3.0. Using git bisect to track down a bad commit lands you there too, and so does checking out a pull request’s remote branch directly, without a local tracking branch set up first.
All four produce the same result, intentionally or not: Git marks where you’re standing as a single point, not a branch. None of these commands is wrong by itself; the trouble starts when you keep working there without deciding what comes next.
How do you get out of detached HEAD state?
The right way out depends entirely on whether the work you did at that commit is worth keeping, and on how long you’ve already been standing there.
If what you were looking at doesn’t matter
If nothing you did at that commit needs to survive, switching back to any branch is enough:
git switch main
If you’re on an older Git version that doesn’t yet support switch, git checkout main handles the exact same job.
If you want to keep the work
If you committed something while in detached HEAD state and don’t want to lose it, create a branch from exactly where you’re standing:
git switch -c new-branch-name
This command carries every commit made up to that point onto the new branch. Once a branch name tracks them, they’re safe, so you can push the branch normally and open a pull request from it.
If you think you’ve already lost commits
Even if you noticed after switching branches, recovering the work is usually possible. The git reflog command keeps a log of HEAD’s recent movements, and you can typically find the lost commit’s hash there. From that hash, git switch -c recovery-branch <hash> opens a new branch and brings the work back.
Why is detached HEAD state considered normal in CI/CD pipelines?
Automation systems like GitHub Actions usually check out a repository against a specific commit when a workflow runs, not against a branch, so the pipeline starts directly in detached HEAD state. That’s fine, because the automation has no need to open a new branch from that commit or commit to it manually; it only builds, tests, or deploys the code. A runner shutting down doesn’t cost anything, because no durable work was ever meant to happen there.
Running into the same state on your own machine is a different situation. There, you are a developer, and the change in front of you is probably meant to stick around, so borrowing CI’s behaviour as a justification for treating detached HEAD as harmless, and working in it for an extended stretch, isn’t a fair comparison.
When should you actually be careful?
The risky scenario is a developer working in detached HEAD state for days without noticing. Every commit made during that stretch is unprotected by a branch; close the terminal, switch branches, or restart the machine, and that work is genuinely at risk of disappearing.
The practical rule is simple. If you’re only looking at a commit or running a one-off test against it, there’s nothing to worry about. If you’re about to write something that needs to survive longer than a few minutes, create a branch first with git switch -c. That one habit removes the single most common cause of lost work in this situation.
Common mistakes
Continuing to commit without reading the terminal warning is the most frequent mistake; developers often don’t notice their commits live on no branch until days later. Starting work without checking git branch first leads to the same blind spot: if the output shows * (HEAD detached at ...) instead of a branch name next to the asterisk, the state is already obvious.
Confusing git checkout -- for restoring a file with checking out a branch is another common slip, since git checkout bundles so many different jobs into one command that it’s easy to lose track of which one just ran. Forgetting to run git stash for uncommitted changes before switching away from detached HEAD can also silently overwrite work that was never committed in the first place.
Checklist
Working through detached HEAD state safely, instead of guessing your way out of it, means following this order every time it comes up:
- Run
git statusto confirm you’re actually in detached HEAD state. - Decide whether what you’re standing on is worth keeping.
- Create a branch with
git switch -c new-branchfor any commit that matters. - Stash uncommitted changes with
git stashbefore switching away, if there are any. - Use
git reflogto search backwards if you suspect a commit has gone missing.
Next step
Detached HEAD state is something every Git user runs into eventually, and it resolves in minutes once you work through it in order. What matters is not ignoring the terminal warning, and creating a branch before doing anything worth keeping. A similar decision point comes up during git merge; if you want to look at both together, our how to resolve a git merge conflict guide covers that side of version control.
If you want to sharpen your command-line habits more broadly, our SSH and essential Linux commands guide is worth a look too. To design your team’s version control workflow, branching strategy, or release process from the ground up, explore our custom software development service or get in touch with us. Our group company Web Tasarım Ofisi also supports web projects with version control infrastructure and long-term technical maintenance.
Related reading
Frequently asked questions
Is detached HEAD state an error?
No. Detached HEAD state is a normal Git condition that means HEAD points directly at a commit instead of at a branch. The real problem only shows up when someone keeps working there for a long time without noticing.
What happens if I commit while in detached HEAD state?
The commit is created normally, but no branch tracks it. The moment you switch to another branch, the only reference pointing to that commit disappears, and it becomes eligible for garbage collection unless you create a branch from it first.
What's the difference between git switch and git checkout?
git checkout bundles branch switching, file restoration and commit navigation into one command, which makes it easy to land in detached HEAD state by accident. git switch is dedicated to branch operations only, so its intent is clearer and it's harder to misuse.
Why does the checkout step in GitHub Actions end up in detached HEAD state?
actions/checkout checks out the repository's specific commit by default, not a branch, so the automation knows exactly which code version it is working with on every run. That's expected, harmless behaviour for CI, not a sign of a misconfigured workflow.
How do I recover commits I think I lost?
The git reflog command keeps a log of HEAD's recent movements. You can usually find the lost commit's hash there, then bring the work back with git switch -c recovery-branch <hash> from that point.