Last updated: April 13, 2025
Table of Contents
- 1. Introduction: Oops, I Did It Again!
- 2. Mistake: Committed to the Wrong Branch
- 3. Mistake: Forgot to Add Files to Last Commit
- 4. Mistake: Typo in the Last Commit Message
- 5. Mistake: Accidentally Deleted a Branch
- 6. Mistake: Committed Sensitive Data
- 7. Mistake: Messy Commit History / Need to Rebase
- 8. Mistake: Force Pushed Over Shared Work
- 9. Mistake: Lost Changes with
git reset --hard
- 10. Conclusion: Git Happens
- 11. Additional Resources
1. Introduction: Oops, I Did It Again!
Git is an incredibly powerful version control system, but with great power comes the potential for making mistakes. Whether you're a beginner or a seasoned developer, accidentally committing to the wrong branch, making a typo in a commit message, or needing to undo changes is a common experience. Fortunately, Git provides robust tools to recover from most common mishaps.
This guide covers some of the most frequent Git mistakes and provides practical steps on how to fix them. Remember to always understand what a command does before running it, especially those that modify history!
2. Mistake: Committed to the Wrong Branch
You made one or more commits, only to realize you were on main
(or another incorrect branch)
instead of your feature branch (e.g., feature/my-new-thing
).
The Fix: Move the commits to the correct branch.
- Make sure your intended branch exists. If not, create it from the current state:
# Create the new branch pointing to the current commit git branch feature/my-new-thing
- Reset the incorrect branch (e.g.,
main
) back to where it should be (before your erroneous commits). ReplaceN
with the number of commits you made incorrectly.
Alternatively, find the commit hash# Reset main back N commits, keeping the changes in your working directory git reset HEAD~N --soft # OR if you haven't pushed and want to discard the commits from main entirely # git reset HEAD~N --hard # Be careful with --hard!
main
*should* point to usinggit log
and reset to that:git reset <correct_main_commit_hash> --soft
- (If you used
--soft
reset and have changes staged) Clean up the staging area:git reset HEAD
- Stash any uncommitted changes you want to keep but move:
git stash
- Checkout the correct branch:
git checkout feature/my-new-thing
- Apply the stashed changes (if you stashed any):
git stash pop
- If you used
--soft
reset in step 2, your changes are now in the working directory on the correct branch. Add and commit them:
If you made multiple commits initially, you might need to recommit them individually or combine them.git add . git commit -m "Your commit message"
Now, your incorrect branch is back to its proper state, and your commits are on the correct feature branch.
3. Mistake: Forgot to Add Files to Last Commit
You made a commit, but realized you forgot to include one or more files, or missed a change in an existing file.
The Fix: Amend the last commit.
Important: Only do this if you haven't pushed the commit to a shared remote repository yet!
- Stage the missing file(s) or changes:
git add forgotten_file.txt git add modified_file.js
- Amend the previous commit, adding the newly staged changes without changing the commit message:
git commit --amend --no-edit
Your last commit now includes the forgotten files/changes.
4. Mistake: Typo in the Last Commit Message
You just committed, but noticed a typo or error in the commit message.
The Fix: Amend the last commit message.
Important: Only do this if you haven't pushed the commit to a shared remote repository yet!
- Run the amend command:
This will open your default text editor with the previous commit message.git commit --amend
- Correct the message in the editor, save, and close the editor.
- Alternatively, provide the new message directly:
git commit --amend -m "Your corrected commit message"
The commit message is now fixed.
5. Mistake: Accidentally Deleted a Branch
You deleted a local branch (e.g., using git branch -d
or git branch -D
) but
realized you still needed it.
The Fix: Use the reflog.
Git keeps a log of where HEAD and branch references have pointed (the reflog). You can usually find the last commit of the deleted branch there.
- View the reflog to find the last commit hash of the deleted branch:
Look for entries likegit reflog
checkout: moving from <deleted-branch-name> to <another-branch>
. The commit hash associated with the<deleted-branch-name>
state is what you need. - Once you find the correct commit hash (e.g.,
a1b2c3d
), recreate the branch pointing to that commit:git checkout -b <deleted-branch-name> a1b2c3d
Your branch is now restored to its previous state.
6. Mistake: Committed Sensitive Data
You accidentally committed passwords, API keys, or other sensitive files.
The Fix (Complex & Requires Caution): Remove the data from history.
WARNING: Rewriting repository history is dangerous, especially if the repository is shared.
It invalidates existing clones for collaborators. Always back up your repository before attempting this.
Simple git commit --amend
or git reset
only works if the sensitive commit is the
*very last* one and hasn't been pushed.
- Remove the file from your current working directory and stage the removal if it's still
present. Add the file path to your
.gitignore
file to prevent re-committing it. - Use a history rewriting tool: The recommended tool is
git filter-repo
(a replacement for the older, complexgit filter-branch
). BFG Repo-Cleaner is another option.Using
git filter-repo
(Example: Remove a file namedsecrets.yml
):# Install git-filter-repo first if you haven't already # (Follow instructions from its official repository) # Run filter-repo to remove the file from all commits git filter-repo --path secrets.yml --invert-paths
Using BFG Repo-Cleaner (Example: Remove a file named
secrets.yml
):# Download bfg.jar first # Create a bare clone (important!) git clone --mirror git://example.com/my-repo.git # Run BFG java -jar bfg.jar --delete-files secrets.yml my-repo.git # Go into the cleaned repo and run gc cd my-repo.git git reflog expire --expire=now --all && git gc --prune=now --aggressive # Push the cleaned history (DANGEROUS - coordinate with team!) # cd .. # git push --force # Or preferably, coordinate and have everyone re-clone
- Invalidate Secrets: Crucially, any committed secrets (API keys, passwords) must be considered compromised. **Immediately revoke or change them.** Removing them from Git history does not make them secure again if they were ever public.
- Coordinate with Team: If the repo is shared, inform collaborators. They will likely need
to re-clone or perform complex fetch/rebase operations. Force pushing (
git push --force
or--force-with-lease
) will be necessary to update the remote repository with the rewritten history.
7. Mistake: Messy Commit History / Need to Rebase
Your feature branch has many small, "work-in-progress" commits, or it has fallen behind the main branch and has many merge commits cluttering the history.
The Fix: Interactive Rebase (git rebase -i
).
Important: Avoid rebasing commits that have already been pushed and shared with others on a collaborative branch, as it rewrites history.
- Identify the base commit onto which you want to rebase or clean up commits *after*. This is often the
commit where your feature branch diverged from the main branch (e.g.,
main
ordevelop
). - Start the interactive rebase:
git rebase -i <base_commit_hash_or_branch_name> # Example: Rebase current branch onto 'main' git rebase -i main
- An editor will open listing the commits since the base. You can:
pick
: Use the commit as is.reword
(orr
): Edit the commit message.edit
(ore
): Stop to amend the commit (change content and message).squash
(ors
): Combine this commit with the previous one (merges changes and combines messages).fixup
(orf
): Combine like squash, but discard this commit's message.drop
(ord
): Delete the commit entirely.- Reorder lines to change commit order.
- Save and close the editor. Git will apply the changes. Resolve any conflicts that arise during the
process. Use
git rebase --continue
after resolving conflicts, orgit rebase --abort
to cancel.
Interactive rebase is powerful for cleaning up local history before merging or creating a pull request.
8. Mistake: Force Pushed Over Shared Work
You used git push --force
on a shared branch and overwrote commits made by others.
The Fix: Coordination and potentially restoring commits.
Prevention is key! Avoid using git push --force
on shared branches. Use
git push --force-with-lease
instead, which checks if the remote branch has changed since your
last fetch, preventing accidental overwrites.
- Stop! Inform your collaborators immediately.
- Find Lost Commits: Ask collaborators if they have the lost commits locally. They might be able to push them back up to a *new* branch. The reflog on the server (if accessible) or collaborators' local reflogs might also contain the lost commit hashes.
- Restore Commits: If someone has the commits, they can create a new branch from the lost
commit hash and push it. Then you can merge or cherry-pick those commits back into the shared branch.
# Collaborator finds lost commit hash 'xyz123' git checkout -b recovery-branch xyz123 git push origin recovery-branch # On the main machine/branch git fetch origin git merge origin/recovery-branch # Or cherry-pick specific commits
- Rebase Your Work: Your local work might now need to be rebased onto the restored branch
history using
git pull --rebase
before you can push again normally.
Recovering from a bad force push requires careful coordination.
9. Mistake: Lost Changes with git reset --hard
You ran git reset --hard
and realized it discarded local changes (committed or uncommitted) that
you actually needed.
The Fix: Check the reflog (immediately!).
git reset --hard
moves the branch pointer and discards changes in the working directory and
staging area. If the changes were *committed* before the reset, they might still be recoverable via the
reflog.
- Immediately run
git reflog
:
Look for the commit hash representing the state *before* you rangit reflog
git reset --hard
. - If you find the commit hash (e.g.,
a1b2c3d
): You can restore your branch to that state:
Or, create a new branch from that commit to inspect it without changing your current branch:git reset --hard a1b2c3d
git checkout -b recovery-branch a1b2c3d
- If changes were uncommitted: Unfortunately,
git reset --hard
discards uncommitted changes permanently. Git doesn't track them. Your only hope might be filesystem recovery tools or IDE local history features (if available), but don't count on it. **Be very careful withgit reset --hard
!**
10. Conclusion: Git Happens
Making mistakes with Git is a normal part of the development process. The key is not to panic. Git provides
powerful tools like --amend
, rebase
, reset
, and especially the
reflog
, which act as safety nets for many common errors.
Understanding these recovery techniques can save you significant time and stress. Always try to understand what a command does before executing it, especially commands that modify history or involve force pushing. When in doubt, create backup branches or consult the extensive Git documentation.
11. Additional Resources
- Official Git Documentation
- Pro Git Book (Free Online) - Especially chapters on Rewriting History and Git Internals.
- Atlassian Git Tutorials: Resetting, Checking Out & Reverting
- Oh Shit, Git!?! - A collection of common Git mistakes and how to fix them (use with caution, understand the commands).
- Git Reflog Documentation