Kako popraviti "Git Push Rejected: Non-FastForward" bez gubitka promjena

Odbijanje koje nije premotavanje unaprijed je Git koji štiti povijest, a ne briše vaš lokalni rad. Obično znači da se udaljena grana pomaknula naprijed nakon što je vaša lokalna grana zadnji put sinkronizirana, pa bi ažuriranje udaljene grane s vašom trenutnom granom odbacilo promjene koje već postoje tamo. Trenutna dokumentacija GitHuba opisuje istu situaciju: prvo dohvatite promjene uzvodno, integrirajte ih lokalno, a zatim ponovno pošaljite.

Najsigurniji opći tijek rada je: zaštititi sav nepotvrđeni rad, dohvatiti udaljenu granu bez mijenjanja trenutne grane, pregledati kako su se povijesti razišle, odabrati spajanje ili ponovno baziranje, riješiti sukobe ako je potrebno i ponovno poslati. Nemojte počinjati s git push --forceili git reset --hardsamo da biste uklonili grešku.

Službene reference korištene za ovaj vodič uključuju GitHub dokumentaciju: Rješavanje pogrešaka koje nisu povezane s premotavanjem unaprijed , Git: dokumentacija za git-push , Git: dokumentacija za git-fetch i Git: dokumentacija za git-rebase .

Što zapravo znači "nema brzog premotavanja"?

Pretpostavimo da vaša lokalna maingrana sadrži commit L, dok je udaljena grana origin/mainnapredovala na drugi commit R. Ako nijedan commit nije predak drugog, povijesti su se razišle. Normalni push ne može jednostavno pomaknuti pokazivač udaljene grane na Lbez da Rnestane iz vidljive povijesti te grane.

Ažuriranje ubrzanim premotavanjem je drugačije: novi savjet grane je potomak stare, pa pomicanje grane naprijed čuva sve što je već dostupno iz nje. Službeni git pushpriručnik definira ovo pravilo predaka i upozorava da ono --forceonemogućuje normalnu zaštitu i može uzrokovati gubitak udaljenih commitova.

Terminal prikazuje da je git push origin main odbijen s greškom koja ne omogućuje brzo premotavanje jer udaljeni poslužitelj sadrži rad koji nije prisutan lokalno.
Odbijanje koje ne omogućuje brzo premotavanje znači da Git odbija zamijeniti udaljenu povijest koju vaša lokalna grana još ne sadrži.

Prije nego što išta poduzmete: je li vaš lokalni rad sigurno zabilježen?

Trčanje:

git status

Ako je radno stablo čisto, vaše trenutne promjene su već predstavljene commitovima i možete stvoriti dodatnu sigurnosnu referencu prije integracije daljinskog upravljača:

git branch backup-before-sync

Ta grana pokazuje na trenutni commit, tako da imate jednostavan naziv za stanje prije integracije.

Ako ste modificirali ili nepraćene datoteke koje nisu potvrđene, odaberite jedan od ovih pristupa prije povlačenja ili ponovnog baziranja:

  • Potvrdite ih ako je rad logički spreman za potvrđivanje.
  • Spremite ih ako je posao nedovršen git stash push -u -m "before non-fast-forward fix":.

Opcija -uuključuje nepraćene datoteke. Službena dokumentacija za git-stash objašnjava da stash bilježi radni direktorij i stanje indeksa te vraća čisto radno stablo. Ignorirane datoteke nisu uključene od -u; -abi uključivao i ignorirane datoteke, ali to je rijetko potrebno za ovaj problem.

Važno: ako git statusprikazuje datoteke koje si ne možete priuštiti izgubiti, nemojte pokretati git reset --hard. Ta naredba može odbaciti nepotvrđene promjene radnog stabla.

Korak 1: Trebate li git pullodmah upotrijebiti?

Možete, ali je lakše razmišljati o tome da prvo dohvatite . GitHub dokumentira koji git fetchpreuzima udaljeni rad i ažurira grane za udaljeno praćenje bez spajanja tih promjena u vašu trenutnu granu. To ga čini korisnim dijagnostičkim korakom jer možete pregledati situaciju prije promjene lokalne povijesti.

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

Nakon dohvaćanja, grana za udaljeno praćenje origin/mainpredstavlja udaljeno stanje koje ste upravo dohvatili. Naredba log omogućuje vam da vidite commite dostupne samo s vaše lokalne strane i samo s udaljene strane.

