How to Fix “Git Push Rejected: Non-Fast-Forward” Without Losing Changes

A non-fast-forward rejection is Git protecting history, not deleting your local work. It usually means the remote branch moved forward after your local branch last synchronized, so updating the remote with your current branch would discard commits that already exist there. GitHub’s current documentation describes the same situation: retrieve the upstream changes first, integrate them locally, then push again.

The safest general workflow is: protect any uncommitted work, fetch the remote branch without modifying your current branch, inspect how the histories diverged, choose either merge or rebase, resolve conflicts if necessary, and push again. Do not start with git push --force or git reset --hard just to make the error disappear.

Official references used for this guide include GitHub Docs: Dealing with non-fast-forward errors, Git: git-push documentation, Git: git-fetch documentation, and Git: git-rebase documentation.

What does “non-fast-forward” actually mean?

Suppose your local main branch contains commit L, while the remote origin/main has advanced to a different commit R. If neither commit is an ancestor of the other, the histories have diverged. A normal push cannot simply move the remote branch pointer to L without making R disappear from that branch’s visible history.

A fast-forward update is different: the new branch tip is a descendant of the old one, so moving the branch forward preserves everything already reachable from it. The official git push manual defines this ancestry rule and warns that --force disables the normal protection and can cause remote commits to be lost.

Terminalen viser git push origin main afvist med en ikke-spolingsfejl, fordi fjernbetjeningen indeholder arbejde, der ikke er lokalt.
A non-fast-forward rejection means Git is refusing to replace remote history that your local branch does not yet contain.

Before doing anything: is your local work safely recorded?

Run:

git status

If the working tree is clean, your current changes are already represented by commits and you can create an extra safety reference before integrating the remote:

git branch backup-before-sync

That branch points to the current commit, so you have an easy name for the pre-integration state.

If you have modified or untracked files that are not committed, choose one of these approaches before pulling or rebasing:

  • Commit them if the work is logically ready for a commit.
  • Stash them if the work is incomplete: git stash push -u -m "before non-fast-forward fix".

The -u option includes untracked files. The official git-stash documentation explains that a stash records the working directory and index state and restores a clean working tree. Ignored files are not included by -u; -a would include ignored files too, but that is rarely necessary for this problem.

Important: if git status shows files you cannot afford to lose, do not run git reset --hard. That command can discard uncommitted working-tree changes.

Step 1: Should you use git pull immediately?

You can, but fetch first is easier to reason about. GitHub documents that git fetch downloads remote work and updates remote-tracking branches without merging those changes into your current branch. That makes it a useful diagnostic step because you can inspect the situation before altering local history.

git fetch origin
git status -sb
git log --oneline --graph --decorate --left-right HEAD...origin/main

After the fetch, the remote-tracking branch origin/main represents the remote state you just retrieved. The log command lets you see commits reachable only from your local side and only from the remote side.

If your local branch has no unique commits and is simply behind, you can often fast-forward it:

git merge --ff-only origin/main

Then there is nothing to reconcile; your branch simply moves forward.

Step 2: Merge or rebase—which should you choose?

Both can preserve your changes. The difference is the shape of the resulting history.

Situation Usually choose Why
Shared branch such as main where your local commits may already be known to others Merge Preserves existing commit identities and does not rewrite your local commits.
Your commits are local/private and you want a linear history Rebase Replays your local commits on top of the updated remote branch.
You are unsure and want the least history rewriting Merge It is easier to explain and safer for shared history.

Merge route

git fetch origin
git merge origin/main

If there are no conflicts, Git completes the integration. If the branches truly diverged, the result may include a merge commit.

Rebase route

git fetch origin
git rebase origin/main

Rebase takes the commits that are unique to your current branch and reapplies them on top of origin/main. Git’s rebase documentation describes it as transplanting a series of commits onto a different starting point. Because those commits receive new commit IDs, rebase is best used for local work that has not already been shared as public history.

If you prefer a shortcut, git pull --rebase origin main performs a fetch followed by a rebase, while git pull --no-rebase origin main explicitly chooses merge behavior. For a recovery situation, separate fetch and merge/rebase commands are often clearer because you can inspect the remote state first.

Terminalen viser git pull origin main, der henter eksterne objekter og opdaterer branchen med eksterne ændringer.
After the remote changes are retrieved, integrate them deliberately—by merge or rebase—rather than overwriting them.

Step 3: What should you do if Git reports a conflict?

A conflict does not mean your changes are gone. It means Git cannot automatically decide how to combine changes to the same content.

Først skal du undersøge staten:

git status

Åbn hver konfliktfyldt fil, bestem, hvad det endelige indhold skal være, fjern konfliktmarkørerne, og opsæt derefter den løste fil:

git add path/to/file

Hvis du vælger fletning, skal du afslutte fletningen, når alle konflikter er opdelt:

git commit

Hvis du valgte rebase, fortsæt med at afspille dine commits:

