This error occurs when you attempt to run git revert while there are unresolved merge conflicts in your working directory. Git requires all conflicts to be resolved before proceeding with new operations.
The "revert is not possible because you have unmerged files" error indicates that Git cannot perform the revert operation because your repository is in an inconsistent state with unresolved merge conflicts. This typically happens when a previous merge, rebase, cherry-pick, or revert operation encountered conflicts that were never fully resolved. When Git performs operations that combine changes from different sources (like merging branches), it may encounter situations where the same lines of code were modified differently in each branch. Git marks these as "unmerged" files and pauses the operation, waiting for you to manually resolve the conflicts. Until you resolve these conflicts and tell Git you're done (by staging the files), Git considers your repository to be in an incomplete state. The key insight is that Git is trying to protect you: performing a revert on top of an already conflicted state would create even more confusion about what the final state of your code should be. Git requires you to first resolve the existing conflicts before introducing new changes through a revert.
First, understand exactly what state your repository is in:
git statusThis will show you:
- Which operation is in progress (merge, revert, rebase, cherry-pick)
- Which files have conflicts (marked as "both modified" or "unmerged")
- What Git suggests you do next
Example output when in a conflicted state:
On branch main
You have unmerged paths.
(fix conflicts and run "git commit")
(use "git merge --abort" to abort the merge)
Unmerged paths:
(use "git add <file>..." to mark resolution)
both modified: src/app.js
both modified: src/config.tsIf you want to keep the changes from the interrupted operation, resolve the conflicts manually:
1. Open each conflicted file and look for conflict markers:
<<<<<<< HEAD
// Your current changes
const value = "current";
=======
// Incoming changes
const value = "incoming";
>>>>>>> branch-name2. Edit the file to keep the code you want (remove the markers):
// Resolved: keeping the incoming changes
const value = "incoming";3. Stage each resolved file:
git add src/app.js
git add src/config.ts
# Or stage all resolved files at once:
git add .4. Complete the operation:
# If it was a merge:
git commit
# If it was a revert:
git revert --continue
# If it was a cherry-pick:
git cherry-pick --continue
# If it was a rebase:
git rebase --continueIf you want to abandon the interrupted operation and return to a clean state:
# If a revert is in progress:
git revert --abort
# If a merge is in progress:
git merge --abort
# If a cherry-pick is in progress:
git cherry-pick --abort
# If a rebase is in progress:
git rebase --abortAfter aborting, verify your repository is clean:
git statusYou should see:
On branch main
nothing to commit, working tree cleanNow you can safely run your original revert command:
git revert <commit-hash>If you want to completely discard all changes and conflicts (use with caution):
# Discard all changes and reset to the last commit
git reset --hard HEADWarning: This will permanently delete any uncommitted changes, including:
- Resolved conflict files that weren't committed
- Any other modifications in your working directory
- Staged changes
If you have important changes you want to save first:
# Stash your changes before resetting
git stash
git reset --hard HEAD
# Later, you can recover them with:
git stash popFor newer versions of Git, you can use git restore to handle individual files:
Unstage conflicted files:
git restore --staged src/app.jsDiscard changes in a specific file:
git restore src/app.jsRestore all files to their state before the conflict:
# Unstage all files
git restore --staged .
# Then discard working directory changes
git restore .This is a safer alternative to git reset --hard as it gives you more control over which files to restore.
Sometimes Git's state files can get into an inconsistent state. Check for leftover operation indicators:
# Check if any operation files exist
ls -la .git/
# Look for these directories/files:
# .git/MERGE_HEAD - indicates merge in progress
# .git/REVERT_HEAD - indicates revert in progress
# .git/CHERRY_PICK_HEAD - indicates cherry-pick in progress
# .git/rebase-merge/ - indicates rebase in progress
# .git/rebase-apply/ - indicates rebase or am in progressIf aborting didn't work and these files still exist, you can manually clean them:
# Remove merge state
rm -f .git/MERGE_HEAD
rm -f .git/MERGE_MSG
rm -f .git/MERGE_MODE
# Remove revert state
rm -f .git/REVERT_HEAD
# Remove cherry-pick state
rm -f .git/CHERRY_PICK_HEAD
# Remove rebase state
rm -rf .git/rebase-merge
rm -rf .git/rebase-applyThen run:
git statusUnderstanding why the conflict occurred helps prevent future issues:
View the commit you're trying to revert:
git show <commit-hash>See what files were changed in that commit:
git diff-tree --no-commit-id --name-only -r <commit-hash>Compare the conflicting versions:
# Show the common ancestor version
git show :1:src/app.js > /tmp/base.js
# Show your version (HEAD)
git show :2:src/app.js > /tmp/ours.js
# Show their version (the commit being merged/reverted)
git show :3:src/app.js > /tmp/theirs.js
# Compare them
diff /tmp/ours.js /tmp/theirs.jsThis helps you understand what changes are conflicting and make informed decisions about resolution.
To avoid unmerged files blocking your workflow:
1. Always complete or abort operations before starting new ones:
# Check status before any significant operation
git status
# If there's an operation in progress, handle it first2. Configure Git to help catch conflicts:
# Enable rerere to remember conflict resolutions
git config --global rerere.enabled true3. Use a merge tool for complex conflicts:
# Launch configured merge tool
git mergetool
# Popular merge tools: vimdiff, meld, kdiff3, vscode
git config --global merge.tool vscode
git config --global mergetool.vscode.cmd 'code --wait $MERGED'4. Consider using Git hooks to prevent commits with conflict markers:
# .git/hooks/pre-commit
#!/bin/sh
if git diff --cached --diff-filter=ACM | grep -q '^+.*<<<<<<< '; then
echo "Error: Conflict markers found in staged files"
exit 1
fiUnderstanding Git's operation states:
Git uses various files in the .git directory to track ongoing operations:
- MERGE_HEAD: Points to the commit being merged
- REVERT_HEAD: Points to the commit being reverted
- CHERRY_PICK_HEAD: Points to the commit being cherry-picked
- ORIG_HEAD: Stores the previous HEAD position before destructive operations
Using git rerere (Reuse Recorded Resolution):
If you frequently encounter similar conflicts, enable rerere:
git config --global rerere.enabled trueGit will remember how you resolved conflicts and automatically apply the same resolution if the same conflict occurs again. This is especially useful during rebases where you might resolve the same conflict multiple times.
The difference between merge, revert, and reset:
- git merge: Combines two branches, creating a new commit with two parents
- git revert: Creates a new commit that undoes the changes from a specific commit (safe, preserves history)
- git reset: Moves the branch pointer, potentially discarding commits (rewrites history)
When conflicts cascade:
If you're reverting a merge commit, you need to specify which parent to revert relative to:
# Revert merge commit, keeping changes from the first parent (usually main)
git revert -m 1 <merge-commit-hash>Without -m, Git won't know which side of the merge to consider as the baseline for the revert.
Scripting around this error:
In CI/CD scripts, you might want to handle this error gracefully:
#!/bin/bash
set -e
# Check if there are unmerged files
if git ls-files -u | grep -q .; then
echo "Unmerged files detected, cleaning up..."
git merge --abort 2>/dev/null || git revert --abort 2>/dev/null || git reset --hard HEAD
fi
# Now safe to revert
git revert --no-edit <commit-hash>kex_exchange_identification: Connection closed by remote host
Connection closed by remote host when connecting to Git server
fatal: unable to access: Proxy auto-configuration failed
How to fix 'Proxy auto-configuration failed' in Git
fatal: unable to access: Authentication failed (proxy requires basic auth)
How to fix 'Authentication failed (proxy requires basic auth)' in Git
fatal: unable to access: no_proxy configuration not working
How to fix 'no_proxy configuration not working' in Git
fatal: unable to read tree object in treeless clone
How to fix 'unable to read tree object in treeless clone' in Git