Git fix-it guides
56 step-by-step walkthroughs for the things that actually go wrong. Each one opens with a short answer and a copyable command, tells you honestly whether the work can be recovered, explains why the fix works, and shows how to stop it happening again.
Most common emergencies
All 56 guides
Search by what happened, or by the error message Git printed — try “detached”, “rejected” or “index.lock”.
56 guides
Recover lost work7
I permanently deleted a file that was never committed — can I get it back?
It comes down to one question: was the file ever staged with git add? If it was, its contents are sitting in Git's object database as a dangling blob and git fsck will find it. If it was never staged and never committed, Git genuinely never saw the file and cannot help — but your editor's local history almost certainly can.
Read the fix →Usually recoverableI ran git reset --hard and lost my commits — how do I undo it?
Committed work is almost never really gone. git reflog lists every position HEAD has held, including the one just before your reset, so you can jump straight back to it with git reset --hard HEAD@{1}. Uncommitted changes that the reset wiped are a different story — those are only recoverable if they had been staged at some point.
Read the fix →Usually recoverableI deleted a Git branch — how do I get it back?
Deleting a branch removes a pointer, not the commits. Find the branch's last commit hash in the reflog and recreate the branch at that hash with git branch <name> <hash>. If the branch was pushed, the copy on the server may still exist and can simply be fetched back.
Read the fix →Usually recoverableI ran git stash drop (or git stash clear) — can I get the stash back?
Stashes are stored as real commit objects, so dropping one only removes it from the stash list — the commit itself survives as an unreachable object. git fsck --unreachable finds it, and git stash apply <hash> puts the work back.
Read the fix →Usually recoverableMy rebase went wrong and my commits are gone — how do I get them back?
The pre-rebase commits are still in the object database. git reflog shows the position from before the rebase started, and ORIG_HEAD is a shortcut to it — git reset --hard ORIG_HEAD usually restores everything in one command.
Read the fix →Always fixableGit says another git process seems to be running — how do I fix index.lock?
Git locks the index while it works and removes the lock when it finishes. A crashed command, a killed process or an editor's background Git integration can leave the lock behind. Confirm nothing is actually running, then delete .git/index.lock.
Read the fix →Usually recoverableGit says 'object file is empty' or 'loose object is corrupt' — can I repair it?
Corruption is almost always a few damaged object files after a crash, disk problem or a killed process. Run git fsck to identify them, delete the empty or unreadable ones, and re-fetch the good copies from your remote. If you have a remote, a fresh clone is often the fastest fix.
Read the fix →Undo a change10
How do I undo the last commit but keep my work?
git reset --soft HEAD~1 removes the commit and leaves every change staged, ready to recommit. Use --mixed (the default) if you also want the changes unstaged, and only use --hard if you genuinely want the work destroyed. If the commit is already pushed, revert it instead of resetting.
Read the fix →Always fixableHow do I undo git add without losing my changes?
git restore --staged <file> removes a file from the staging area and leaves your edits completely untouched. The older equivalent is git reset HEAD <file>. Neither one touches the contents of your file, so this is a zero-risk operation.
Read the fix →Rarely recoverable by GitHow do I throw away all my local changes in Git?
git restore . discards edits to tracked files and git clean -fd deletes untracked ones. Both are irreversible for anything that was never staged or committed, so run git stash first if there's any doubt — it takes a second and makes the whole operation undoable.
Read the fix →Always fixableI committed to main instead of my feature branch — how do I move the commits?
Create a branch at your current position to keep the commits, then reset the branch you polluted back to where it should be. Nothing is lost because the new branch holds the commits the whole time.
Read the fix →Always fixableHow do I revert just one file to a previous version?
git restore --source=<commit> -- <path> rewrites one file to its state at that commit and leaves everything else alone. The classic equivalent is git checkout <commit> -- <path>. Neither moves your branch or affects any other file.
Read the fix →Always fixableGit says I'm in 'detached HEAD' — what does that mean and how do I fix it?
Detached HEAD means you're on a commit rather than a branch. If you made no commits, git switch - takes you back. If you did commit, create a branch at your current position first with git switch -c <name>, otherwise those commits have no reference and become hard to find.
Read the fix →Always fixableHow do I undo a git pull?
A pull is a fetch plus a merge or rebase, so undoing it means moving your branch back to where it was. git reset --hard ORIG_HEAD does exactly that, because Git saves your pre-pull position there automatically.
Read the fix →Always fixableHow do I rename a Git branch?
git branch -m <new-name> renames the branch you're on. Renaming on the server takes two more steps, because Git has no rename operation for remote branches — you push the new name and delete the old one.
Read the fix →Always fixableHow do I undo a git cherry-pick?
If it's still in progress, git cherry-pick --abort restores everything. If it completed, git reset --hard HEAD~1 removes the resulting commit — or git revert it if you've already pushed.
Read the fix →Always fixableI ran git rm and deleted a file — how do I restore it?
If you haven't committed the deletion, git restore --staged --worktree <file> brings the file back from HEAD. If you already committed, restore it from the previous commit with git restore --source=HEAD~1.
Read the fix →Clean up history11
How do I edit a Git commit message?
For the most recent commit, git commit --amend -m "new message" replaces it. For older commits, git rebase -i lets you mark any of them as reword. Both rewrite history, so if the commit is already pushed you'll need git push --force-with-lease and a word to your team.
Read the fix →Always fixableI committed a secret — how do I remove it from Git history?
Rotate the secret first — that's the only step that genuinely protects you. Then purge it from history with git filter-repo (or the BFG Repo-Cleaner) and force-push. Deleting the file in a new commit does nothing, because the old commit still contains it and is still fetchable.
Read the fix →Always fixableHow do I combine multiple commits into a single commit?
git rebase -i HEAD~n opens an editor where you mark commits as squash or fixup to fold them into the one above. For a quick all-in-one collapse, git reset --soft HEAD~n followed by a fresh commit achieves the same result with no editor at all.
Read the fix →Always fixableHow do I break a large commit into multiple commits?
Mark the commit as edit in git rebase -i, then run git reset HEAD~ to turn it back into unstaged changes. Stage the pieces one at a time with git add -p, commit each, and finish with git rebase --continue.
Read the fix →Always fixableMy commits show the wrong name or email — how do I fix them?
Set the correct identity with git config, then fix the last commit with git commit --amend --reset-author. For a range of commits use git rebase with an exec step, or git filter-repo --mailmap to rewrite the whole history at once.
Read the fix →Always fixableI committed a large file and my push is rejected — how do I remove it?
If it's still the last commit, git reset --soft HEAD~1 and re-commit without it. If it's further back, purge it from history with git filter-repo --strip-blobs-bigger-than. Going forward, route large binaries through Git LFS.
Read the fix →Always fixableHow do I change the order of commits in Git?
Run git rebase -i and move the lines in the editor — Git replays them in whatever order you leave them. Conflicts happen when the commits touch the same code, in which case reordering may not be possible without editing.
Read the fix →Always fixableHow do I remove a single commit without losing the ones after it?
Mark it drop in git rebase -i and Git replays everything except that commit. On a shared branch, git revert is the safe alternative — it neutralises the change without rewriting anyone's history.
Read the fix →Always fixableHow do I edit a commit that isn't the most recent one?
Mark the commit edit in git rebase -i. Git stops there, you make your changes and amend, then git rebase --continue replays the rest. The tidier route is git commit --fixup plus an autosquash rebase.
Read the fix →Always fixableHow do I extract a folder from my repo into a separate repo with its history?
git filter-repo --path <dir> --path-rename <dir>/: keeps only that directory and moves it to the root, preserving every commit that touched it. Work on a fresh clone so your original repository is never at risk.
Read the fix →Always fixableHow do I combine two separate repos while keeping both histories?
Add the second repository as a remote, fetch it, and merge with --allow-unrelated-histories into a subdirectory. Both sets of commits end up in one repository with their history intact.
Read the fix →Merge conflicts5
Git says I have merge conflicts — how do I fix them?
Git pauses and marks the clashing sections with <<<<<<<, ======= and >>>>>>>. Edit each file to the version you actually want, delete the markers, git add the file, then git merge --continue. If it gets overwhelming, git merge --abort returns you to exactly where you started.
Read the fix →Always fixableHow do I undo a Git merge?
If the merge hasn't been pushed, git reset --hard HEAD~1 removes it cleanly. If it has been pushed, use git revert -m 1 <merge-hash> so history stays valid for everyone else. And if you're still in the middle of a conflicted merge, git merge --abort is all you need.
Read the fix →Always fixableTwo people edited the same Unity scene — how do I merge it without losing work?
Unity scenes and prefabs are YAML, so they can be merged — but only if Force Text serialization is on and you've registered Unity's own UnityYAMLMerge tool with Git. Without that setup Git mangles them, and the only safe resolution is to pick one side entirely.
Read the fix →Always fixableGit says a binary file conflicts — how do I resolve it?
Binary files can't be merged line by line, so Git asks you to choose one version wholesale. Use git checkout --ours or --theirs to pick, then stage it. Mark such files as binary in .gitattributes so Git stops trying to diff them.
Read the fix →Always fixableGit says refusing to merge unrelated histories — what does that mean?
The two branches share no common ancestor, so Git won't guess how to combine them. Adding --allow-unrelated-histories permits the merge — but first check you aren't accidentally merging two genuinely different projects, which is what this guard is protecting you from.
Read the fix →Push & pull problems10
How do I undo a commit that's already on the remote?
On a shared branch, use git revert <hash> — it adds a new commit that reverses the change, so nobody else has to do anything. Rewriting with reset plus a force-push is only appropriate on a branch you're certain nobody else has pulled.
Read the fix →Usually recoverableSomeone force-pushed and my commits are gone — how do I get them back?
Your local clone still has the commits, and your reflog records where the branch pointed before the force-push overwrote it. Find that hash with git reflog, recover it to a branch, and push it back. If your local copy is already clean, a teammate's clone or the server's reflog may still have it.
Read the fix →Always fixableMy push was rejected — 'Updates were rejected because the remote contains work that you do not have'. What now?
Someone pushed commits you don't have yet, so your push would erase them. Git is protecting you. Fetch and integrate their work first with git pull --rebase, then push again. Never reach for --force here unless you genuinely intend to delete what's on the server.
Read the fix →Always fixablegit pull says I need to specify how to reconcile divergent branches — what do I choose?
Git 2.27+ refuses to guess whether you want a merge or a rebase when both sides have new commits. Pick one — git config --global pull.rebase true gives you clean linear history and is the best default for most people.
Read the fix →Always fixableGit keeps saying authentication failed even though my password is correct — why?
GitHub stopped accepting account passwords over HTTPS in August 2021. You need a personal access token in place of the password, or better, switch the remote to SSH. If it worked yesterday, a cached old credential is usually the culprit — clear it and re-authenticate.
Read the fix →Always fixablegit clone or push fails with Permission denied (publickey) — how do I fix my SSH key?
The server didn't accept any key your SSH client offered. Either you have no key, the key isn't loaded into the agent, or its public half was never added to your account. Run ssh -T git@github.com to see exactly which keys are being tried.
Read the fix →Always fixableHow do I change the remote URL of a Git repository?
git remote set-url origin <new-url> repoints an existing remote. It's a purely local change — nothing on either server is touched — so it's the safe way to switch between HTTPS and SSH, move to a new host, or fix a URL after renaming the repository.
Read the fix →Always fixableHow do I sync my fork with the upstream repository?
Add the original repository as a remote called upstream, fetch it, then merge or rebase upstream/main into your main and push. GitHub's 'Sync fork' button does the same thing, but doing it locally gives you control when your fork has diverged.
Read the fix →Usually recoverableHow do I delete a remote branch in Git?
git push origin --delete <branch> removes it from the server. Deleting it locally with git branch -d doesn't touch the remote at all, and other people keep seeing stale copies until they run git fetch --prune.
Read the fix →Always fixableGit won't let me pull because of local changes — how do I fix it?
Git is refusing to overwrite uncommitted edits to files the incoming commits also change. Commit them, stash them, or discard them — stashing is the reversible choice and takes one command.
Read the fix →Find something5
How do I find which commit broke my code?
git bisect binary-searches your history. Tell it one commit that works and one that doesn't; it checks out the midpoint and asks you to test, halving the range each time. With git bisect run it tests automatically and names the guilty commit unattended.
Read the fix →Always fixableA file was deleted months ago — how do I find and restore it?
git log --all --full-history -- "**/filename" finds every commit that ever touched the file, including the one that deleted it. Restore it from the commit before the deletion with git checkout <hash>^ -- <path>.
Read the fix →Always fixableHow do I compare two branches in Git?
git diff main..feature compares the two tips; git diff main...feature (three dots) compares against their common ancestor and shows only what the feature branch added. The three-dot form is almost always the one you want for reviewing a branch.
Read the fix →Always fixableMy .git folder is enormous — how do I find the biggest files in history?
git count-objects -vH tells you the total size; combining git rev-list --objects with git cat-file --batch-check lists the largest blobs by name. Deleting the files now won't shrink anything — they have to be purged from history.
Read the fix →Always fixableHow do I find which commit introduced a particular piece of code?
git log -S "text" (the pickaxe) finds every commit where the number of occurrences of that string changed — which is how you locate the commit that introduced or deleted it. git log -L traces one function's entire evolution.
Read the fix →Setup & config8
Why is .gitignore not working for files that are already tracked?
.gitignore only applies to untracked files. Once a file has been committed, Git keeps tracking it no matter what the ignore rules say. Remove it from the index with git rm --cached <file> — that stops tracking while leaving the file on your disk.
Read the fix →Always fixablegit status says every file changed but I didn't touch them — how do I fix line endings?
Windows writes CRLF and Unix writes LF, and without a policy Git records whichever your editor produced. Commit a .gitattributes with `* text=auto`, then renormalise the repository once — this fixes it for everyone, unlike the per-machine core.autocrlf setting.
Read the fix →Always fixableI renamed a file's case and Git won't notice — how do I fix it?
Windows and macOS filesystems treat Player.cs and player.cs as the same file, so a case-only rename is invisible to Git. Use git mv -f to force it, or rename via a temporary name, then commit — otherwise the wrong case ships to your Linux CI and the build breaks.
Read the fix →Always fixableHow do I make Git remember my credentials?
Configure a credential helper that stores the token in your OS keychain, or switch to SSH keys and skip credentials entirely. Avoid the `store` helper — it writes your token to a plaintext file.
Read the fix →Always fixableGit says files changed but only the mode differs — how do I ignore that?
Git tracks the executable bit, so a file going from 100644 to 100755 counts as a change. Set core.fileMode false to ignore mode differences, or fix the bit properly with git update-index --chmod when it genuinely matters.
Read the fix →Always fixableHow do I keep my own version of a tracked file without Git nagging me?
git update-index --skip-worktree <file> makes Git ignore your local modifications to a tracked file. The cleaner long-term answer is to commit an example file, ignore the real one, and have everyone copy it.
Read the fix →Always fixableCloning takes forever — how do I clone a big repo faster?
Use --filter=blob:none for a partial clone that fetches file contents lazily, and add sparse-checkout to materialise only the directories you need. --depth 1 is fastest of all but gives you no usable history.
Read the fix →Always fixableI cloned a repo and the submodule folders are empty — how do I fix it?
Cloning records submodules but doesn't populate them. Run git submodule update --init --recursive, or clone with --recurse-submodules next time so it happens automatically.
Read the fix →Using these guides
What is the first thing to do when Git goes wrong?
Stop and run git status and git reflog before trying anything else. Status usually names the command that fixes your situation, and the reflog records where you were before the mistake. Most damage happens after the original error, when people start running recovery commands they don't fully understand.
Can I recover work I never committed?
Only if it was staged with git add at some point — staging writes the content into Git's object database, where git fsck --lost-found can still find it. Content that was never staged and never committed was never given to Git, so no Git command can produce it. Your editor's local history is the realistic fallback.
How long do I have to recover lost commits?
Reflog entries survive 90 days for reachable commits and 30 for unreachable ones, after which garbage collection can remove the objects. That's a generous window, but act sooner rather than later — and never run git gc --prune=now while you're still trying to recover something.
Is it safe to follow these guides on a shared repository?
Each guide states whether its fix rewrites history. Anything involving reset, rebase, amend, filter-repo or a force-push changes commits others may already have pulled, so on a shared branch prefer the revert-based alternative each guide offers. On your own branch, rewriting is normal and fine.
What does the recoverability badge on each guide mean?
It's an honest estimate before you start. 'Always fixable' means Git has everything it needs. 'Usually recoverable' means it works if you act before garbage collection. 'Sometimes' depends on whether the content ever reached the object database, and 'rarely' means Git probably never saw it and the fix lies outside Git.
Do these commands work on Windows?
Yes — Git itself is identical on every platform. Where a step uses shell-specific syntax such as a loop or a pipeline, the guide includes a PowerShell version alongside the bash one, so you can copy whichever matches your terminal.
Looking up a command instead?
The cheat sheet documents all 82 commands with syntax, flags, examples and a danger rating.
Open the cheat sheet →