git rebase --continue

Hvis rebasen går dårligt, og du vil returnere branchen til dens tilstand før rebasen, skal du bruge:

git rebase --abort

Den nuværende Git rebase-manual dokumenterer specifikt --continueog --aborttil dette formål. Brug ikke git rebase --skipblot til at få en konflikt til at forsvinde, medmindre du rent faktisk har til hensigt at udelade afspilningen af ​​commit'en.

Terminal, der viser en divergerende hovedgren, en app.js-fletningskonflikt og kommandoer, der stager den løste fil og opretter konfliktløsnings-commit'en.
Løs først indholdet, opret den rettede fil i stages, og afslut derefter fletningen eller fortsæt rebasen.

Trin 4: Hvornår er det sikkert at presse igen?

Før du pusher, skal du kontrollere arbejdstræet og den seneste historik:

git status
git log --oneline --graph --decorate -n 12

Tryk derefter normalt:

git push origin main

Hvis du fusionerede den eksterne branch, eller kun rebaserede commits, der aldrig var blevet pushet før, burde et normalt push typisk være den rigtige handling, fordi det nye eksterne tip vil være en forfader til dit lokale tip.

Terminalen viser git push origin main fuldført efter integration af eksterne ændringer.
Når din gren indeholder både fjernarbejdet og dine tilsigtede lokale ændringer, kan et normalt tryk føre fjernarbejdet sikkert frem.

Hvornår skal du bruge --force-with-lease?

Brug den kun, når du bevidst omskriver en historik, der allerede findes på fjernbetjeningen — for eksempel hvis du har rebaseret en funktionsgren, som du tidligere har pushet, og nu skal erstatte den gren's gamle commit-sekvens.

git push --force-with-lease origin feature-branch

Den officielle git pushdokumentation forklarer, hvorfor dette er sikrere end almindeligt --force: ​​leasen kontrollerer, at den eksterne reference stadig har den værdi, du forventer. Hvis en anden person pushede nyt arbejde efter den tilstand, du baserede din omskrivning på, afvises den tvungne opdatering i stedet for blindt at overskrive deres commits.

Den beskyttelse er ikke en grund til rutinemæssigt at bruge force pushing. Undgå force pushing af delte branches, medmindre maindit team eksplicit tillader omskrevet historik. Server-side branch Protection kan også afvise force pushes uanset din lokale kommando.

Erstat ikke dette:

git push --force origin main

Plain --forcedeaktiverer den normale sikkerhedskontrol uden spolning fremad og kan overskrive eksterne commits. Gits egen dokumentation advarer om, at det kan forårsage, at det eksterne arkiv mister commits.

Hvad hvis du allerede har kørt den forkerte kommando?

Git har ofte stadig nok lokal historik til at gendanne en tidligere branch-position. Kør:

git reflog

Reblogs registrerer de seneste opdateringer til lokale referencer, inklusive tidligere værdier af HEAD. Hvis du finder den commit, der repræsenterede din branch før den fejlagtige nulstilling eller rebase, skal du oprette en rescue branch i stedet for at flytte den mainigen med det samme:

git branch rescue-work <commit-id>

Undersøg rescue-workog gendan nu de commits, du har brug for. Den officielle git-reflog-dokumentation beskriver reflogs som optegnelser over, hvor branch-tips og andre referencer tidligere pegede hen.

Hvorfor git pulloprettes der nogle gange en merge-commit?

git pullhenter først og integrerer derefter den valgte upstream-gren. Afhængigt af indstillingerne og repository-konfigurationen kan denne integration være en merge eller en rebase. Hvis du ønsker forudsigelig adfærd, mens du retter en ikke-spolende afvisning, skal du eksplicit angive din hensigt:

# Preserve branch history with a merge
git pull --no-rebase origin main

# Replay private local commits on top
git pull --rebase origin main

For mest synlighed, brug git fetch originførst og løb git merge origin/maineller git rebase origin/mainseparat.

Hvad hvis den eksterne commit er uønsket?

Gå ikke ud fra, at "uønsket" betyder, at det er sikkert at slette. Undersøg det først:

git fetch origin
git log --oneline --decorate HEAD..origin/main
git show origin/main

Hvis commit'en tilhører en anden udvikler, en bot, en afhængighedsopdaterer eller en ændring foretaget i webgrænsefladen, skal du integrere eller tilbageføre den via normal historik. Hvis dit team bevidst har accepteret at erstatte den eksterne historik, kan en bevogtet kraftpush være passende – men det er en beslutning om repository-historik, ikke standardløsningen til en ikke-spolingsfejl.

