Skip to content

Grokem · https://www.grokem.com/programming/version-control/git-detached-head-and-rejected-push

Version ControlTroubleshooting guide

Git troubleshooting: detached HEAD, rejected pushes and merge conflicts

The three messages that stop most people: what 'detached HEAD', 'fetch first' and 'CONFLICT' mean, and the exact commands that get you out of each.

Grokem Editorial

Editorial desk

Published
  • 4 min read
Tested withGit2.53

Git's error messages are long but usually accurate. Three of them account for most panic.

1. "You are in 'detached HEAD' state"

What happened. HEAD normally points at a branch, and the branch points at a commit. When you check out a commit directly (an old hash, a tag, origin/main), HEAD points at the commit itself. Git tells you so:

text
Note: switching to '1deec24'.

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.

Looking around is harmless. The risk is committing here and then leaving: those commits belong to no branch and can be lost. Git warns you when you switch away:

text
Warning: you are leaving 1 commit behind, not connected to
any of your branches:

  55d8594 Work done while detached

To keep the work, give it a branch, now or at the warning:

bash
git switch -c rescue-work          # while still detached
git branch rescue-work 55d8594     # or later, using the hash from the warning

To discard it, just go back: git switch main. If you only wanted to look, that is all there is to it.

2. "! [rejected] main -> main (fetch first)"

What happened. Someone pushed to main after you last updated, so your history and the remote's have diverged. Git refuses to overwrite theirs:

text
 ! [rejected]        main -> main (fetch first)
error: failed to push some refs to '<remote>'
hint: Updates were rejected because the remote contains work that you do not
hint: have locally. This is usually caused by another repository pushing to
hint: the same ref. If you want to integrate the remote changes, use
hint: 'git pull' before pushing again.

The fix is to bring their work in, then push:

bash
git pull             # merges their commits into yours
git push

If you prefer a straight history, git pull --rebase replays your commits on top of theirs instead of adding a merge commit. Either way you may meet a conflict, which is the next problem. Resist git push --force. It would make the push succeed by deleting the other person's commits from the remote.

3. "CONFLICT (content): Merge conflict"

What happened. You and someone else changed the same lines. Git merged everything it could and stopped on the rest:

text
Auto-merging app.txt
CONFLICT (content): Merge conflict in app.txt
Automatic merge failed; fix conflicts and then commit the result.

git status lists the file as UU (both modified), and the file now contains both versions between markers:

text
line 1
<<<<<<< HEAD
alice change
=======
bob change
>>>>>>> 05975ba9f2cb700b9f5012a04531e0d11c296e36

Between <<<<<<< HEAD and ======= is your version. Between ======= and >>>>>>> is theirs.

To resolve it:

  1. Open the file and decide what the lines should be: yours, theirs, both or something new.
  2. Delete the three marker lines. A file that still contains <<<<<<< is not resolved.
  3. Mark the file resolved and finish the merge:
bash
git add app.txt
git commit

To give up and return to how things were before the pull, run git merge --abort.

Tips that prevent repeats: pull often so differences stay small, keep commits focused, and agree who edits generated or shared files.

Two more you will meet

  • "Your local changes would be overwritten by checkout." Git is protecting uncommitted work. Commit it, or git stash it, switch, and git stash pop to bring it back.
  • "Refusing to merge unrelated histories." The two histories have no common ancestor, usually because each side ran git init separately. Only if you are sure they belong together, add --allow-unrelated-histories.

A habit that helps

Before anything risky (a hard reset, a rebase, a big merge) run git branch backup. It is a bookmark of where you were, it costs nothing, and you can delete it later.

Troubleshooting

ProblemLikely causeFix
You are in 'detached HEAD' stateYou checked out a commit, tag or remote branch directly instead of a branch, so new commits belong to no branch.To keep any work you did, run git switch -c <new-branch-name>. To discard it and go back, run git switch main (or git switch -).
! [rejected] main -> main (fetch first)The remote has commits you do not have locally, so your push would not be a simple fast-forward.Run git pull (or git pull --rebase), resolve any conflicts, then push again. Do not force-push to a shared branch.
CONFLICT (content): Merge conflict in <file>You and someone else changed the same lines, and Git cannot choose.Open the file, edit between the <<<<<<< and >>>>>>> markers to what you want, remove the markers, git add the file and finish with git commit.
error: Your local changes to the following files would be overwritten by checkoutYou have uncommitted changes in a file that differs on the branch you are switching to.Commit the changes, or put them aside with git stash, switch, then git stash pop.
fatal: refusing to merge unrelated historiesThe two branches share no common commit, often after an init in two places.If you are sure they should be joined, use git pull --allow-unrelated-histories and resolve the result.

Frequently asked questions

Is it safe to use git push --force?

On a branch only you use, yes, with care. On a shared branch it overwrites other people's work. If you must, use git push --force-with-lease, which refuses if the remote has changed since you last looked.

Merge or rebase when pulling?

Merging keeps the exact history and adds a merge commit. Rebasing replays your commits on top for a straighter line. Pick one per team and write it down.

References

From Grokem: https://www.grokem.com/programming/version-control/git-detached-head-and-rejected-push

How did this strike you?

Be the first to react – it is anonymous.

Community

Questions about this?

Ask in Questions and help and get help from other readers.

Ask a questionBrowse Questions and help

Comments

No comments yet. Share what worked for you, or ask a question.

Keep going

All in topic

Choose what we may use. You can change this at any time with “Privacy choices” at the foot of every page. Details are in the Cookie policy and the Privacy policy.

Strictly necessary

Remembers your theme, the lessons you marked as done and this choice. It stays on your device, tracks nothing and cannot be switched off.

Always on
What exactly is collected, and why

Grokem’s own counts

Collects
The pages you open and how long you stay, how far you scroll, where you came from, your device type, browser, screen size, language and time zone. Your IP address is turned into a code that changes every day; it is never stored as it is.
Why
To see how long lessons are read and where readers leave. Not shared with anyone.
Stored
A random visitor ID, a visit ID and the time of your last page view in your browser’s storage (gr_vid, gr_sid, gr_last). No name or email is attached.