Skip to main content

The Detached HEAD State: Why Git Won't Push and How to Fix It

· 6 min read
Serhii Hrekov
software engineer, creator, artist, programmer, projects founder

This situation is known as being in a Detached HEAD state. It happens because when you use git checkout <commit-hash>, you're telling Git to look at that specific point in history, not a moving branch name.

The solution is to create a new branch at that commit before pushing.

Understanding the Detached HEAD State

When you use git checkout <commit-hash>, the pointer called HEAD is detached from any named branch and points directly to that single commit.

  • Normal State (Attached HEAD): HEAD points to a branch name (e.g., main, feature-x), which in turn points to a commit. When you commit, the branch name simply moves forward.
  • Detached HEAD State: HEAD points directly to a commit hash. When you commit, the new commit is created, and HEAD moves to it, but since no branch name is pointing to it, this new commit is easily "lost" once you switch branches again.

Your new commit exists, but it's not currently tracked by any branch in your local repository, which is why git push doesn't know where to send it.


Step-by-Step Solution

You have already made your changes and committed them. Let's assume your new commit hash is ABCDEF. Here is what you need to do:

1. Verify Your Current Commit

First, check the history to confirm the location of your new commit.

git log --oneline

The output will show your new commit at the top, and indicate that you are in a detached state (e.g., (HEAD, no branch)). Note the hash of your new commit (e.g., ABCDEF).

2. Create a New Branch

Create a new branch name that points to your current (detached) commit. The git branch <new-branch-name> command creates the branch, and git checkout then switches you to it, ending the detached HEAD state.

# Creates a new branch at your current commit (ABCDEF)
git branch my-new-feature-branch

# Switches to the newly created branch
git checkout my-new-feature-branch

Alternative (Shorter): You can perform both steps at once by using the git switch command with the -c or git checkout with the -b flag:

# Preferred modern command: switches to a new branch
git switch -c my-new-feature-branch
# OR
# Older command: switches to a new branch
git checkout -b my-new-feature-branch

3. Push the New Branch

Now that you are on a named branch, you can push it to the remote repository.

git push -u origin my-new-feature-branch

The -u flag sets the upstream tracking, so future git push and git pull commands will work without specifying the remote.


Best Practice: The Safer Way to Make Changes

To avoid the detached HEAD state entirely when you want to make changes based on an older commit, use the following pattern:

  1. Create a New Branch Immediately before making changes.
  2. Make Changes and Commit on that new branch.
# 1. Start from the specific commit hash (or a branch)
git checkout <commit-hash>

# 2. IMMEDIATELY create a new branch and switch to it
git checkout -b fix-on-old-version

# 3. Make changes and commit
# ... (edit files) ...
git add .
git commit -m "Fix applied to the older commit."

# 4. Push as normal
git push -u origin fix-on-old-version

By creating and switching to a branch in step 2, the HEAD pointer remains attached to the branch name, making it impossible to lose your new commits.

Source

  1. Git Documentation on Detached HEAD
  2. Understanding HEAD in Git
  3. Git Log Formatting Options