What this error means
Git refuses to merge (e.g., during git pull) when you have local modifications to tracked files that would be overwritten by incoming changes. It’s a safety check so you don’t lose work.
Common contexts:
- git pull (fetch + merge or rebase)
- git merge branch
- git switch/checkout to another branch with conflicting local edits
Quickstart: pick a safe path
Choose based on your goal:
- Keep your work and integrate remote changes
- Commit your changes, then pull.
- Or stash your changes, pull, then reapply.
- Temporarily shelve work to a separate branch
- Create a WIP branch, commit there, pull main, then merge back.
- Discard local changes
- Restore files to HEAD, then pull.
Command cheat sheet
| Goal | Commands | Notes |
|---|---|---|
| Commit then pull | git add -A && git commit -m "wip" && git pull | Clean and explicit history |
| Stash then pull | git stash push -u -m "wip" && git pull && git stash pop | -u includes untracked files |
| Shelve to branch | git switch -c wip/changes && git add -A && git commit -m "wip"; git switch - | Keeps work visible in branches |
| Discard changes | git restore --worktree --staged --source=HEAD -- . | Equivalent to reset index+worktree |
| CI/ephemeral reset | git fetch origin && git reset --hard origin/main && git clean -fdx | Destroys local changes; use only on disposable clones |
Minimal working example (reproduce the error)
This creates a bare remote, two clones, then triggers the error by pulling with local edits.
set -euo pipefail
# 1) Create a bare origin
rm -rf /tmp/git-demo && mkdir -p /tmp/git-demo
cd /tmp/git-demo
mkdir origin.git && git init --bare origin.git
# 2) First clone and initial commit
git clone origin.git A && cd A
printf "hello\n" > file.txt
git add file.txt
git commit -m "initial"
git push origin main:main
# 3) Second clone modifies and pushes
cd ..
git clone origin.git B && cd B
printf "remote change\n" >> file.txt
git commit -am "remote edit"
git push origin main
# 4) Back to first clone: create local change, then pull
cd ../A
printf "local change\n" >> file.txt
# This pull will fail with the overwrite error
set +e
git pull || echo "Encountered expected error"
Typical message excerpt:
- error: Your local changes to the following files would be overwritten by merge:
- Please commit your changes or stash them before you merge.
Step-by-step fixes
- Commit then pull (recommended if changes are ready)
- Review and stage changes: git add -p or git add -A
- Commit: git commit -m "Describe change"
- Update: git pull
- Resolve merge conflicts if prompted; then git commit
- Stash then pull (if changes are not ready)
- Stash including untracked: git stash push -u -m "wip before pull"
- Update: git pull
- Reapply: git stash pop
- If conflicts arise during pop, resolve them, git add, and git commit
Tips:
- Use git stash list to see entries; git stash apply <stash> to apply without dropping.
- For a subset of files: git stash push -p
- Shelve to a WIP branch (keeps history clean)
- Create and switch: git switch -c wip/your-change
- Save work: git add -A && git commit -m "WIP"
- Return: git switch -
- Update main: git pull
- Merge WIP later: git merge wip/your-change (resolve and commit)
- Discard local changes (use with care)
- Discard both staged and working tree changes to match HEAD:
- git restore --worktree --staged --source=HEAD -- .
- Then update:
- git pull
- To also delete untracked files:
- git clean -fd
- And ignored files too (dangerous):
- git clean -fdx
- Prefer rebase with autostash (optional)
- Configure once: git config --global pull.rebase true
- Autostash before rebase: git config --global rebase.autoStash true
- Then: git pull will auto-stash/apply around the rebase when safe
DevOps and CI/CD usage
- For disposable agents/containers, prefer a clean sync from remote:
- git fetch --all --prune
- git reset --hard origin/main
- git clean -fdx
- Avoid stashes in CI unless you explicitly persist workspace state.
- If builds require local patches, commit them on a branch and rebase/merge explicitly.
Pitfalls and how to avoid them
- Untracked vs tracked files
- The error triggers for tracked files with local mods. Untracked files won’t block a merge, but can block branch switches; stash with -u if needed.
- Line endings and filters
- CRLF normalization or filters can make Git think files changed. Set consistent attributes (.gitattributes) and consider core.autocrlf or text eol policies.
- Submodules
- Dirty submodules can block operations. Update with git submodule update --init --recursive and commit submodule pointer changes.
- Partial changes
- If only some paths conflict, stash or commit selectively (git add -p, git stash -p) to minimize merges.
- Overusing reset --hard
- It’s fast but destructive. Use only when you’re certain the workspace is disposable or changes are backed up.
Performance notes
- Stash vs commit
- Both create objects; performance is similar. Prefer commit for traceability; stash for transient work.
- Large repositories
- Limit scope with pathspecs: git add <path>, git restore -- <path>.
- Use sparse-checkout or partial clone to reduce data size in CI.
- Cleaning
- git clean -fdx is O(files). On very large trees, prefer caching build artifacts outside the repo to avoid frequent rebuilds.
- Worktrees
- git worktree add ../wt-main origin/main lets you build/test without touching your primary working directory.
Small FAQ
- Why does Git refuse to merge?
- To prevent losing uncommitted edits to tracked files that would be overwritten by incoming changes.
- Is git pull --rebase safer?
- It changes history shape but the same safety check applies. Enable rebase.autoStash to reduce friction.
- Stash or commit?
- Commit if the work is meaningful and should be tracked. Stash if it’s experimental or transient.
- Keep only remote version of a file?
- git fetch origin && git restore --source=origin/main -- path/to/file
- Clean slate to match remote branch?
- git fetch origin && git reset --hard origin/main && git clean -fdx