GitLearn — Common Mistakes & Fixes
GitLearn
⟳ Flow
15px

🛠️ Common Mistakes & Fixes

Everyone breaks something in Git eventually. This page is a fast lookup — find your situation, run the fix. Each entry notes whether the fix is safe or destructive.

💡
Golden rule: git reflog is your safety net. Git almost never permanently deletes commits — they stay in the reflog for 90 days. If something went wrong, run git reflog first before panicking.

Wrong Commits

😬

I committed directly to main Caution

You made one or more commits on main instead of a feature branch.

If you have NOT pushed yet — move the commit to a new branch and roll main back:

git branch my-feature        # create branch pointing at your commit
git reset --hard HEAD~1      # move main back one commit (adjust number if multiple)
git checkout my-feature      # switch to your branch and continue

If you already pushed — after moving the commit to a branch, force-push main back. Only do this if main is not protected and no one else has pulled:

git push origin main --force-with-lease   # reset main on remote
git push origin my-feature                 # push your feature branch
⚠️
If main is branch-protected (common in GitLab/GitHub) the force push will be blocked — open a revert MR instead.
✏️

I committed with the wrong message Safe (if not pushed)

Typo, wrong ticket number, or just a bad description on the last commit.

Not pushed yet — amend is completely safe:

git commit --amend -m "fix: correct message here"

Already pushed — amend rewrites history, so teammates need to re-pull. Only do this on your own branch:

git commit --amend -m "fix: correct message here"
git push --force-with-lease
💡
To edit an older commit message (not just the last one), use interactive rebase: git rebase -i HEAD~N and change pick to reword on the commit you want to fix.
🙈

I accidentally committed a file I shouldn't have Caution if pushed

e.g. .env, appsettings.local.json, credentials, binary dump, or node_modules.

Remove the file from the last commit but keep it on disk:

git rm --cached path/to/secret.env
echo "secret.env" >> .gitignore   # prevent it being added again
git commit --amend --no-edit

If you already pushed, force-push to remove it from the remote:

git push --force-with-lease
🚨
If the file contained secrets (passwords, API keys): treat them as compromised the moment they were pushed — even for a second. Rotate/revoke the keys immediately. Removing the file from Git history does not guarantee the data was never seen or cached.
🔀

I committed to the wrong branch Safe

Your commit is on feature-a but it belongs on feature-b.

Cherry-pick the commit onto the correct branch, then remove it from the wrong one:

git log --oneline -5             # find and note the commit hash (e.g. a1b2c3d)

git checkout correct-branch
git cherry-pick a1b2c3d          # apply the commit here

git checkout wrong-branch
git reset --hard HEAD~1          # remove the commit from wrong branch
💡
If you have multiple commits to move, cherry-pick a range: git cherry-pick A^..B where A is the oldest and B is the newest commit hash.

Push Mistakes

📤

I pushed a bad commit to a shared branch Safe approach

Broken build, wrong file, or incomplete work pushed to a branch others are using.

The safe fix: revert. This adds a new commit that undoes the bad one — history stays intact, no one's work is disrupted:

git revert HEAD              # reverts the last commit
git push                     # push the revert commit

To revert an older commit (not the last one):

git log --oneline -10        # find the bad commit hash
git revert a1b2c3d           # revert that specific commit
git push
🚨
Do NOT reset + force-push on a shared branch. It rewrites history and will cause conflicts for everyone who already pulled.
🔑

I pushed sensitive data (passwords, API keys) Critical

A secret ended up in a commit that was pushed to a remote repository.

🚨
Step 0 — Do this first, before anything else: rotate and revoke the exposed secret immediately. Assume it has been seen. Removing it from Git history does not mean it was never cached or indexed.

Remove the file completely from all history using git filter-repo (install with pip install git-filter-repo):

# Remove a specific file from all history
git filter-repo --path path/to/secret.env --invert-paths

# Force push all branches and tags
git push origin --force --all
git push origin --force --tags

Add the file to .gitignore immediately so it can't be committed again:

