Git Troubleshooting Guide: Step-by-Step Problem Resolution
The Systematic Approach to Git Troubleshooting
Git problems can be frustrating, but most have systematic solutions. This guide takes a symptom-based approachβyou identify what's going wrong, and we provide step-by-step diagnostic commands and solutions. From authentication failures to merge conflicts, corrupted indexes to slow performance, you'll find practical fixes for real-world problems.
Core principle: Always diagnose before fixing. Git provides extensive debugging tools (GIT_TRACE, git fsck, git remote -v show) that reveal what's actually happening. Use these to understand the problem before applying solutions.
Quick Reference: Common Error Messages
| Error Message | Likely Cause | Quick Fix |
|---|---|---|
fatal: not a git repository |
Not in a Git repo or .git folder corrupted | Run git init or check parent directories |
Permission denied (publickey) |
SSH key issues | Check SSH agent and key permissions |
! [rejected] main -> main (non-fast-forward) |
Remote has changes you don't have | git pull first, then push |
error: failed to push some refs |
Branch protection or divergence | git pull --rebase then push |
fatal: refusing to merge unrelated histories |
Branches with no common ancestor | git merge --allow-unrelated-histories |
CONFLICT (content): Merge conflict |
Same file changed differently | Resolve conflicts manually |
Diagnostic Tools: Understanding What's Wrong
1. Git Trace Mode
Enable verbose debugging to see exactly what Git is doing:
$ GIT_TRACE=1 git status
# Trace network operations
$ GIT_CURL_VERBOSE=1 git push
$ GIT_SSH_COMMAND="ssh -vvv" git fetch
# Trace packfile operations
$ GIT_TRACE_PACKET=1 git fetch
What to look for: The trace output shows every command Git executes internally, network requests, and where failures occur. This is invaluable for authentication and protocol issues.
2. Repository Integrity Check
$ git fsck --full
# Check for dangling objects (lost data)
$ git fsck --lost-found
# Verify packfiles
$ git verify-pack -v .git/objects/pack/*.idx
3. Remote Connection Diagnostics
$ git ls-remote origin
# Show remote details
$ git remote -v show origin
# Check SSH connection
$ ssh -T git@github.com # GitHub test
$ ssh -T git@gitlab.com # GitLab test
Symptom Category 1: Authentication and Access Problems
Diagnosis Steps:
$ eval "$(ssh-agent -s)"
# 2. List loaded keys
$ ssh-add -l
# 3. Test SSH connection
$ ssh -T git@github.com
# Expected: "Hi username! You've successfully authenticated"
# 4. Check key permissions
$ ls -la ~/.ssh/
$ chmod 600 ~/.ssh/id_rsa # Private key must be 600
$ chmod 644 ~/.ssh/id_rsa.pub # Public key can be 644
Solutions:
- Add your key to SSH agent:
ssh-add ~/.ssh/your_key - Add key to GitHub/GitLab: Copy
cat ~/.ssh/id_rsa.pubto hosting service - Check remote URL:
git remote -vshould use git@, not https:// - Fix remote URL:
git remote set-url origin git@github.com:user/repo.git - Create config file: ~/.ssh/config with Host-specific settings
Host github.com
HostName github.com
User git
IdentityFile ~/.ssh/github_key
IdentitiesOnly yes
Diagnosis:
$ git config --global credential.helper
# On macOS, check Keychain
$ git credential-osxkeychain get
# On Windows, check Credential Manager
$ cmdkey /list
Solutions:
- Update credential helper:
git config --global credential.helper osxkeychain(macOS) - Use personal access token: GitHub no longer accepts passwords
- Cache credentials:
git config --global credential.helper 'cache --timeout=3600' - Switch to SSH:
git remote set-url origin git@github.com:user/repo.git
Symptom Category 2: Push/Pull Problems
What's happening:
The remote branch has commits you don't have locally. Git refuses to overwrite them.
Diagnosis:
$ git fetch origin
$ git log origin/main --oneline
# Compare local and remote
$ git log HEAD..origin/main --oneline # Commits you're missing
Solutions:
- Merge approach:
$ git pull origin main
$ git push origin main - Rebase approach (cleaner history):
$ git pull --rebase origin main
$ git push origin main - If you're sure you want to overwrite (use with caution):
$ git push --force-with-lease origin main
β οΈ Never use --force on shared branches. Use --force-with-lease which checks that your local branch matches the remote before force-pushing.
What's happening:
You have uncommitted changes that conflict with incoming changes. Git protects you from losing work.
Solutions:
- Commit your changes (recommended):
$ git add .
$ git commit -m "WIP: local changes" - Stash temporarily:
$ git stash push -m "temp-work"
$ git pull
$ git stash pop # May cause conflicts - Discard changes (careful!):
$ git reset --hard HEAD # Loses uncommitted work
View stash contents before applying:
$ git stash show -p stash@{0}
What's happening:
You're trying to merge two branches that don't share a common commit. Common when merging different repositories or after --orphan branches.
Solutions:
- Allow unrelated histories (if intentional):
$ git pull origin main --allow-unrelated-histories
- If merging different repositories:
$ git remote add other ../other-repo
$ git fetch other
$ git merge other/main --allow-unrelated-histories - First, verify this is what you want: Check that you're not accidentally mixing projects.
Symptom Category 3: Merge and Rebase Conflicts
Understanding conflict markers:
<<<<<<< HEAD
This is your current change
=======
This is the incoming change
>>>>>>> branch-name
Step-by-step resolution:
- Identify conflicted files:
git status - Open each conflicted file in your editor
- Choose the correct version:
- Keep your changes (before ======)
- Keep their changes (after ======)
- Combine both (edit manually)
- Remove conflict markers (<<<, ===, >>>)
- Mark as resolved:
git add [file] - Complete the merge:
git commit
Using merge tools:
$ git config --global merge.tool vscode
$ git config --global mergetool.vscode.cmd 'code --wait $MERGED'
# Launch merge tool
$ git mergetool
Abort if things go wrong:
$ git rebase --abort
Common situations:
- You're in the middle of a rebase with conflicts
- Git shows "rebase in progress" when you try other commands
Solutions:
- Continue after resolving conflicts:
$ git add [resolved-files]
$ git rebase --continue - Skip this commit:
$ git rebase --skip
- Abort entirely:
$ git rebase --abort
Symptom Category 4: Index and Working Tree Issues
What's happening:
The Git index (.git/index) is corrupted. This file tracks staged changes.
Solution:
$ cp .git/index .git/index.backup
# Remove corrupted index
$ rm .git/index
# Rebuild index from HEAD
$ git reset
# Restage any unstaged changes
$ git status # Check what needs re-adding
Diagnosis:
$ git check-ignore -v node_modules/
# See why a file isn't being ignored
$ git status --ignored
Solutions:
- Update .gitignore:
$ echo "node_modules/" >> .gitignore
$ git add .gitignore - Remove already tracked files that should be ignored:
$ git rm -r --cached node_modules/
$ git commit -m "Remove node_modules from git" - Global gitignore for all repos:
$ git config --global core.excludesfile ~/.gitignore_global
Symptom Category 5: Repository Corruption
Diagnosis:
error: object file .git/objects/ab/cdef123... is empty
Solutions (in order of safety):
Option 1: Restore from remote (if available)
$ cp -r . ../repo-backup
# Clone fresh copy
$ cd ..
$ git clone [remote-url] fresh-repo
# Copy over uncommitted changes
$ cp -r repo-backup/* fresh-repo/ (except .git)
Option 2: Repair from other clones
$ git remote add healthy ../healthy-repo
$ git fetch healthy
# Replace missing objects
$ git fsck --full # Check if fixed
Option 3: Manual object recovery
$ git fsck --full > missing.txt
# Try to restore from packfiles
$ git unpack-objects < .git/objects/pack/pack-[name].pack
Symptom Category 6: Performance Issues
Diagnosis:
$ 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 -10
Solutions:
- Run garbage collection:
$ git gc --aggressive --prune=now
- Enable filesystem monitor:
$ git config core.fsmonitor true
- Use shallow clone for CI:
$ git clone --depth 1 [url]
- Move large files to Git LFS:
$ git lfs track "*.psd"
$ git add .gitattributes
Symptom Category 7: Hook and Script Issues
Diagnosis:
$ ls -la .git/hooks/
$ chmod +x .git/hooks/pre-commit
# Test hook directly
$ .git/hooks/pre-commit
Solutions:
- Make hooks executable:
chmod +x .git/hooks/* - Check shebang line: First line should be
#!/bin/shor#!/usr/bin/env bash - Bypass hooks temporarily:
git commit --no-verify - Use hook managers: husky for npm, pre-commit framework
Symptom Category 8: Submodule Problems
Common submodule problems:
Problem: Submodule shows as modified but no changes
$ git submodule update --init --recursive
Problem: Submodule not updating
$ git add .
$ git commit -m "Update submodules"
Problem: Cloned repo missing submodules
# Or after clone:
$ git submodule update --init --recursive
Symptom Category 9: Environment and Configuration
Diagnosis:
$ git config --list --show-origin
# Check specific values
$ git config user.name
$ git config user.email
Solutions:
$ git config --global user.name "Your Name"
$ git config --global user.email "your@email.com"
# Set per repository
$ git config user.name "Project Specific Name"
# Override for specific directory
$ git config --global includeIf.gitdir:~/work/.path ~/.gitconfig-work
Git Troubleshooting Cheat Sheet
| Problem | Diagnostic Command | Fix Command |
|---|---|---|
| Can't push | git fetch; git log HEAD..origin/main |
git pull --rebase |
| Wrong author | git log --pretty=full |
git commit --amend --reset-author |
| Lost commits | git reflog |
git branch recover [hash] |
| SSH issues | ssh -vT git@github.com |
ssh-add ~/.ssh/key |
| Merge conflicts | git status |
Manual resolution or git mergetool |
| Corrupt index | git fsck |
rm .git/index; git reset |
Git Debugging Environment Variables
| Variable | Purpose |
|---|---|
GIT_TRACE=1 |
Trace all Git commands |
GIT_CURL_VERBOSE=1 |
Debug HTTP/HTTPS operations |
GIT_SSH_COMMAND="ssh -vvv" |
Debug SSH connections |
GIT_TRACE_PACKET=1 |
Debug network protocol |
GIT_TRACE_PERFORMANCE=1 |
Debug performance issues |
GIT_TRACE_SETUP=1 |
Debug repository discovery |
Emergency Recovery Script
# git-emergency.sh - Run when things go wrong
echo "=== GIT EMERGENCY DIAGNOSTIC ==="
echo "1. Repository status:"
git status
echo "2. Recent reflog entries:"
git reflog | head -10
echo "3. Repository integrity:"
git fsck --full
echo "4. Remote connectivity:"
git remote -v
git ls-remote origin HEAD
echo "5. Configuration:"
git config --list | head -20
echo "6. Unreachable objects:"
git fsck --unreachable | head -10
echo "7. Large files:"
git rev-list --objects --all | git cat-file --batch-check='%(objecttype) %(objectname) %(objectsize) %(rest)' | grep "^blob" | sort -k3 -n -r | head -5
Frequently Asked Questions
If you're in the middle of a rebase and things go wrong, you have several options:
- Abort completely:
git rebase --abort- returns to pre-rebase state - Skip current commit:
git rebase --skip- if you want to omit this commit - Continue after fixes:
git add . && git rebase --continue - If you already completed the rebase but want to undo:
git reflogto find pre-rebase commit, thengit reset --hard [hash]
This typically happens with HTTPS remotes. Solutions:
- Cache credentials:
git config --global credential.helper cache - Use credential manager: On Windows: Git Credential Manager; on macOS: osxkeychain
- Switch to SSH: Generate SSH key and update remote URL to git@github.com:user/repo.git
- Use personal access token: GitHub no longer accepts passwords; use tokens instead
This error means Git can't find a tree object. Recovery steps:
- Run
git fsck --fullto identify missing objects - If you have another clone, fetch missing objects:
git remote add backup ../other-repo; git fetch backup - If the missing object is in a packfile, try:
git unpack-objects < .git/objects/pack/*.pack - As last resort, clone fresh from remote and reapply local changes
This is usually a network/SSL issue. Try these solutions:
- Increase buffer size:
git config http.postBuffer 524288000 - Disable SSL verification (temporary):
git config http.sslVerify false - Use SSH instead of HTTPS
- Check network stability and VPN/proxy settings
- Try shallow clone:
git clone --depth 1 [url]
Use Git's performance tracing:
GIT_TRACE_PERFORMANCE=1 git status- shows timing of each operationGIT_TRACE=1 git fetch- shows detailed operation log- Check repository size:
git count-objects -vH - Enable filesystem monitor:
git config core.fsmonitor true - Run garbage collection:
git gc --aggressive