KhueApps
Home/DevOps/Fixing Git error about staged content differing from file and HEAD

Fixing Git error about staged content differing from file and HEAD

Last updated: October 07, 2025

What this error means

You see:

fatal: The following paths have staged content different from both the file and the HEAD

It occurs when the index (staged version) of a path does not match either:

  • the working tree file, and
  • the version in HEAD (last committed version).

This usually shows up while running checkout or restore to pull a version from HEAD or another commit, which would overwrite your staged changes.

Quickstart fixes

Decide which version you want to keep, then use one of these targeted fixes:

  • Keep working tree, drop staged changes for path:

    • git restore --staged <path>
    • or: git reset HEAD -- <path>
  • Keep staged version, overwrite working tree with staged:

    • git checkout -f -- <path>
  • Overwrite both staged and working tree with HEAD (discard everything for path):

    • git restore -s HEAD --staged --worktree -- <path>
    • or: git reset --hard HEAD -- <path>

After applying your choice, re-run the original command.

Minimal working example (reproduce and fix)

# 1) Setup
mkdir demo && cd demo
git init
echo "v1" > app.txt
git add app.txt
git commit -m "init"

# 2) Create staged and working tree differences
# Stage one change…
echo "staged" > app.txt
git add app.txt
# …then modify working tree again without staging
echo "worktree" >> app.txt

# 3) Try to pull HEAD’s version into app.txt (will fail)
# This wants to replace both index and working tree with HEAD
git checkout HEAD -- app.txt
# fatal: The following paths have staged content different from both the file and the HEAD: app.txt

# 4A) Fix option: Keep working tree; drop staged
git restore --staged app.txt
# Now you can restore from HEAD if you still want
git checkout HEAD -- app.txt   # or: git restore -s HEAD --worktree -- app.txt

# 4B) Fix option: Keep staged; overwrite working tree
# Reset state again to reproduce the conflict
# (recreate staged + different worktree)
echo "staged" > app.txt && git add app.txt
echo "worktree" >> app.txt
# Force write index to working tree
git checkout -f -- app.txt

# 4C) Fix option: Discard both staged and worktree; use HEAD
git restore -s HEAD --staged --worktree -- app.txt

Step-by-step resolution

  1. Inspect what differs
  • See staged vs HEAD:
    • git diff --staged -- <path>
  • See working tree vs staged:
    • git diff -- <path>
  • See HEAD vs working tree (ignoring staged):
    • git diff HEAD -- <path>
  1. Decide which version to keep per path
  • Working tree is correct → unstage it
  • Staged is correct → force it into working tree
  • HEAD is correct → restore both index and working tree from HEAD
  1. Apply the corresponding command
  • Keep working tree:
    • git restore --staged <path>
  • Keep staged:
    • git checkout -f -- <path>
  • Keep HEAD:
    • git restore -s HEAD --staged --worktree -- <path>
  1. Verify and continue
  • git status
  • Re-run your original checkout/restore/rebase/merge command

Why it happens

Commands like git checkout <tree-ish> -- <path> and git restore -s <tree-ish> --staged --worktree <path> attempt to write both the index and the working tree from a given commit. If the index already holds unique changes (different from both HEAD and your working tree), Git refuses to avoid destroying those staged changes inadvertently.

Pitfalls and safety notes

  • Force flags are destructive

    • git checkout -f -- <path> and git reset --hard HEAD -- <path> discard data for that path. Inspect diffs first.
  • Use pathspecs to limit scope

    • Always specify the exact path(s) to avoid impacting unrelated files.
  • Mixed new Git and legacy commands

    • git restore is the modern alternative; git checkout works everywhere. Prefer restore where available for clarity:
      • Unstage: git restore --staged <path>
      • Restore file only: git restore -s HEAD --worktree -- <path>
  • CRLF or mode-only changes

    • If diffs look odd, check line endings and filemode:
      • git config core.autocrlf input|true|false
      • git config core.filemode false
  • In-progress merges or rebases

    • If you are mid-merge/rebase, resolve conflicts or use stash/commit carefully before retrying.

Performance notes (large repos)

  • Limit diffs to impacted paths:
    • git diff --staged -- <path>
    • git status -- <path>
  • Avoid scanning the whole repo unnecessarily; target specific files to reduce index/worktree comparison costs.
  • If status feels slow, refresh the index timestamps:
    • git update-index --refresh

FAQ

Q: Which version am I about to lose with -f? A: For git checkout -f -- <path>, you overwrite the working tree file with the staged content, losing un-staged edits for that path.

Q: How do I keep both staged and my current edits? A: Commit the staged changes first (git commit -m "..."), then stash your working tree edits (git stash push -u) or commit them afterward.

Q: Can I avoid this by operating on only the working tree? A: Yes. Use git restore -s <commit> --worktree -- <path> to change only the file, leaving the index untouched.

Q: Why does git checkout HEAD -- <path> fail here? A: It would modify both the index and working tree from HEAD, discarding staged content. Git blocks that unless you force or unstage first.

Q: Is there a way to preview exactly what is staged? A: Yes. Use git diff --staged and git show :<path> to view the index’s version.

Series: Git

DevOps