Ako vaša lokalna grana nema jedinstvenih commitova i jednostavno kasni, često je možete premotati unaprijed:

git merge --ff-only origin/main

Tada nema ništa za usklađivanje; vaša grana jednostavno ide naprijed.

Korak 2: Spajanje ili ponovno baziranje - što odabrati?

Oba mogu sačuvati vaše promjene. Razlika je u obliku rezultirajuće povijesti.

Situacija Obično biraju Zašto
Zajednička grana, kao na primjer maingdje vaši lokalni commiti mogu već biti poznati drugima Spojiti Čuva postojeće identitete commitova i ne prepisuje vaše lokalne commite.
Vaši commiti su lokalni/privatni i želite linearnu povijest Ponovno baziranje Ponovno reproducira vaše lokalne commite preko ažurirane udaljene grane.
Niste sigurni i želite što manje prekrajanja povijesti Spojiti Lakše je objasniti i sigurnije je za zajedničku povijest.

Spoji rutu

git fetch origin
git merge origin/main

Ako nema sukoba, Git dovršava integraciju. Ako su se grane doista razišle, rezultat može uključivati ​​commit spajanja.

Rebaziranje rute

git fetch origin
git rebase origin/main

Rebase uzima commitove koji su jedinstveni za vašu trenutnu granu i ponovno ih primjenjuje na origin/main. Gitova dokumentacija rebasea opisuje to kao presađivanje niza commitova na drugu početnu točku. Budući da ti commiti dobivaju nove ID-ove commita, rebase se najbolje koristi za lokalni rad koji još nije podijeljen kao javna povijest.

Ako preferirate prečac, git pull --rebase origin mainizvodi dohvaćanje nakon čega slijedi ponovno poravnanje, dok git pull --no-rebase origin maineksplicitno odabire ponašanje spajanja. Za situaciju oporavka, naredbe separate fetchi merge/ rebasečesto su jasnije jer prvo možete pregledati udaljeno stanje.

Terminal koji prikazuje git pull origin main kako dohvaća udaljene objekte i ažurira granu s udaljenim promjenama.
Nakon što se dohvate udaljene promjene, namjerno ih integrirajte - spajanjem ili rebaseiranjem - umjesto da ih prepišete.

Korak 3: Što učiniti ako Git prijavi konflikt?

Sukob ne znači da su vaše promjene nestale. To znači da Git ne može automatski odlučiti kako kombinirati promjene na istom sadržaju.

Prvo provjerite stanje:

git status

Otvorite svaku konfliktnu datoteku, odlučite kakav bi trebao biti konačni sadržaj, uklonite oznake konflikta, a zatim pripremite riješenu datoteku:

git add path/to/file

Ako ste odabrali spajanje, dovršite spajanje nakon što su svi sukobi pripremljeni:

git commit

Ako ste odabrali rebase, nastavite ponovno izvoditi svoje commite:

git rebase --continue

Ako rebase ide loše i želite vratiti granu u stanje prije rebase-a, koristite:

git rebase --abort

Trenutni Git priručnik za rebase posebno dokumentira --continuei --abortu tu svrhu. Nemojte koristiti git rebase --skipsamo za uklanjanje sukoba osim ako zapravo ne namjeravate izostaviti ponavljanje commita.

Terminal koji prikazuje divergiranu glavnu granu, sukob spajanja app.js-a i naredbe koje pripremaju riješenu datoteku i stvaraju commit za rješavanje sukoba.
Prvo riješite sadržaj, pripremite ispravljenu datoteku, a zatim dovršite spajanje ili nastavite ponovno baziranje.

Korak 4: Kada je sigurno ponovno gurati?

Prije slanja, provjerite radno stablo i nedavnu povijest:

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

Zatim pritisnite normalno:

git push origin main

Ako ste spojili udaljenu granu ili rebazirali samo commitove koji nikada prije nisu bili poslani, normalno slanje bi obično trebalo biti ispravna operacija jer će novi udaljeni savjet biti predak vašeg lokalnog savjeta.

Terminal koji prikazuje uspješno dovršavanje git push origin main naredbe nakon integracije udaljenih promjena.
Nakon što vaša grana sadrži i udaljeni rad i namjeravane lokalne promjene, normalno dodavanje može sigurno pomaknuti udaljeni rad naprijed.

Kada biste trebali koristiti --force-with-lease?

