# Common Git Errors and How to Fix Them (2026 Guide)

URL: https://www.devopsness.com/blog/git-error-troubleshooting-guide
Author: Kiril Urbonas
Published: 2026-07-16
Updated: 2026-10-12
Categories: DevOps
Tags: DevOps, Debugging, Operations, Git, Version Control

Summary: Rejected pushes, local changes that would be overwritten, merge conflicts, detached HEAD, unrelated histories, publickey denials, and oversized files. What each message means and the safe fix.

---
# Common Git Errors and How to Fix Them (2026 Guide)

Most Git errors mean one of four things: your branch is behind the remote, uncommitted changes are in the way, two edits collided, or you are not on a branch. Read the exact message, run `git status`, then apply the matching fix below. Avoid `--force` and `reset --hard` until you know which case you are in.

Git's messages sound like disasters and are usually a two-command fix. The table maps the text you see to the cause and the fix; the sections after it show the commands.

## Quick lookup: message to fix

| Message contains | What it means | Safe fix |
|---|---|---|
| `! [rejected] ... (non-fast-forward)` or `(fetch first)` | The remote has commits you don't | `git pull --rebase`, then `git push` |
| `Your local changes to the following files would be overwritten` | Uncommitted edits block a checkout, pull, or merge | `git stash`, act, `git stash pop` |
| `CONFLICT (content): Merge conflict in` | Both sides changed the same lines | Edit, `git add`, continue |
| `You are in 'detached HEAD' state` | You checked out a commit, not a branch | `git switch -c <name>` to keep work |
| `fatal: refusing to merge unrelated histories` | Two repos with no common ancestor | `--allow-unrelated-histories`, once, deliberately |
| `Permission denied (publickey)` | The host rejected your SSH key | `ssh -T git@github.com`, then load or add the key |
| `GH001: Large files detected` | A file over GitHub's 100 MiB limit is in a commit | Remove it from history; use Git LFS |
| `You have divergent branches and need to specify how to reconcile them` | Local and remote both have new commits | `git pull --rebase` or set `pull.rebase` |
| `has no upstream branch` | The branch was never pushed | `git push -u origin <branch>` |
| `fatal: not a git repository` | Wrong directory, or never initialized | `cd` to the repo root or `git init` |

## Push rejected (non-fast-forward)

Git refuses a push that isn't a fast-forward because it would delete commits on the remote. The fix is to integrate the remote work first, then push:

```bash
# Bring in the remote commits and replay yours on top
$ git pull --rebase origin main
$ git push origin main
```

If you rebased your own feature branch and the remote copy is now stale, use `git push --force-with-lease`, never plain `--force`. It refuses to overwrite the remote if someone else pushed in the meantime. Edge cases, including protected branches, are in [fixing git push rejected](/blog/fix-git-push-rejected).

## Local changes would be overwritten

Git won't let a checkout, pull, or merge clobber uncommitted edits. Either commit them or park them:

```bash
$ git stash push -m "wip before switching"
$ git switch other-branch
$ git stash pop        # bring the edits back when you return
```

If the edits are junk, `git restore <file>` discards them, and that one is not recoverable. More options are in [your local changes would be overwritten](/blog/fix-git-local-changes-overwritten).

## Merge conflicts

A conflict is a decision Git won't make for you. Open each file listed by `git status`, pick the right content between the `<<<<<<<`, `=======`, and `>>>>>>>` markers, delete the markers, then `git add <file>`. Finish with `git commit` for a merge or `git rebase --continue` for a rebase. Changed your mind? `git merge --abort` or `git rebase --abort` returns you to the state before you started. A calmer walkthrough is in [resolving merge conflicts](/blog/fix-git-merge-conflict).

## Detached HEAD

You checked out a tag, a commit hash, or a remote branch directly, so `HEAD` points at a commit instead of a branch. That is fine for looking around. The danger is committing there and then switching away: per the Git docs, commits referenced by nothing are eventually garbage-collected.

```bash
# Keep the work: turn the detached commit into a branch
$ git switch -c rescue-work
# Or just go back to where you were
$ git switch main
```

Already switched away? `git reflog` lists where `HEAD` has been; find the hash and `git branch rescue-work <hash>`. Details in [git detached HEAD](/blog/fix-detached-head).

