Vezérlőpult
19. Szinkronizálási helyzetek · Távoli tárolók: GitHub

4. témakör · Távoli tárolók: GitHub · 19. fejezet

Szinkronizálási helyzetek

Amikor többen dolgoznak ugyanazon a repón, előbb-utóbb jönnek a piros üzenetek: rejected, divergent branches, CONFLICT. Ezek nem hibák, hanem a Git védekezése: nem enged felülírni mások munkáját. Ebben a fejezetben végigmegyünk a tipikus helyzeteken, megtanulod, mikor és hogyan használd (és mikor ne) a --force-t, és mit tegyél, ha minden összekuszálódott.

CLI + DesktopSzinkron-mentőcsapatBesorolóSzimulátor15 kvízkérdés

Tanulási célok

1Áttekintés: a tipikus helyzetek

ÜzenetMi történt?Megoldás
! [rejected] … (fetch first)a GitHubon van olyan commit, ami nálad nincsgit pull, majd git push
! [rejected] … (non-fast-forward)a GitHubon lévő ág nem őse a tiédnek (pl. amend/rebase után)git pull; saját ágon esetleg --force-with-lease
Need to specify how to reconcile divergent branchesmindkét oldalon van új commit, és nincs beállítva, hogyan egyesüljenekgit config pull.rebase false (vagy true), majd újra pull
CONFLICT (content) pull utánugyanazt a részt mindketten eltérően módosítottátokfeloldás (13. fejezet), git add, git commit / rebase --continue, push
would be overwritten by mergenem commitolt munkád van, amit a pull felülírnacommit, vagy git stash → pull → git stash pop
refusing to merge unrelated historiesa két történetnek nincs közös őse (pl. README-vel létrehozott repó)git pull --allow-unrelated-histories (17. fejezet)

2Elutasított push

PS> git push
To https://github.com/anna-kovacs/osztalyoldal.git
 ! [rejected]        main -> main (fetch first)
error: failed to push some refs to 'https://github.com/anna-kovacs/osztalyoldal.git'
hint: Updates were rejected because the remote contains work that you do not
hint: have locally. …

Péter feltöltött, amíg te dolgoztál. Ha a Git elfogadná a push-t, Péter commitja eltűnne a GitHubról. Ezért a GitHub csak akkor fogad el egy push-t, ha az előretolás (fast-forward): a GitHubon lévő ág a te ágad őse. A megoldás mindig ugyanaz: előbb beépíted a GitHubon lévő munkát, aztán töltesz fel.

PS> git pull      # letöltés + beépítés (merge vagy rebase)
PS> git push      # most már előretolás: sikerül
⛔ NE A --FORCE LEGYEN AZ ELSŐ ÖTLET

A git push --force itt „megoldaná” a hibát úgy, hogy törli Péter commitját a GitHubról. Elutasított push-ra a válasz: pull.

3Szétvált ágak

Ha nálad is és a GitHubon is van új commit, a két ág szétvált (diverged). Az újabb Git ilyenkor nem dönt helyetted, hanem megáll:

hint: You have divergent branches and need to specify how to reconcile them.
hint:   git config pull.rebase false  # merge
hint:   git config pull.rebase true   # rebase
hint:   git config pull.ff only       # fast-forward only
fatal: Need to specify how to reconcile divergent branches.
Beállítás / kapcsolóMi történik szétváláskor?Eredmény
pull.rebase false · git pull --no-rebasemerge commit készüla történet megmutatja az elágazást
pull.rebase true · git pull --rebasea helyi commitjaid a GitHub-os ág mögé kerülnek (új hash)egyenes történet
pull.ff only · git pull --ff-onlymegáll, ha nem lehet előretolnicsak tiszta frissítés

Kezdőknek jó választás a globális beállítás: git config --global pull.rebase false. Ha a csapat egyenes történetet szeretne, akkor true. A pull-rebase nyugodtan használható, mert a saját, még fel nem töltött commitjaidat írja át (14. fejezet).

4Ütközés pull közben

Ha ugyanazt a sort Péter is és te is módosítottátok, a pull beépítő lépése ütközést jelez. A feloldás pontosan olyan, mint a 13. fejezetben:

merge-es pull után

PS> git pull
CONFLICT (content): Merge conflict in index.html
# … feloldás a fájlban …
PS> git add index.html
PS> git commit --no-edit
PS> git push

rebase-es pull után

PS> git pull --rebase
CONFLICT (content): Merge conflict in index.html
# … feloldás a fájlban …
PS> git add index.html
PS> git rebase --continue
PS> git push

Kiszállás: git merge --abort, illetve git rebase --abort. A feloldás után ne felejtsd el a push-t: amíg nem töltöd fel, a GitHubon továbbra is csak Péter változata van.

5Nem commitolt munka pull előtt

error: Your local changes to the following files would be overwritten by merge:
	index.html
Please commit your changes or stash them before you merge.
Aborting

A pull nem kezd bele, mert felülírná a még nem commitolt munkádat. Két megoldás:

6Force push: mikor igen, mikor ne

A git push --force a GitHubon lévő ágat felülírja a tiéddel, akkor is, ha ezzel commitok tűnnek el. Van jogos használata: ha a saját, csak általad használt ágadat írtad át (amend, rebase, 10. és 14. fejezet), a sima push elutasítódik (non-fast-forward), mert a régi commitok fent vannak.

ParancsMit csinál?
git push --forcevakon felülír: ha közben más is feltöltött, az ő munkája elveszik
git push --force-with-leasecsak akkor ír felül, ha a GitHubon az ág még ott áll, ahol a legutóbbi fetch-kor látted; ha közben más feltöltött, elutasítja (stale info)
⛔ KÖZÖS ÁGRA SOHA

A main-re és minden ágra, amelyen más is dolgozik, ne force push-olj. Csapatban a main-t érdemes a GitHubon védetté tenni (branch protection, 24. fejezet): ott a force push be sem engedett. Ha egy közös ágon hibás commit van, arra a git revert való (10. fejezet).

7Ha minden összekuszálódott

Ha a helyi repód annyira összekeveredett, hogy inkább eldobnád a helyi változásokat, és pontosan a GitHubon lévő állapotot vennéd át:

PS> git fetch
PS> git branch mentes                # biztonsági címke a mostani állapotra (ha mégis kellene)
PS> git reset --hard origin/main     # a main pontosan a GitHub-os állapotra áll
⚠️ A HELYI, FEL NEM TÖLTÖTT MUNKA ELVÉSZ

A reset --hard a nem commitolt változásokat végleg eldobja, a fel nem töltött commitokat pedig lekapcsolja az ágról (a reflogból még visszahozhatók, 10. fejezet). Ezért előtte a git branch mentes egy olcsó biztosítás. Az utolsó menedék: egy friss klón egy másik mappába.

8Szinkron-mentőcsapat

Válaszd ki, milyen üzenetet kaptál (vagy mi a helyzet), és a mentőcsapat megmondja a lépéseket!

Mit írt a Git?

pull, --force-with-lease vagy revert?

Melyik a helyes (és biztonságos) lépés?

1 / 8Pontszám: 0
…

9A Desktopban és a VS Code-ban

Desktop GitHub Desktop
  • Ha push-olnál, de a GitHubon van újabb, a Desktop figyelmeztet (Newer commits on remote), és Fetch, majd Pull origin gombot kínál.
  • Szétvált ágaknál a Pull origin merge commitot készít (vagy a beállításod szerinti rebase-t); ütközésnél a megszokott Resolve conflicts ablak jön.
  • Ha a Desktopban átírtál egy már feltöltött commitot (amend, squash, átrendezés), a gomb Force push origin lesz, és a Desktop rákérdez, biztos vagy-e benne. (A Desktop is lease-t használ a háttérben.)
IDE VS Code
  • Elutasított push-nál: Can't push refs to remote. Try running "Pull" first to integrate your changes. A Sync gomb pull + push egyben.
  • A … menüben: Pull (Rebase) és Push (Force). Ez utóbbi alapból --force-with-lease; a git.allowForcePush beállítás kell hozzá.

10Gyakorlás a szimulátorban