Koristite ga samo kada ste namjerno prepisali povijest koja već postoji na udaljenom poslužitelju - na primjer, prebazirali ste granu značajke koju ste prethodno gurnuli i sada trebate zamijeniti stari commit niz te grane.

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

Službena git pushdokumentacija objašnjava zašto je ovo sigurnije od običnog --force: lease provjerava ima li udaljena referenca još uvijek vrijednost koju očekujete. Ako je neka druga osoba poslala novi rad nakon stanja na kojem ste temeljili svoje prepisivanje, prisilno ažuriranje se odbija umjesto da se slijepo prepisuju njihovi commiti.

Ta zaštita nije razlog za rutinsko korištenje prisilnog slanja. Izbjegavajte prisilno slanje dijeljenih grana, osim mainako vaš tim izričito ne dopušta prepisivanje povijesti. Zaštita grana na strani poslužitelja također može odbiti prisilno slanje bez obzira na vašu lokalnu naredbu.

Nemojte ovo zamijeniti:

git push --force origin main

Plain --forceonemogućuje normalnu sigurnosnu provjeru koja nije premotavanje unaprijed i može prebrisati udaljene commitove. Gitova vlastita dokumentacija upozorava da to može uzrokovati gubitak commitova u udaljenom repozitoriju.

Što ako ste već pokrenuli pogrešnu naredbu?

Git često još uvijek ima dovoljno lokalne povijesti za oporavak prethodne pozicije grane. Pokrenite:

git reflog

Reflogovi bilježe nedavna ažuriranja lokalnih referenci, uključujući prethodne vrijednosti HEAD. Ako pronađete commit koji je predstavljao vašu granu prije pogrešnog resetiranja ili rebase-a, stvorite rescue granu umjesto da se odmah mainponovno krećete:

git branch rescue-work <commit-id>

Sada pregledajte rescue-worki oporavite potrebne commitove. Službena dokumentacija za git-reflog opisuje reflogove kao zapise o tome gdje su prethodno ukazivali savjeti za grananje i druge reference.

Zašto se git pullponekad stvarao commit spajanja?

git pullprvo dohvaća, a zatim integrira odabranu uzvodnu granu. Ovisno o opcijama i konfiguraciji repozitorija, ta integracija može biti spajanje ili rebase. Ako želite predvidljivo ponašanje prilikom ispravljanja odbijanja koje nije premotavanje unaprijed, izričito navedite svoju namjeru:

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

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

Za najbolju vidljivost, koristite git fetch originprvo pa trčite git merge origin/mainili git rebase origin/mainodvojeno.

Što ako je udaljeni commit neželjen?

Nemojte pretpostavljati da "neželjeno" znači da je sigurno izbrisati. Prvo ga pregledajte:

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

Ako commit pripada drugom programeru, botu, ažuriratelju ovisnosti ili je promjena napravljena u web sučelju, integrirajte ga ili vratite kroz normalnu povijest. Ako se vaš tim namjerno složio da zamijeni udaljenu povijest, tada bi moglo biti prikladno zaštićeno prisilno slanje - ali to je odluka o povijesti repozitorija, a ne standardno rješenje za pogrešku koja ne uključuje premotavanje unaprijed.

Kontrolna lista za sigurne odluke

  • Nepotvrdene datoteke? Potvrdite ih ili spremite prije integracije.
  • Trebate sigurnosnu točku? Napravite sigurnosnu granu na trenutnom commitu.
  • Daljinski upravljač promijenjen? Pokrenite git fetch originprije nego što odlučite što učiniti.
  • Dijeljena povijest? Preferirate spajanje ako želite izbjeći prepisivanje commitova.
  • Privatne lokalne izmjene? Rebase može održati povijest linearnom.
  • Sukob? Riješite datoteku, pripremite je, a zatim dovršite spajanje ili nastavite ponovno baziranje.
  • Je li normalna integracija dovršena? Koristite normalnu git push.
  • Već objavljena povijest namjerno preoblikovana? Razmotrite --force-with-lease, a ne običan --force.

Zaključak

Poruka o nepremotavanju je sigurnosna barijera koja vam govori da udaljena grana sadrži povijest koju vaše predloženo slanje ne čuva. Rješenje nije u prevladavanju te barijere. Zaštitite svoj lokalni rad, dohvatite udaljenu granu, pregledajte divergenciju, integrirajte je sa spajanjem ili rebaseom, namjerno riješite sukobe i ponovno pošaljite.

