Master the art of diagnosing and fixing Git issues to recover from mistakes and keep your workflow smooth.
Git error messages often contain valuable information for troubleshooting:
| Error Message | Likely Cause | Solution |
|---|---|---|
fatal: not a git repository |
Command run outside of git repo | Navigate to repo directory or initialize one |
error: failed to push some refs |
Remote contains work you don't have locally | Pull or fetch before pushing |
fatal: refusing to merge unrelated histories |
Trying to merge repositories with no common ancestor | Use --allow-unrelated-histories flag |
fatal: remote origin already exists |
Attempting to add a remote that's already defined | Use git remote set-url instead |
error: Your local changes would be overwritten |
Uncommitted changes conflict with pull | Commit, stash, or discard changes first |
Git errors typically follow this pattern:
error/fatal: <specific error message>
hint: <helpful suggestion on what to do next>
When troubleshooting:
- Read the entire error message carefully
- Look for hints that Git provides
- Check for any file paths or refs mentioned in the error
💡 Tip: Run
git statusimmediately after encountering an error for additional context about the state of your repository.
Fix the most recent commit:
# Change the commit message of the last commit
git commit --amend -m "New commit message"
# Add forgotten files to the last commit without changing the message
git add forgotten-file.txt
git commit --amend --no-edit
# Change author information for the last commit
git commit --amend --author="New Name <email@example.com>"
⚠️ Warning: Never amend commits that have been pushed to a shared repository unless you're absolutely sure no one has based work on them.
Undo commits with different levels of aggressiveness:
# Soft reset - keep changes staged
git reset --soft HEAD~1 # Undo last commit, keep changes staged
# Mixed reset (default) - keep changes but unstaged
git reset HEAD~1 # Undo last commit, keep changes unstaged
# Hard reset - discard changes completely
git reset --hard HEAD~1 # ⚠️ Undo last commit AND discard changes
# Reset to a specific commit
git reset --hard 7abc123 # ⚠️ Reset to specific commit and discard changes
# Reset a single file to a previous version
git reset 7abc123 -- path/to/file.txt
⚠️ Warning:--hardpermanently discards changes. However, you can still recover commits with reflog (see below).
Create new commits that undo previous changes:
# Revert the most recent commit
git revert HEAD
# Revert a specific commit
git revert 7abc123
# Revert multiple commits
git revert 7abc123..9def456
# Revert a merge commit
git revert -m 1 merge_commit_hash💡 Tip: Use revert when you need to undo changes that have already been shared with others.
Apply specific commits from one branch to another:
# Apply a single commit to current branch
git cherry-pick 7abc123
# Cherry-pick without committing changes
git cherry-pick -n 7abc123
# Cherry-pick a range of commits
git cherry-pick 7abc123^..9def456Modify multiple commits in sequence:
# Interactively rebase the last 3 commits
git rebase -i HEAD~3
# Rebase onto a specific commit
git rebase -i 7abc123Interactive rebase commands:
pick- Keep the commit as isreword- Change the commit messageedit- Pause to amend the commitsquash- Combine with previous commit (keeps both messages)fixup- Combine with previous commit (discard this message)drop- Remove the commit entirely
💡 Tip: Interactive rebase can solve many complex problems but use with caution on public history.
Git keeps a log of all reference updates (reflog) for typically 90 days:
# View reflog for HEAD
git reflog
# View reflog for a specific branch
git reflog show branch-name
# Restore to a specific reflog entry
git checkout HEAD@{2} # Go to where HEAD was 2 moves ago
git branch recovered-branch HEAD@{2} # Create branch at that pointExample reflog output:
734713b HEAD@{0}: commit: Fix typo in README
a72f9c4 HEAD@{1}: reset: moving to HEAD~1
d29eb23 HEAD@{2}: commit: Work that was undone by reset
Recover work after an accidental reset:
# Find the SHA of the deleted commit in the reflog
git reflog
# Create a new branch pointing to the lost commit
git branch recovered-work d29eb23 # SHA from reflog
# Or reset your current branch to the lost commit
git reset --hard d29eb23Restore a branch that was accidentally deleted:
# Find the SHA of the branch's last commit
git reflog
# Recreate the branch at that commit
git branch deleted-branch d29eb23 # SHA from reflogFind commits that aren't referenced by any branch or tag:
# Find dangling commits
git fsck --lost-found
# Examine a specific dangling commit
git show <sha>
# Create a branch to rescued dangling commit
git branch rescued-work <sha>Recover stashed work:
# List all stashes
git stash list
# Recover a dropped stash (if it's still in reflog)
git fsck --no-reflog | grep commit | cut -d' ' -f3 | xargs git show --summary
# Apply a specific stash
git stash apply stash@{n}
# Create a branch from a stash
git stash branch new-branch stash@{0}When Git can't automatically merge changes, it marks conflicts in files like this:
<<<<<<< HEAD
This is the change in the current branch
=======
This is the incoming change from the other branch
>>>>>>> feature-branch
Understanding conflict markers:
<<<<<<< HEAD- Beginning of changes in your current branch=======- Separator between the conflicting changes>>>>>>> feature-branch- End of changes from the branch being merged in
Steps to manually resolve conflicts:
# 1. Identify conflicted files
git status
# 2. Open and edit the files to fix conflicts
# 3. Remove conflict markers and keep what you want
# 4. Mark conflicts as resolved
git add resolved-file.txt
# 5. Continue the merge
git merge --continue
# Or for older Git versions
git commitResolve conflicts using visual tools:
# Configure your preferred merge tool (one-time setup)
git config --global merge.tool kdiff3
# Launch configured merge tool for all conflicts
git mergetool
# Launch for specific file
git mergetool path/to/file.txtPopular merge tools:
- VS Code
- KDiff3
- Meld
- Beyond Compare
- P4Merge
Cancel a merge in progress:
# Abort the current merge and restore pre-merge state
git merge --abortHandle conflicts during a rebase:
# During a rebase with conflicts:
# 1. Resolve the conflicts manually in the files
# 2. Add resolved files
git add resolved-file.txt
# 3. Continue the rebase
git rebase --continue
# Or to skip the current commit
git rebase --skip
# Or to abort the entire rebase
git rebase --abortDiagnose and improve Git performance:
# Check repository size
git count-objects -vH
# Run garbage collection to optimize repository
git gc
# Aggressively optimize the repository
git gc --aggressive
# Prune all unreachable objects
git pruneStrategies for large files:
# Configure Git LFS (Large File Storage)
git lfs install
# Track large file patterns with LFS
git lfs track "*.psd"
git lfs track "*.zip"
# Verify tracking
git lfs ls-files
# Clone a repository with LFS objects
git lfs clone <repository-url>Remove large files from history:
# Find the largest objects in your repository
git rev-list --objects --all | git cat-file --batch-check='%(objecttype) %(objectname) %(objectsize) %(rest)' | sed -n 's/^blob //p' | sort -k2nr | head -10
# Use git-filter-repo to remove large files
# First, install git-filter-repo
git filter-repo --path path/to/large/file --invert-paths --force
# Garbage collect after filtering
git gc --aggressive --prune=now
⚠️ Warning: Rewriting history with tools likegit filter-repowill change all commit hashes. Only use on repositories where you can force-push and other collaborators can handle the change.
Reduce clone size and time:
# Shallow clone with limited history
git clone --depth=1 <repository-url>
# Clone only specific branches
git clone --single-branch --branch main <repository-url>
# Fetch additional history later
git fetch --unshallow
# Partial clone (Git 2.22+)
git clone --filter=blob:none <repository-url>Fix the "detached HEAD" state:
# Check if you're in detached HEAD state
git status
# Create a new branch at current position
git branch new-branch-name
# Switch to the new branch to save your work
git checkout new-branch-name
# Alternative: create and switch in one command
git checkout -b new-branch-nameFix branches pointing to invalid commits:
# Reset branch to a known good commit
git checkout broken-branch
git reset --hard 7abc123
# Force update a remote branch
git push --force-with-lease origin broken-branchUndo a problematic merge:
# Revert a merge commit
git revert -m 1 <merge-commit-hash>
# Reset to before the merge (if not yet pushed)
git reset --hard HEAD~1Manage obsolete branches:
# List merged branches that can be safely deleted
git branch --merged
# Delete local branches that have been merged
git branch -d branch-name
# Force delete a branch regardless of merge status
git branch -D branch-name
# Delete remote branch
git push origin --delete branch-name
# Prune tracking branches no longer on remote
git fetch --pruneHandle common remote operation issues:
# Fix "non-fast-forward" push rejection
git pull --rebase origin main
git push origin main
# Force push when necessary (use with caution!)
git push --force-with-lease origin main
# Set upstream for current branch
git branch --set-upstream-to=origin/main main
# Retrieve changes without merging
git fetch origin
⚠️ Warning: Force pushing (git push --force) overwrites the remote history and can cause serious problems for collaborators. Prefer using--force-with-leasewhich fails if there are upstream changes you don't have.
Diagnose and fix connection problems:
# Test SSH connection to GitHub
ssh -T git@github.com
# Test connection with verbose output
ssh -vT git@github.com
# Set higher timeout for slow connections
git config --global http.lowSpeedLimit 1000
git config --global http.lowSpeedTime 60Handle divergent branches:
# See how branches have diverged
git log --graph --oneline --all
# For diverged branches, pull with rebase
git pull --rebase
# Pull with specific strategy
git pull --strategy recursive --strategy-option theirsRepair invalid remote settings:
# Update remote URL
git remote set-url origin https://github.com/username/repo.git
# Remove and add remote
git remote remove origin
git remote add origin https://github.com/username/repo.git
# Prune deleted remote branches
git remote prune origin
# Reset to exactly match remote branch
git fetch origin
git reset --hard origin/mainTroubleshoot and fix SSH key problems:
# Verify your SSH key is being used
ssh -vT git@github.com
# Start SSH agent
eval "$(ssh-agent -s)"
# Add private key to the agent
ssh-add ~/.ssh/id_rsa
# Create a new SSH key
ssh-keygen -t ed25519 -C "your_email@example.com"
# Copy public key to clipboard (Linux)
cat ~/.ssh/id_ed25519.pub | xclip -selection clipboard
# Copy public key to clipboard (macOS)
cat ~/.ssh/id_ed25519.pub | pbcopy
# Windows (PowerShell)
Get-Content ~/.ssh/id_ed25519.pub | Set-ClipboardFix password caching issues:
# View current credential helper
git config --global --get credential.helper
# Reset credential helper
git config --global --unset credential.helper
# Set a new credential helper
# For Windows
git config --global credential.helper manager-core
# For macOS
git config --global credential.helper osxkeychain
# For Linux
git config --global credential.helper 'cache --timeout=3600'
# For plaintext storage (not secure but simple)
git config --global credential.helper storeFix permission-related problems:
# Check your access level on a repository
ssh git@github.com info
# Fix permissions for SSH key files
chmod 600 ~/.ssh/id_rsa
chmod 644 ~/.ssh/id_rsa.pub
# Fix "Permission denied" errors
ssh -T git@github.com
# Switch from SSH to HTTPS temporarily
git remote set-url origin https://github.com/username/repo.gitHandle issues with executable permission bit changes:
# Prevent Git from tracking file permission changes
git config core.fileMode false
# Fix specific file permissions
git update-index --chmod=+x script.sh # Make executable
git update-index --chmod=-x script.sh # Remove executable bitFix line ending conversion problems:
# Configure line endings appropriately
# For Windows
git config --global core.autocrlf true
# For macOS/Linux
git config --global core.autocrlf input
# Fix EOL issues for a specific file
git add --renormalize file.txt
# Renormalize the entire repo
git add --renormalize .
git commit -m "Normalize line endings"Handle permission changes showing as modifications:
# Make Git ignore permission changes
git config core.filemode false
# Reset file permissions without changing content
git checkout-index --force --all| Problem | Command | Description |
|---|---|---|
| Fix Last Commit | git commit --amend |
Change last commit |
| Undo Last Commit | git reset HEAD~1 |
Undo commit, keep changes |
| Discard All Changes | git reset --hard HEAD |
Remove all uncommitted changes |
| View History Log | git reflog |
Show reference history |
| Recover Deleted Work | git branch recover-branch HEAD@{n} |
Create branch from reflog |
| Abort Merge | git merge --abort |
Cancel current merge |
| Fix Detached HEAD | git checkout -b new-branch |
Create branch at current position |
| Force Push Safely | git push --force-with-lease |
Force push with safeguard |
| Clean Repo | git gc --aggressive |
Optimize repository |
- Git configuration and command shortcuts
- Advanced Git techniques and features
- Combining branches with merge and rebase operations
- Working with remote repositories (push, pull, fetch)