En tjekliste til sikker beslutning

  • Ikke-committede filer? Committ eller gem dem før integration.
  • Brug for et sikkerhedspunkt? Opret en backup-branch ved den nuværende commit.
  • Fjernbetjening ændret? Kør git fetch originfør du beslutter dig for, hvad du skal gøre.
  • Delt historik? Foretrækker du merge, hvis du vil undgå at omskrive commits.
  • Private lokale commits? Rebase kan holde historikken lineær.
  • Konflikt? Løs filen, opret en midlertidig løsning, og afslut derefter fletningen eller fortsæt rebasen.
  • Normal integration fuldført? Brug en normal git push.
  • Allerede udgivet historie, der bevidst er rebaseret? Overvej det --force-with-lease, ikke almindelig --force.

Konklusion

Beskeden om ikke at spole frem er en sikkerhedsbarriere, der fortæller dig, at den eksterne gren indeholder historik, som dit foreslåede push ikke bevarer. Løsningen er ikke at overvinde denne barriere. Beskyt dit lokale arbejde, hent den eksterne gren, undersøg divergensen, integrer den med merge eller rebase, løs konflikter bevidst, og push igen.

Hvis du husker én regel, så gør den til denne: hent og forstå, før du gennemtvinger . Det bevarer både dine ændringer og det arbejde, der allerede er på fjernbetjeningen – og forvandler en skræmmende push-afvisning til et rutinemæssigt Git-synkroniseringsproblem.

Efterlad en kommentar

Sådan rettes "ENOSPC: Systemgrænse for filovervågning nået" i Linux

Sådan rettes "ENOSPC: Systemgrænse for filovervågning nået" i Linux

Ret fejl i Linux ENOSPC-filovervågning ved at kontrollere inotify-grænser, finde processer med mange overvågningsbehov, hæve grænser sikkert og gøre ændringer permanente.

Sådan rettes "Tailwind CSS-stilarter opdateres ikke" i en Vite React-app

Sådan rettes "Tailwind CSS-stilarter opdateres ikke" i en Vite React-app

Ret problemer med Tailwind CSS-stilarter, der ikke opdateres i Vite React, ved at kontrollere Tailwind v4-opsætning, CSS-import, kildekodedetektion, dynamiske klasser, HMR og forældede cacher.

Sådan rettes ModuleNotFoundError: Intet modul med navnet 'pip' i Python 3

Sådan rettes ModuleNotFoundError: Intet modul med navnet 'pip' i Python 3

Ret Python 3's ModuleNotFoundError for pip på Windows, macOS og Linux med ensurepip, OS-pakker, virtuelle miljøer og fortolkertjek.

Sådan rettes "Tilladelse nægtet (offentlig nøgle)" i GitHub SSH

Sådan rettes "Tilladelse nægtet (offentlig nøgle)" i GitHub SSH

Ret GitHub SSH-tilladelse nægtet (publickey) ved at kontrollere værten, den aktive SSH-nøgle, GitHub-kontoen, SSO-godkendelsen, den eksterne URL og port 22-adgang.

How to Fix “Git Push Rejected: Non-Fast-Forward” Without Losing Changes

How to Fix “Git Push Rejected: Non-Fast-Forward” Without Losing Changes

Fix a Git non-fast-forward push safely. Protect local work, fetch remote commits, choose merge or rebase, resolve conflicts, and push without losing changes.

Sådan rettes "Nginx 502 Bad Gateway" ved proxy til Node.js

Sådan rettes "Nginx 502 Bad Gateway" ved proxy til Node.js

Ret Nginx 502 Bad Gateway-fejl med en Node.js upstream ved at kontrollere app-porten, NGINX-logfiler, proxy_pass-adresse, containernetværk, timeouts og genindlæsning.

Sådan rettes "Type 'null' kan ikke tildeles til type" i TypeScript

Sådan rettes "Type 'null' kan ikke tildeles til type" i TypeScript

Retter TypeScripts fejl "Type 'null' kan ikke tildeles til type" med foreningstyper, indsnævring, standardværdier og sikre påstande under strictNullChecks.

Sådan retter du fejlen "Prisma Client Has Not Been Generated Yet"

Sådan retter du fejlen "Prisma Client Has Not Been Generated Yet"

Ret fejlen med Prisma Client, der ikke er genereret, ved at kontrollere din generator, schema, output-sti, imports, versioner, monorepo-opsætning og build-trin til deployment.

Sådan rettes "ERR_MODULE_NOT_FOUND" i Node.js ESM-importer

Sådan rettes "ERR_MODULE_NOT_FOUND" i Node.js ESM-importer

Ret Node.js ERR_MODULE_NOT_FOUND i ESM ved at kontrollere importstier, filtypenavne, pakkeinstallation, eksport, ESM-tilstand og rene installationer.

Sådan løser du SSL-certifikatproblemet: Unable to get local issuer certificate i Git

Sådan løser du SSL-certifikatproblemet: Unable to get local issuer certificate i Git

Løs Git-fejlen 'unable to get local issuer certificate' ved at identificere tillidsbackenden, installere den korrekte CA-kæde og holde SSL-verifikation aktiveret.