Ako se sjećate jednog pravila, neka bude ovo: dohvati i razumi prije nego što prisiliš promjenu . To čuva i tvoje promjene i rad koji je već na daljinu - i pretvara zastrašujuće odbijanje push-a u rutinski problem sinkronizacije Gita.

Ostavite komentar

Kako popraviti grešku "Tailwind CSS stilovi se ne ažuriraju" u Vite React aplikaciji

Kako popraviti grešku "Tailwind CSS stilovi se ne ažuriraju" u Vite React aplikaciji

Ispravite Tailwind CSS stilove koji se ne ažuriraju u Vite Reactu provjerom postavki Tailwind v4, CSS uvoza, otkrivanja izvora, dinamičkih klasa, HMR-a i zastarjelih predmemorija.

Kako popraviti ModuleNotFoundError: Nema modula pod nazivom 'pip' u Pythonu 3

Kako popraviti ModuleNotFoundError: Nema modula pod nazivom 'pip' u Pythonu 3

Ispravite ModuleNotFoundError u Pythonu 3 za pip na Windowsima, macOS-u i Linuxu pomoću ensurepipa, OS paketa, virtualnih okruženja i provjera interpretera.

Kako popraviti "Dozvola odbijena (javni ključ)" u GitHub SSH-u

Kako popraviti "Dozvola odbijena (javni ključ)" u GitHub SSH-u

Ispravite GitHub SSH Permission Denied (publickey) provjerom hosta, aktivnog SSH ključa, GitHub računa, SSO autorizacije, udaljenog URL-a i pristupa portu 22.

Kako popraviti "Git Push Rejected: Non-FastForward" bez gubitka promjena

Kako popraviti "Git Push Rejected: Non-FastForward" bez gubitka promjena

Sigurno ispravite Git push koji ne omogućuje brzo premotavanje. Zaštitite lokalni rad, dohvatite udaljene commitove, odaberite spajanje ili rebase, riješite sukobe i pushajte bez gubitka promjena.

Kako popraviti "Nginx 502 Bad Gateway" prilikom proxyja za Node.js

Kako popraviti "Nginx 502 Bad Gateway" prilikom proxyja za Node.js

Ispravite greške Nginx 502 Bad Gateway s Node.js uzvodno provjerom porta aplikacije, NGINX logova, proxy_pass adrese, umrežavanja kontejnera, vremenskih ograničenja i ponovnog učitavanja.

Kako popraviti "Tip 'null' se ne može dodijeliti tipu" u TypeScriptu

Kako popraviti "Tip 'null' se ne može dodijeliti tipu" u TypeScriptu

Ispravljena je greška "Tip 'null' nije moguće dodijeliti tipu" u TypeScriptu s tipovima unija, sužavanjem, zadanim vrijednostima i sigurnim tvrdnjama pod strictNullChecks.

Kako ispraviti pogrešku „Prisma Client has not been generated yet”

Kako ispraviti pogrešku „Prisma Client has not been generated yet”

Ispravite pogrešku da Prisma Client nije generiran provjerom generatora, sheme, izlazne putanje, uvoza, verzija, monorepo postavki i koraka izgradnje pri implementaciji.

Kako ispraviti "ERR_MODULE_NOT_FOUND" u Node.js ESM uvozima

Kako ispraviti "ERR_MODULE_NOT_FOUND" u Node.js ESM uvozima

Ispravite Node.js ERR_MODULE_NOT_FOUND u ESM-u provjerom putanja uvoza, ekstenzija datoteka, instalacije paketa, izvoza, ESM načina rada i čistih instalacija.

Kako riješiti problem sa SSL certifikatom: Nemoguće dobiti lokalni certifikat izdavatelja u Gitu

Kako riješiti problem sa SSL certifikatom: Nemoguće dobiti lokalni certifikat izdavatelja u Gitu

Riješite Gitovu grešku 'nemoguće dobiti lokalni certifikat izdavatelja' identificiranjem pozadine povjerenja, instaliranjem ispravnog lanca CA i održavanjem omogućene SSL verifikacije.

Kako riješiti grešku mrežnog isteka vremena MongoDB u Mongoose vezi

Kako riješiti grešku mrežnog isteka vremena MongoDB u Mongoose vezi

Riješite greške mrežnog isteka vremena MongoDB u Mongooseu identificiranjem vrste isteka, testiranjem dostupnosti Atlasa ili TCP-a, ispravljanjem URI-ja i podešavanjem vremena isteka samo kada je opravdano.