echo "secret.env" >> .gitignore
git add .gitignore
git commit -m "chore: ignore secret files"
git push
⚠️
After rewriting history, all teammates must delete their local clone and re-clone fresh. Their local copies still have the old history.

Branch Confusion

🗑️

I deleted a branch by accident Recoverable

Ran git branch -D or deleted via the GitLab UI and need the branch back.

The commits still exist in the reflog. Find the tip commit and recreate the branch:

git reflog                         # scroll through to find the last commit that was on your branch
                                   # look for the branch name in the description, e.g.:
                                   # a1b2c3d HEAD@{4}: checkout: moving from feature-x to main

git checkout -b feature-x a1b2c3d # recreate the branch at that commit
💡
If you deleted the branch on GitLab, check the MR or commit history in the UI — GitLab keeps a "Restore branch" button on recently deleted branches for a short time.
👻

I'm in "detached HEAD" state Caution

Git says HEAD detached at abc1234. Commits you make here are not on any branch and will be lost when you switch away.

If you haven't made any commits yet — just switch back to a branch:

git checkout main       # or whichever branch you want

If you made commits in detached HEAD — save them to a new branch immediately before switching away:

git branch rescued-work         # create branch at current HEAD
git checkout rescued-work       # switch to it — commits are now safe
# or in one step:
git checkout -b rescued-work
⚠️
If you switch branches without saving, your detached commits become unreachable. They're still in the reflog for 90 days — use git reflog to find and recover them.
🚫

My push was rejected (non-fast-forward) Safe

Git says rejected — non-fast-forward or Updates were rejected because the tip of your current branch is behind.

Someone else pushed to the same branch first. Pull their changes, then push again:

git pull --rebase origin main   # fetch and replay your commits on top of theirs
# if conflicts appear, resolve them, then:
git rebase --continue
git push

Alternatively, merge instead of rebase:

git pull origin main    # merge their changes into your branch
git push
🚨
Never use git push --force to bypass this on a shared branch — it will overwrite your teammates' commits.

Getting Unstuck

⚔️

I have merge conflicts I can't figure out Safe

Git stopped mid-merge with conflict markers in the files and you're not sure what to keep.

See exactly which files are conflicting:

git status      # files listed under "both modified" have conflicts

Open each conflicting file. Git marks the conflict like this:

<<<<<<< HEAD
your version of the code
=======
their version of the code
>>>>>>> feature-branch

Edit the file to the version you want (delete the markers and unwanted lines), then mark it resolved:

git add path/to/resolved-file.cs
git commit    # complete the merge

To abort the merge entirely and go back to before you started:

git merge --abort
💡
Visual Studio and VS Code both have built-in merge conflict UIs — look for the "Accept Current / Accept Incoming / Accept Both" buttons above each conflict. Much easier than editing raw markers.
🗂️

My working directory is a mess — I want to start fresh Destructive

Half-finished experiments everywhere, can't tell what's what, want to go back to the last commit.

Keep changes but hide them (recommended — you can get them back):

git stash push -m "WIP: messy experiments"    # save and clean
# ... work fresh ...
git stash pop                                  # restore later if needed

Discard all changes to tracked files permanently:

git restore .          # discard all unstaged changes (cannot be undone)

Also remove untracked files and folders (new files you never committed):

git clean -fd          # -f = force, -d = include directories
git clean -fdn         # dry run first — shows what WOULD be deleted
🚨
git restore . and git clean -fd permanently delete local changes. Always try git stash first — it's reversible.
🔍

I lost commits after a reset — how do I get them back? Recoverable

You ran git reset --hard and the commits seem to have disappeared.

Git's reflog records every position HEAD has been at. Your commits are still there:

git reflog                    # find the commit hash from before the reset
                              # look for lines like: a1b2c3d HEAD@{3}: commit: your message here

Once you have the hash, restore your work:

# Option A — create a new branch at the lost commit (safest)
git checkout -b recovered a1b2c3d

# Option B — move HEAD back to that commit
git reset --hard a1b2c3d
💡
Reflog entries expire after 90 days by default. For very old lost work, check git fsck --lost-found — it finds dangling commits not referenced by any branch or reflog.