Az osztalyoldal repón Péterrel dolgoztok. Amíg te a gépeden dolgoztál, Péter már feltöltött, ugyanabba a sorba. Oldd meg sorban a helyzeteket!

PowerShell + Git

Windows PowerShell
Küldetések 0 / 9
    A gépeden
    A GitHubonanna-kovacs/osztalyoldal

    11Feladatok

    Gyakorló feladatok

    ⭐ alap · ⭐⭐ haladó · ⭐⭐⭐ kihívás

    19.1⭐Web

    Egy saját repódban módosítsd a README-t a GitHub weboldalán, és ugyanazt a sort a gépeden is (commit). Próbálj feltölteni: olvasd el az elutasítást, majd oldd meg pull-lal.

    19.2⭐CLI

    Nézd meg, mi a beállításod: git config --global pull.rebase. Ha nincs, döntsd el a fejezet alapján, mit állítasz be, és indokold egy mondatban.

    19.3⭐

    Menj végig a Szinkron-mentőcsapat összes esetén, és írj egy egyoldalas „piros üzenetek” puskát a saját szavaiddal.

    19.4⭐⭐CLI

    Egy saját feature ágadon, amelyet már feltöltöttél, írd át az utolsó commit üzenetét (--amend). Mit mond a sima git push? Töltsd fel --force-with-lease-szel.

    19.5⭐⭐Desktop

    Párban: mindketten módosítsátok ugyanazt a sort, az egyik töltsön fel, a másik a GitHub Desktopban pull-oljon, oldja fel az ütközést, és töltse fel.

    19.6⭐⭐CLI

    Egy gyakorló repóban szándékosan kuszáld össze a main-t (néhány rossz commit, nem commitolt szemét), majd állítsd a GitHub-os állapotra: git fetch, git branch mentes, git reset --hard origin/main. Ellenőrizd, hogy a mentes ágon megvan-e a régi állapot.

    19.7⭐⭐⭐CLI

    Mutasd be a --force és a --force-with-lease különbségét két géppel (vagy két klónnal): az egyikről tölts fel, a másikról amendelj és próbáld mindkét kapcsolóval. Melyik veszítette volna el a másik munkáját?

    12Önellenőrző kvíz

    Ellenőrizd magad!

    Az egyválasztós kérdéseknél kattints a válaszra. A többválasztósaknál jelöld be az összes helyeset, majd nyomd meg az Ellenőrzés gombot.

    13Fogalomtár

    FogalomJelentés
    rejected (fetch first)elutasított push: a GitHubon van olyan commit, ami nálad nincs
    non-fast-forwarda push nem előretolás: a távoli ág nem őse a helyinek
    szétvált ágak (diverged)a helyi és a távoli ágon is van új commit
    pull.rebase / pull.ffbeállítás arról, hogyan egyesítse a pull a szétvált ágakat (merge, rebase, csak előretolás)
    force pushgit push --force: a távoli ág felülírása, akkor is, ha commitok vesznek el
    --force-with-leasebiztonságosabb felülírás: elutasít, ha közben más feltöltött (stale info)
    védett ág (branch protection)GitHub-szabály: pl. a main-re tilos a force push és a közvetlen push (24. fejezet)
    git reset --hard origin/maina helyi ág a letöltött távoli állapotra áll; a helyi munka elvész

    14Összegzés

    1. Elutasított push (fetch first / non-fast-forward): pull, esetleg feloldás, aztán push. Nem force!
    2. Szétvált ágaknál a pull megállhat: állítsd be a pull.rebase-t (false: merge, true: rebase), vagy használd a --no-rebase / --rebase kapcsolót.
    3. Pull-ütközés: feloldás, git add, git commit (vagy git rebase --continue), és a végén push.
    4. Nem commitolt munka pull előtt: commit vagy stash.
    5. Force push csak saját, átírt ágra, és akkor is --force-with-lease; közös ágra soha. Mentés: git branch mentes + git reset --hard origin/main.

    Ezzel a szinkronizálás eszköztára teljes. A következő témakörben a GitHub csapatmunka-eszközei jönnek, elsőként a pull request.