Last modified: March 23, 2026
This article is written in: 🇺🇸
HEAD is Git’s pointer to the snapshot you’re currently working on—the bookmark of your checkout. Most of the time, HEAD points to the tip of a branch (like master or main). When you commit, HEAD (and that branch) advance to the new commit.
HEAD is a tiny text file: .git/HEAD. Running cat .git/HEAD might show ref: refs/heads/master, meaning HEAD points to the branch named master. If it shows a raw commit hash instead, HEAD is detached (explained below).git switch or git checkout) moves HEAD to point at the target branch. Knowing where HEAD points makes branching, merging, and navigating history far more predictable.Git provides shorthand for referencing commits relative to HEAD:
| Notation | Meaning | Example Use |
HEAD |
Current commit | git show HEAD |
HEAD~1 |
Parent of current commit | git diff HEAD~1 HEAD |
HEAD~N |
N commits back | git reset HEAD~3 |
HEAD^ |
First parent (same as ~1) |
git show HEAD^ |
HEAD^2 |
Second parent (for merge commits) | git show HEAD^2 |
HEAD@{N} |
Nth previous position in reflog | git show HEAD@{1} |
# View commit 3 generations back
git show HEAD~3
# Compare current commit with its parent
git diff HEAD~1 HEAD
# Reset last 2 commits but keep changes staged
git reset --soft HEAD~2
Time → (commits left→right)
┌───────────── Merge ──────────────┐
main ──●──┼──●───────────●───────────●───────●────────▶
A1 A2 M1 A3 A4 (branch tip: main)
\ ^ \
\ │ \
feature/login ●───●───●─────┘ ●─────●──▶
F1 F2 F3 M2 F4 (HEAD -> feature/login)
hotfix/urgent ●────●─────────────────────────┘
H1 H2
Tags/Remotes:
(origin/main) at A3 (v1.2) tag at M1
Legend:
● = commit node
A*, F*, H* = commit short IDs (on main, feature/login, hotfix/urgent)
M* = merge commits
HEAD -> <branch> means your working tree points to that branch’s tip
HEAD -> feature/login (on the feature/login row) tells you your current checkout is at F4. New commits will extend feature/login.git switch main (or git checkout main), HEAD moves to A4, and the indicator becomes HEAD -> main.A detached HEAD is when HEAD points directly to a commit instead of to a branch tip—usually after checking out a specific commit hash or a tag.
HEAD elsewhere because nothing points to them.git switch -c my-work) or merge/cherry-pick it into an existing branch.If you accidentally switch away from a detached HEAD without saving your work, git reflog is your safety net. It records every position HEAD has been in:
git reflog
# output example:
# a1b2c3d HEAD@{0}: checkout: moving to main
# e4f5a6b HEAD@{1}: commit: Important work I did while detached
# c7d8e9f HEAD@{2}: checkout: moving from main to c7d8e9f
# Create a branch to save the lost commit
git branch recovery-branch e4f5a6b
git switch recovery-branch
⚠️ Important: Reflog entries expire after ~90 days by default. Don’t rely on reflog as a long-term backup—always create a branch for work you want to keep.
This is what it looks like when you check out a specific commit:
main ──●──●──●──●──●──▶
A1 A2 A3 A4
(HEAD) ----------------^
(checked out at commit A3, no branch name)
Here HEAD points to A3 itself, not a branch. New commits would form an orphaned line unless you first make a branch, e.g. git switch -c temp-work.
If you commit (F) while HEAD is detached at commit C, history forks:
A <-- B <-- C (HEAD) <-- F
\
D <-- E (master)
Commit F is not on master. If you switch back to master, there’s no branch reference to F unless you merge, cherry-pick, or create a branch pointing to it. If left unattached, F can be garbage-collected once unreachable.
You enter a detached HEAD state by checking out a commit hash or tag. For example:
git switch b4d373a8990c2b5de30a37bf843b2f51fae2b40
Or equivalently:
git checkout b4d373a8990c2b5de30a37bf843b2f51fae2b40
HEAD now points to that exact commit rather than a branch tip. Git will say:
Note: switching to 'b4d373a8990c2b5de30a37bf843b2f51fae2b40'.
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.
That’s your cue: commits made now live off to the side until you attach them to a branch (e.g., git switch -c keep-this).
Sometimes you realize you’ve made valuable commits while detached and want to keep them. The safe fix is to create a branch at the commit you’re on and then switch to it.
git branch new_branch
Then switch to it:
git switch new_branch
Now new_branch contains all commits you made while HEAD was detached, and you’re no longer detached—HEAD points to the branch tip again. Your work is preserved and anchored to new_branch.
Before:
A <-- B <-- C (HEAD) <-- F
After creating and switching to new_branch:
A <-- B <-- C <-- F (new_branch, HEAD)
F is no longer “floating”; it’s anchored to the new_branch branch.
Tip: You can do this in one step with git switch -c new_branch. Verify where you are with git status or git branch --show-current.
⚠️ Critical: If you leave a commit detached without a branch and switch away, Git will eventually garbage-collect it (typically after 30 days). Always create a branch immediately if you made important commits while detached.
It’s cleaner to avoid a detached HEAD unless you’re only looking. If you intend to make changes, create a branch at that commit first so new work has a name and a home.
Example Scenario: You want to check out an older commit to debug or reproduce behavior.
I. Create a branch named old_version at that commit:
git branch old_version b4d373a8990c2b5de30a37bf843b2f51fae2b40
II. Switch to old_version:
git switch old_version
Now, any commits you make stay on old_version—no work drifts unreferenced.
Tip: One-step variant: git switch -c old_version b4d373a8990c2b5de30a37bf843b2f51fae2b40.
When you’re done exploring a detached commit, just jump back to a normal branch (like master):
git switch master
or
git checkout master
You’ll be right where master last pointed. If you made commits while detached and haven’t put them on a branch yet, do so before switching—or recover them later via git reflog and then create a branch to keep them.
You’ve made useful commits while detached and want them on master. The trick is to merge the commit that contains your work (usually the latest one on that detached line) into master.
I. Switch to master (the branch you want to bring changes into):
git switch master
(Or git checkout master.)
Tip: If your default branch is main, substitute accordingly.
II. Merge the detached commit (use the tip commit’s hash):
git merge b4d373c8990a2b5de30a37bf843b2f51f5c2b400
This creates a merge commit tying your detached line into master. You’re effectively stitching that “loose thread” back into the main history. If Git reports conflicts:
git status # see which files need attention
# resolve conflicts in your editor
git add <file_with_conflicts>
git merge --continue # or: git commit
Now your detached changes are part of master, recorded with a merge commit.
(master) (HEAD detached)
| |
D <-- E C <-- F
\ /
------ Merge Commit --
Result: a single continuous history where F’s changes are integrated into master.
Notes
git cherry-pick <hash> instead.