Git Gone Wrong? Fix Common Git Mistakes Quickly
Git is an indispensable tool for modern software development, enabling collaboration, version control, and efficient project management. However, even experienced developers can stumble upon common Git mistakes that can disrupt workflows and even break projects. This tutorial outlines frequent Git mishaps and provides practical solutions to get you back on track. Learn how to avoid these pitfalls and maintain a healthy Git repository.
TL;DR – Fast Fix Cheatsheet
# See where HEAD moved (recover lost commits)
git reflog
# Recover a deleted branch (find commit from reflog)
git checkout -b <branch> <commit> # or: git branch <branch> <commit>
# Undo last commit but keep changes
git reset --soft HEAD~1
# Revert a bad commit on a shared branch (history-safe)
git revert <commit>
# Unstage files
git reset HEAD <file> # one file
git reset HEAD . # all
# Stash work (before switching branches)
git stash push -m "wip: doing X"
git stash list
git stash pop
# Safer force-push (don’t overwrite others)
git push --force-with-lease
# Update feature branch cleanly
git pull --rebase origin main
What Are the Most Common Git Mistakes and Their Solutions?
The most common Git mistakes include accidentally committing sensitive data, force pushing without understanding the consequences, losing commits, and merge conflicts. Each of these issues has targeted fixes; prevention mostly comes from adopting safe defaults and disciplined workflows.
Force Pushing: The Good, the Bad, and the Ugly
Force pushing (git push --force
or git push --force-with-lease
) can rewrite remote history and overwrite teammates’ work.
How to Recover from a Bad Force Push
- Notify your team. You may have overwritten remote commits.
- Find lost commits:
git reflog
- Create a temporary branch at the lost commit:
git branch temp-branch <commit-hash>
- Merge or cherry-pick back:
# Option 1: merge all recovered changes git merge temp-branch # Option 2: cherry-pick specific commits git cherry-pick <commit-hash>
- Push the corrected branch:
git push origin <branch>
main
. If you must rewrite history, prefer git push --force-with-lease
, which refuses to overwrite unseen remote updates.
How to Remove Sensitive Data (Passwords, API Keys) from Git
Leaked secrets require rewriting history and rotating credentials. git filter-repo
is the recommended tool (faster/safer than filter-branch
).
Install git filter-repo
# Python/pip (often the easiest)
pip install git-filter-repo
# macOS (Homebrew)
brew install git-filter-repo
Remove Files or Blobs from History
# Remove a file everywhere in history (e.g., .env)
git filter-repo --force --path .env --invert-paths
# Strip a specific blob if you know the blob-id
git filter-repo --strip-blobs-with-ids <blob-id>
# After rewriting, rotate credentials immediately and push cleaned history
git push --force-with-lease origin <branch>
.gitignore
, use environment variables or a secrets manager, and enable secret scanning (e.g., Gitleaks, TruffleHog, GitHub secret scanning) via pre-commit or CI.
Merge Conflicts: Resolving the Inevitable
Conflicts occur when changes overlap and Git can’t automatically merge.
How to Resolve Merge Conflicts
- Identify conflicts: check
git merge
/git rebase
output orgit status
. - Open conflicting files and find markers:
<<<<<<< HEAD ======= >>>>>>> branch-name
- Edit, choose/merge lines, and delete markers.
- Stage and complete:
git add <resolved-file> # If merging: git commit -m "Resolve merge conflicts" # If rebasing: git rebase --continue
Recover Lost Commits with Git Reflog
Deleted a branch or broke a rebase? git reflog
tracks where HEAD
and branches have been.
# Inspect recent movements
git reflog
# Create a branch at a previously recorded commit
git checkout -b recover-branch <commit>
# Bring back specific changes
git cherry-pick <commit>
Detached HEAD State: Getting Back on Track
Working on a commit directly (not a branch) puts you in a detached HEAD state; changes aren’t attached to a branch.
# Attach current work to a new branch
git checkout -b my-fix
Staging Specific Lines: Mastering git add -p
git add -p <file>
# At the prompt:
# y = stage, n = skip, s = split, e = edit, q = quit, ? = help
git diff
(working vs staged) and git diff --staged
(staged vs last commit) before committing.
Ignoring Files: The Power of .gitignore
- Create a
.gitignore
at the repo root. - Add patterns (one per line; wildcards allowed).
- Commit the file.
# Dependencies
node_modules/
# Environment files
.env
.env.*
# Build artifacts
dist/
build/
# OS/editor junk
.DS_Store
Thumbs.db
.vscode/
.idea/
.gitignore
updated as the project evolves (new tools, build outputs, IDE settings).
Undoing Commits: git revert
vs. git reset
git revert
creates a new commit that undoes a previous one (safe for shared history). git reset
moves the branch pointer, optionally changing the index/working tree (best for local work).
When to Use git revert
# Safe for shared branches (preserves history)
git revert <commit>
When to Use git reset
# Keep changes staged
git reset --soft HEAD~1
# Keep changes unstaged (default)
git reset --mixed HEAD~1
# Discard changes entirely (DANGEROUS)
git reset --hard HEAD~1
revert
for public/shared branches; use reset
only on local branches you haven’t pushed.
Staying Updated: git pull --rebase
- Checkout your feature branch:
git checkout feature-branch
- Rebase onto main:
git pull --rebase origin main
- Resolve conflicts as needed, then continue:
git rebase --continue
git config pull.rebase true
and rebase.autoStash true
to streamline updates.
Committed on the Wrong Branch
You committed on main
by mistake.
# Create the correct branch at current state
git checkout -b feature/my-change
# Move main back N commits (adjust N)
git checkout main
git reset --hard HEAD~N
# Merge/cherry-pick from your feature branch if needed
git checkout feature/my-change
git status
before committing.
FAQ
What is the difference between git merge and git rebase?
git merge
creates a new merge commit, preserving the history of both branches. git rebase
rewrites the history of the current branch by applying its commits on top of the target branch, resulting in a linear history. Rebase is generally preferred for feature branches before merging into the main branch.
How do I undo a git add?
# Unstage a specific file
git reset HEAD <file>
# Unstage all files
git reset HEAD .
How can I see the changes I've made but haven't committed yet?
# Working directory vs staging area
git diff
# Staged vs last commit
git diff --staged
How do I recover a deleted branch?
# Find the commit where the branch last pointed
git reflog
# Recreate it at that commit
git checkout -b <branch-name> <commit>
# or
git branch <branch-name> <commit>
Conclusion
Mastering Git is an ongoing process, and even experienced developers make mistakes. By understanding common Git pitfalls and their solutions, you can minimize disruptions and maintain a healthy Git repository. Remember to communicate with your team, adopt good Git practices, and regularly back up your work. For more insights on optimizing your development workflow, consider exploring related topics across your engineering blog.