## Refusing to merge unrelated histories

This appears when you `git init` locally, create a repo on GitHub with a README, and then try to pull. The two histories share no ancestor, so Git refuses by default. If combining them is what you meant, run `git pull origin main --allow-unrelated-histories` once and resolve any conflicts. If it isn't, you probably have the wrong remote: check `git remote -v`.

## Permission denied (publickey)

This comes from SSH, not Git: the host didn't accept any key you offered. Diagnose before generating new keys:

```bash
$ ssh -T git@github.com          # should greet you by username
$ ssh-add -l                     # are any keys loaded in the agent?
$ ssh -vT git@github.com         # verbose: which key files were tried
```

If no key is loaded, `ssh-add ~/.ssh/id_ed25519`. If you have no key, create one with `ssh-keygen -t ed25519` and add the public half to your account. Also check the remote URL: an `https://` remote never uses your SSH key.

## Large files

As of October 2026, GitHub warns above 50 MiB, blocks files over 100 MiB, and limits browser uploads to 25 MiB. If the big file is only in your latest unpushed commit, `git rm --cached <file>` plus `git commit --amend` removes it. If it is deeper in history, deleting it in a new commit isn't enough; the push still carries the old blob. Rewrite history with `git filter-repo`, then track large binaries with `git lfs track "*.zip"`. The full procedure, including secrets, is in [removing a large file from Git history](/blog/remove-large-file-git-history).

## Related fixes

[Not a git repository](/blog/fix-git-not-a-repository), [undo a commit](/blog/git-undo-last-commit), [git revert vs reset](/blog/git-revert-vs-reset), [rebase vs merge](/blog/git-rebase-vs-merge).

## Questions people ask

### How do I fix "Updates were rejected because the tip of your current branch is behind"?

Run `git pull --rebase` to replay your commits on top of the remote ones, resolve any conflicts, then `git push`. Don't reach for `git push --force`, which deletes whatever the remote had that you didn't. If you rewrote your own branch on purpose, use `git push --force-with-lease`, which fails safely if someone else pushed first.

### Is git push --force ever safe?

On a branch only you use, after a deliberate rebase or amend, yes, and `--force-with-lease` makes it safer by checking the remote hasn't moved. On shared branches like `main`, no: it silently removes teammates' commits. Most hosts let you protect important branches so force pushes are rejected outright.

### How do I recover commits after a bad reset or rebase?

Run `git reflog`. It records every position `HEAD` has held, including commits no branch points to anymore. Find the hash from before the mistake and run `git branch recovered <hash>` or `git reset --hard <hash>`. Unreferenced commits stay recoverable until garbage collection removes them, typically weeks later by default.

### Why does git say "not a git repository"?

The current directory and its parents contain no `.git` folder. You are usually in the wrong directory, or a clone extracted one level deeper than expected. `cd` into the project root (where `.git` lives) or, for a brand-new project, run `git init`.

## The decision, concretely

- **Push rejected?** `git pull --rebase`, then push. Force only your own branch, and only with `--force-with-lease`.
- **Edits blocking a switch or pull?** Stash or commit; `git restore` only when you mean to throw them away.
- **Conflict or detached HEAD?** Not an emergency. Resolve and add, or `git switch -c` to keep the work.
- **Auth or file-size error?** That's your host, not Git: test SSH with `ssh -T`, move big binaries to LFS.

## The call we'd make

Run `git status` before any fix, and never run a destructive command (`reset --hard`, `push --force`, `clean -fd`) to make an error go away. Almost every Git mistake is reversible through `git reflog` as long as the work was committed once, so commit early, even messily, and tidy later. The only losses we see in practice are uncommitted edits.

## Sources

- [git-push documentation: note about fast-forwards](https://git-scm.com/docs/git-push)
- [git-merge documentation: --allow-unrelated-histories](https://git-scm.com/docs/git-merge)
- [git-checkout documentation: detached HEAD](https://git-scm.com/docs/git-checkout)
- [GitHub Docs: Error: Permission denied (publickey)](https://docs.github.com/en/authentication/troubleshooting-ssh/error-permission-denied-publickey)
- [GitHub Docs: About large files on GitHub](https://docs.github.com/en/repositories/working-with-files/managing-large-files/about-large-files-on-github)

