Git is powerful but sometimes things go wrong. This guide provides solutions to common problems and strategies for recovering from difficult situations.
Undoing Changes
I Made a Mistake in the Last Commit
You can amend the most recent commit:
# Fix the mistake
# Stage the corrected files
git add fixed-file.js
# Amend the commit
git commit --amend
# Keep the same message
git commit --amend --no-edit
Only amend commits that haven’t been pushed to a shared repository. Amending published commits requires force pushing and can cause problems for collaborators.
I Committed to the Wrong Branch
Move the commit to the correct branch:
Note the commit hash
git log -1 # Copy the commit hash
Switch to the correct branch
git switch correct-branch
Cherry-pick the commit
git cherry-pick <commit-hash>
Remove from wrong branch
git switch wrong-branch
git reset --hard HEAD~1 # If it's the last commit
# Or:
git revert <commit-hash> # If it's been pushed
I Need to Undo a Commit in the Main Branch
Use git revert to undo a commit that’s been pushed:
# Revert a single commit
git revert <commit-hash>
# Revert without creating a commit immediately
git revert -n <commit-hash>
# Revert a range of commits
git revert <older-commit>..<newer-commit>
# Revert a merge commit (specify which parent)
git revert -m 1 <merge-commit-hash>
git revert creates new commits that undo changes. This preserves history and is safe for shared branches. Use git reset only for local, unpushed commits.
I Accidentally Deleted a File
Restore deleted files:
# Restore a file from the index
git restore deleted-file.js
# Restore from a specific commit
git restore --source=HEAD~2 deleted-file.js
# Restore from a specific commit (old syntax)
git checkout <commit-hash> -- deleted-file.js
I Want to Discard All Local Changes
# Discard changes in working directory
git restore .
# Discard changes and staged files
git reset --hard HEAD
# Remove untracked files (use with caution!)
git clean -fd
# Preview what would be deleted
git clean -fdn
git reset --hard and git clean are destructive operations that permanently delete changes. Use with extreme caution!
Branch Issues
I Can’t Switch Branches Due to Uncommitted Changes
Save your changes temporarily:
# Stash changes
git stash push -m "Work in progress"
# Switch branches
git switch other-branch
# Return and restore changes
git switch original-branch
git stash pop
# Include untracked files
git stash push -u -m "Include untracked files"
I Deleted a Branch by Accident
Recover deleted branches:
Find the commit hash
git reflog
# Look for the branch deletion or last commit on that branch
Recreate the branch
git branch recovered-branch <commit-hash>
I Have Diverged Branches
When your branch and the remote have diverged:
# Check the situation
git status
# Your branch and 'origin/main' have diverged
# Option 1: Merge remote changes
git pull origin main
# Option 2: Rebase on remote
git pull --rebase origin main
# Option 3: Reset to remote (loses local commits!)
git reset --hard origin/main
# Option 4: Keep both (create a backup branch first)
git branch backup
git rebase origin/main
Merge and Rebase Issues
I Have Merge Conflicts
Resolve merge conflicts step by step:
Identify conflicted files
git status
# Unmerged paths:
# both modified: file.js
Open and resolve conflicts
Look for conflict markers:<<<<<<< HEAD
Your changes
=======
Their changes
>>>>>>> branch-name
Edit the file to keep the desired changes and remove the markers. Complete the merge
git commit # For merge conflicts
git rebase --continue # For rebase conflicts
Conflict resolution tools:
# Use a merge tool
git mergetool
# Accept all changes from one side
git checkout --ours file.js # Keep your version
git checkout --theirs file.js # Keep their version
git add file.js
# Show conflict in different formats
git diff # Standard diff
git diff --ours # Compare with your version
git diff --theirs # Compare with their version
I Want to Abort a Merge or Rebase
# Abort a merge
git merge --abort
# Abort a rebase
git rebase --abort
# Abort a cherry-pick
git cherry-pick --abort
# Abort applying patches
git am --abort
Rebase Broke My Branch
Recover from a bad rebase:
# Find the previous state
git reflog
# Find the entry before the rebase (e.g., HEAD@{3})
# Reset to before the rebase
git reset --hard HEAD@{3}
# Or create a new branch from that point
git branch recovery HEAD@{3}
Issues with Reverting a Merge
If you reverted a merge and now need to re-merge the branch:
Understanding the problem
When you revert a merge, Git remembers the merge base. Re-merging the same branch won’t include the original changes.
Revert the revert
# Find the revert commit
git log --oneline
# Revert the revert
git revert <revert-commit-hash>
Alternatively, if the branch was completely rebuilt:
# The rebuilt branch can be merged directly
git merge rebuilt-feature-branch
See the comprehensive explanation in Git documentation: git help workflows or search for “revert a faulty merge”.
Remote Repository Issues
Push Rejected: Updates Were Rejected
# Error: Updates were rejected because the tip of your current branch is behind
# Solution 1: Pull and merge
git pull origin main
git push origin main
# Solution 2: Pull and rebase
git pull --rebase origin main
git push origin main
# Solution 3: Force push (dangerous!)
# Only if you're certain no one else has pushed
git push --force-with-lease origin main
Never force push to shared branches without coordinating with your team. Use --force-with-lease instead of --force to avoid overwriting others’ work.
Wrong Remote URL
Fix incorrect remote URLs:
# Check current URL
git remote -v
# Change remote URL
git remote set-url origin https://github.com/correct/repo.git
# Verify the change
git remote -v
Can’t Push: Repository Not Found
Common authentication issues:
# For HTTPS: Update credentials
git credential reject
# Then push again and enter correct credentials
# Switch from HTTPS to SSH
git remote set-url origin git@github.com:user/repo.git
# For SSH: Check your SSH keys
ssh -T git@github.com
File and History Issues
File Always Shows as Modified
Common causes and solutions:
Case sensitivity issues (Windows/macOS):
# Remove the duplicate file
git rm --cached AFile.txt
git commit -m "Remove case conflict"
git checkout .
Line ending issues:
# Normalize line endings
git add --renormalize .
git commit -m "Normalize line endings"
# Configure line ending handling
git config --global core.autocrlf input # Linux/macOS
git config --global core.autocrlf true # Windows
File permissions:
# Ignore file mode changes
git config core.fileMode false
Accidentally Committed Large Files
Remove large files from history:
# Using git filter-repo (recommended)
git filter-repo --path large-file.zip --invert-paths
# Force push to update remote
git push --force origin main
# Using BFG Repo-Cleaner
bfg --delete-files large-file.zip
git reflog expire --expire=now --all
git gc --prune=now --aggressive
Rewriting history affects all collaborators. Coordinate with your team and have everyone re-clone or reset their local copies.
Accidentally Committed Secrets
Remove sensitive data immediately:
Remove from history
git filter-repo --path secrets.env --invert-paths
Force push
git push --force origin --all
git push --force origin --tags
Rotate credentials
Immediately change any exposed passwords, API keys, or tokens. Removing from Git is not enough - the secrets are compromised.
Notify your team
All collaborators must re-clone the repository or reset their local copies.
Files Ignored But Still Tracked
Gitignore only affects untracked files:
# Remove from Git but keep locally
git rm --cached file-to-ignore.log
git commit -m "Stop tracking file"
# Add to .gitignore
echo "file-to-ignore.log" >> .gitignore
git add .gitignore
git commit -m "Update .gitignore"
Advanced Recovery
Lost Commits (Detached HEAD)
Recover commits made in detached HEAD state:
Find the lost commit
git reflog
# Look for your lost commit
Create a branch
git branch recovered <commit-hash>
Merge or cherry-pick
git switch main
git merge recovered
Repository Corruption
Recover from corrupted objects:
# Verify repository integrity
git fsck --full
# Try to recover
git reflog expire --expire=now --all
git gc --prune=now --aggressive
# If still corrupted, clone fresh and copy working directory
git clone <remote-url> fresh-clone
cp -r original/.git/config fresh-clone/.git/
cd fresh-clone
git reset --hard
Recovering Deleted Stashes
# Find lost stash
git fsck --no-reflog | grep commit
# Try each commit to find your stash
git show <commit-hash>
# Apply the stash
git stash apply <commit-hash>
Git Operations Are Slow
Optimize repository performance:
# Garbage collection
git gc --aggressive --prune=now
# Repack objects
git repack -Ad
# Check repository size
git count-objects -vH
# Find large files
git rev-list --objects --all | \
git cat-file --batch-check='%(objecttype) %(objectname) %(objectsize) %(rest)' | \
grep '^blob' | sort -k3 -n -r | head -20
Large Repository Issues
Strategies for large repositories:
# Shallow clone (limited history)
git clone --depth 1 <url>
# Partial clone (lazy object fetching)
git clone --filter=blob:none <url>
# Sparse checkout (limited working tree)
git sparse-checkout init --cone
git sparse-checkout set src/important-module
Getting Help
Diagnostic Commands
# Check repository status
git status
# View recent actions
git reflog
# Check branch relationships
git log --oneline --graph --all
# View configuration
git config --list --show-origin
# Check remote connectivity
git ls-remote origin
# Verbose output for debugging
GIT_TRACE=1 git pull
GIT_CURL_VERBOSE=1 git push
When All Else Fails
If you’re truly stuck:
- Don’t panic: Most situations are recoverable
- Back up: Copy the entire
.git directory before trying risky operations
- Use reflog:
git reflog is your friend for recovery
- Ask for help: Git community is helpful on Stack Overflow and forums
- Start fresh: As a last resort, clone fresh and manually copy over changes
The command git reflog shows the history of where HEAD has been. This is invaluable for recovery and can save you from almost any mistake.
Prevention Tips
- Commit often: Small commits are easier to manage
- Use branches: Experiment safely without affecting main work
- Pull before push: Stay synchronized with the team
- Check before committing: Review
git status and git diff
- Test before pushing: Run tests locally
- Back up important work: Push to a remote or create backup branches
- Learn incrementally: Master basics before advanced features
- Use Git hooks: Automate checks to prevent common mistakes