-
1. Pričetek
- 1.1 O nadzoru različic
- 1.2 Kratka zgodovina Gita
- 1.3 Kaj je Git?
- 1.4 Ukazna vrstica
- 1.5 Git namestitev
- 1.6 Prva namestitev Gita
- 1.7 Pridobivanje pomoči
- 1.8 Povzetek
-
2. Osnove Git
- 2.1 Pridobivanje repozitorija Git
- 2.2 Snemanje sprememb v repozitorij
- 2.3 Pregled zgodovine potrditev
- 2.4 Razveljavljanje stvari
- 2.5 Delo z daljavami
- 2.6 Označevanje
- 2.7 Git aliasi
- 2.8 Povzetek
-
3. Veje Git
- 3.1 Veje na kratko
- 3.2 Osnove vej in združevanja
- 3.3 Upravljanje vej
- 3.4 Potek dela z vejami
- 3.5 Oddaljene veje
- 3.6 Ponovno baziranje (rebasing)
- 3.7 Povzetek
-
4. Git na strežniku
- 4.1 Protokoli
- 4.2 Pridobiti Git na strežnik
- 4.3 Generiranje vaših javnih ključev SSH
- 4.4 Nastavitev strežnika
- 4.5 Prikriti proces Git
- 4.6 Pametni HTTP
- 4.7 GitWeb
- 4.8 GitLab
- 4.9 Tretje osebne opcije gostovanja
- 4.10 Povzetek
-
5. Distribuirani Git
- 5.1 Razdeljeni poteki dela
- 5.2 Prispevanje projektu
- 5.3 Vzdrževanje projekta
- 5.4 Povzetek
-
6. GitHub
-
7. Orodja Git
- 7.1 Revision Selection
- 7.2 Interactive Staging
- 7.3 Stashing and Cleaning
- 7.4 Signing Your Work
- 7.5 Searching
- 7.6 Rewriting History
- 7.7 Reset Demystified
- 7.8 Advanced Merging
- 7.9 Rerere
- 7.10 Debugging with Git
- 7.11 Submodules
- 7.12 Bundling
- 7.13 Replace
- 7.14 Credential Storage
- 7.15 Povzetek
-
8. Prilagoditev Gita
- 8.1 Git Configuration
- 8.2 Git Attributes
- 8.3 Kljuke Git
- 8.4 An Example Git-Enforced Policy
- 8.5 Povzetek
-
9. Git in ostali sistemi
- 9.1 Git kot klient
- 9.2 Migracija na Git
- 9.3 Povzetek
-
10. Notranjost Gita
- 10.1 Napeljava in keramika
- 10.2 Git Objects
- 10.3 Git References
- 10.4 Packfiles
- 10.5 Refspec
- 10.6 Transfer Protocols
- 10.7 Maintenance and Data Recovery
- 10.8 Environment Variables
- 10.9 Povzetek
-
A1. Dodatek A: Git v drugih okoljih
- A1.1 Grafični vmesniki
- A1.2 Git v programu Visual Studio
- A1.3 Git v Visual Studio Code
- A1.4 Git v IntelliJ / PyCharm / WebStorm / PhpStorm / RubyMine
- A1.5 Git v Sublime Text
- A1.6 Git v Bashu
- A1.7 Git v Zsh
- A1.8 Git v Powershellu
- A1.9 Povzetek
-
A2. Dodatek B: Vdelava Gita v vašo aplikacijo
- A2.1 Git v ukazni vrstici
- A2.2 Libgit2
- A2.3 JGit
- A2.4 go-git
- A2.5 Dulwich
-
A3. Dodatek C: Ukazi Git
- A3.1 Nastavitev in konfiguracija
- A3.2 Pridobivanje in ustvarjanje projektov
- A3.3 Osnove posnetkov
- A3.4 Veje in združevanje
- A3.5 Deljenje in posodabljanje projektov
- A3.6 Pregled in primerjava
- A3.7 Razhroščevanje
- A3.8 Popravljanje
- A3.9 E-pošta
- A3.10 Zunanji sistemi
- A3.11 Administracija
- A3.12 Orodja za vododovodne sisteme
3.6 Veje Git - Ponovno baziranje (rebasing)
Ponovno baziranje (rebasing)
V Git-u sta dva glavna načina za integracijo sprememb iz ene veje v drugo: merge
in rebase
.
V tej sekciji se boste naučili, kaj je rebasing, kako ga narediti, zakaj je precej posebno orodje in v katerih primerih, ga ne boste uporabljali.
Osnovno ponovno baziranje
Če se vrnete na prejšnji primer iz Basic Merging, lahko vidite, da ste se oddaljili od vašega dela in naredili pošiljanja na dveh različnih vejah.

Najenostavnejši način za integracijo vej, kot smo to že pokrili je ukaz merge
.
Izvede tri-načinsko združevanje med dvema zadnjima posnetkoma vej (C3
in C4
) in najbolj zadnji skupen prednik obeh (C2
), ustvarjanje novega posnetka (in pošiljanje).

Vendar obstaja še drug način: lahko vzamete popravek spremembe, ki je bil predstavljen v C4
in ga ponovno uporabite na vrhu C3
.
V Git-u se to imenuje rebasing.
Z ukazom rebase
lahko vzamete vse spremembe, ki so bile poslane na eni veji in jih ponovite na drugi.
V tem primeru bi pognali sledeče:
$ git checkout experiment
$ git rebase master
First, rewinding head to replay your work on top of it...
Applying: added staged command
Deluje, če greste do skupnega prednika obeh vej (ene na kateri ste in druge katero ponovno bazirate), pridobitev diff-a predstavljenega z vsakim pošiljanjem veje na kateri ste, shranjevanje teh diff-ov v začasne datoteke, ponastavljanje trenutne veje na istem pošiljanju kot je veja, na katero bazirate in končno uporaba vsake spremebe v zameno.

C4
onto C3
Na tej točki lahko greste nazaj k master veji in naredite združevanje s hitrim pomikanjem naprej (fast-forward).
$ git checkout master
$ git merge experiment

Sedaj, ko posnetek kaže k C4
je točno enak kot tisti, ki je bil pokazan na s strani C5
v primeru združevanja.
Ni razlike v končnem produktu integracije vendar ponovno baziranje naredi čistejšo zgodovino.
Če primerjate dnevnik ponovno baziranje veje izgleda kot linearna zgodovina: izgleda, da se je vso delo zgodilo v serijah tudi ko se je prvotno zgodilo vzporedno.
Pogostokrat boste to naredili, da zagotovite, da se vaša pošiljanja uporabijo čisto na oddaljeni veji - mogoče v projektu kateremu poskušate prispevati vendar ga ne vzdržujete.
V tem primeru bi naredili vaše delo na veji in nato osnovali vaše delo glede na to origin/master
, ko ste pripravljeni poslati vaše popravke glavnemu projektu.
Na ta način vzdrževalcu ni treba narediti nikakršnega integracijskega dela - samo fast-forward ali čisto uporabo.
Bodite pozorni, saj posnetek na katerega kaže končno pošiljanje, s katerim ste končali, bodisi je zadnje ponovno baziranega pošiljanja za rebase ali končno pošiljanje združevanja po združevanju, gre za isti posnetek - samo zgodovina je, kar je drugačno. Rebasing ponovno predvaja spremembe iz ene vrstice dela v drugo v vrstnem redu, ki so bile predstabljene, medtem ko združevanje vzame končne točke in jih združi skupaj.
Bolj zanimivi rebasing
Lahko tudi imate vaše ponovno predvajanje rebase-a na nečem drugem od ciljne rebase veje.
Vzamimo zgodovino, kot je A history with a topic branch off another topic branch za primer.
Naredili ste tematsko vejo (server
), da ste dodali nekaj funkcionalnosti strežniške strani vašemu projektu in naredili ste pošiljanje.
Nato ste od tam naredili razvejanje, da ste naredili spremembe strani klienta (client
) in nekajkrat poslali.
Končno ste šli nazaj na vašo vejo server in naredili nekaj več pošiljanj.

Predpostavimo, da se odločite, da želite združiti vaše spremembe strani klienta v vašo glavno izdajo, vendar se želite držati stran od sprememb strežniške strani dokler ni nadaljnje testirano.
Lahko vzamete spremembe na klientu, ki niso na strežniku (C8
and C9
) in jih ponovno predvajate na vaši veji master z uporabo opcije --onto
na git rebase
:
$ git rebase --onto master server client
To v osnovi pove, Izpišite vejo client, ugotovite popravke iz skupnih prednikov vej
master.''
Je nekoliko bolj kompleksno, vendar rezultat je precej kul.client
in server
in jih nato ponovno predvajajte na

Sedaj lahko naredite fast-forward na vaši veji master (glejte Fast-forwarding your master branch to include the client branch changes):
$ git checkout master
$ git merge client

Recimo, da se odločite potegniti tudi na vašo vejo server.
Lahko naredite rebase na veji server glede na vejo master brez, da jo morate najprej izpisati s pogonom git rebase [basebranch] [topicbranch]
- kar izpiše tematsko vejo (v tem primeru server
) za vas in jo ponovno predvajate na osnovni veji (master
):
$ git rebase master server
To ponovno predvaja vaše delo server
na vrhu vašega dela master
, kot je prikazano v Rebasing your server branch on top of your master branch.

Nato lahko naredite fast-forward na osnovni veji (master
):
$ git checkout master
$ git merge server
Lahko odstranite veji client
in server
, ker je celotno delo integrirano in ju ne potrebujete več, kar pusti vašo zgodovino za ta celotenn proces izgledati kot Final commit history:
$ git branch -d client
$ git branch -d server

Nevarnosti ponovnega baziranja
Ahh, vendar blagoslova ponovnega baziranja ni brez njegovih slabih strani, ki so lahko povzete v eni vrstici:
Pošiljanj, ki obstojajo izven vašega repozitorija ne ponovno bazirajte.
Če sledite tem smernicam, boste v redu. Če ne, vas bodo ljudje sovražili in zaničevani boste s strani prijateljev in družine.
Ko ponovno bazirate, opuščate obstoječa pošiljanja in ustvarjate nove, ki so podobna vendar drugačna.
Če potisnete pošiljanja nekaj in jih ostali potegnejo in bazirajo svoje delo na njih in nato vi prepišete ta pošiljanja z git rebase
in jih potisnete ponovno, bodo vaši sodelavci morali narediti ponovno združevanje njihovega dela in stvari bodo postale grde, ko poskušate potegniti njihovo delo nazaj v vaše.
Poglejmo primer, kako baziranje dela, ki ste naredili javno, lahko povzroča probleme. Predpostavimo, da klonirate iz centralnega strežnika in nato naredite nekaj dela iz tega. Vaša zgodovina pošiljanja izgleda takole:

Sedaj, ko nekdo drug naredi delo, ki vključuje združitev in potiskanje, ki dela na centralnem strežniku. Ujamete ga in združite novo oddaljeno vejo v vaše delo, naredite, da vaša zgodovina izgleda nekakako takole:

Naslednje, oseba, ki je potisnila združeno delo, se odloči iti nazaj in ponovno bazirati svoje delo namesto tega; naredi git push --force
, da prepiše zgodovino na strežniku.
Nato ujamete iz tega strežnika in prenesete nova pošiljanja.

Sedaj ste oboji v škripcih.
Če naredite git pull
, boste ustvarili pošiljanje združitve, ki vključuje tako vrstico zgodovine in vaš repozitorij bo izgledal takole:

Če poženete git log
, ko vaša zgodovina izgleda takole, boste videli dve pošiljanji, ki imata istega avtorja, datum in sporočilo, kar bo zmedeno.
Nadalje, če potisnete to zgodovino nazaj na strežnik, boste ponovno predstavili vsa ta ponovno bazirana pošiljanja na centralnem strežniku, kar je lahko dalje zmede ljudi.
Je precej varno predpostavljati, da drug razvijalec ne želi C4
in C6
v zgodovini; to je razlog, zakaj sploh ponovno baziranje.
Ponovno bazirajte ko ponovno bazirate
Če se najdete v situaciji, kot je ta, ima Git nekaj dodatne čarobnosti, ki vam lahko pomaga. Če nekdo v vaši ekipi porine spremembe, ki prepišejo delo, na katerem ste osnovali vaše delo, je vaš iziv ugotoviti, kaj je vaše in kaj so drugi prepisali.
Izkaže se, da kot dodatek k pošiljanju preverjene vsote SHA-1, Git tudi preračuna preverjeno vsoto, ki je osnovana samo kot popravek predstavljen v pošiljanju. To se imenuje ``patch-id''.
Če potegnete delo, ki je bilo prepisano in osnovano na vrhu novega pošiljanja vašega partnerja lahko Git tudi pogostokrat uspešno ugotovi, kaj je unikatno vaše in jih uporabite nazaj na vrhu nove veje.
Na primer v prejšnjem scenariju če namesto, da delate združevanje, ko ste na Someone pushes rebased commits, abandoning commits you’ve based your work on, poženemo git rebase teamone/master
, bo Git:
-
Določil, katero delo je unikatno za vašo vejo (C2, C3, C4, C6, C7)
-
Določil, katera niso pošiljanja združevanja (C2, C3, C4)
-
Določil, katera niso bila prepisana v ciljno vejo (samo C2 in C3, saj C4 je isti popravek kot C4')
-
Uporabil ta pošiljanja na vrhu
teamone/master
Torej namesto rezultata, ki ga vidimo v You merge in the same work again into a new merge commit, bi končali z nečim bolj kot Rebase on top of force-pushed rebase work..

To samo deluje, če sta C4 in C4', ki ga je naredil vaš partner skoraj točno enak popravek. Drugače ponovno baziranje ne bo zmožno povedati, da je duplikat in bo dodal drug C4 podoben popravek (ki ga bo verjetno neuspel uporabiti čisto, saj bi spremembe će bile vsaj nekako tam).
To lahko tudi poenostavite s pogonom git pull --rebase
namesto normalnega git pull
. Ali pa bi lahko naredili to ročno z git fetch
, ki mu sledi git rebase teamone/master
v tem primeru.
Če uporabljate git pull
in želite narediti --rebase
privzeto, lahko nastavite pull.rebase
nastavitveno vrednost s nečim kot je git config --global pull.rebase true
.
Če obravnavate ponovno baziranje kot način čiščenja in dela s pošiljanju preden jih potisnete in če samo ponovno bazirate pošiljanja, ki še nikoli niso bila na voljo javno potem boste v redu. Če ponovno bazirate pošiljanja, ki so že bila potisnjena javno in so ljudje lahko bazirali delo na teh pošiljanjih, potem ste lahko v neki frustrirajoči težavi in prezirate vaše člane ekipe.
Če vi ali partner najde to potrebno na neki točki, zagotovite, da vsi znajo pognati git pull --rebase
, da poskusijo narediti problem potem, ko se zgodi, nekoliko bolj enostaven.
Ponovno baziranje proti združevanju
Sedaj, ko ste videli ponovno baziranje in združevanje v delovanju, se lahko sprašujete katero je boljše. Preden lahko to odgovorimo, pojdimo korak nazaj in povejmo o tem, kaj zgodovina pomeni.
Ena točka pogleda na to je, da je zgodovina pošiljanja vašega repozitorija posnetek kaj se je dejansko zgodilo. Je zgodovinski dokument, vreden svojega lastnega prav in ne bi smel biti ponarejen. Iz tega zornega kota spreminjanje zgodovine pošiljanja je skoraj bogolketno; ležite, kaj se je dejansko zgodilo. Torej kaj če je grda serijca pošiljanj združevanja? Tako se je zgodilo in repozitorij bi moral ohraniti to za zaznamce.
Nasprotno stališče je, da je zgodovina pošiljanja zgodba, kako je bil vaš projekt narejen. Ne bi objavili prvega osnutka knjige in navodila, kako vzdrževati programsko opremo, zaslužijo previdno urejanje. To je tabor, ki uporablja orodja, kot je rebase in filter-branch, da povejo zgodbo na način, ki je najboljši za bodoče bralce.
Sedaj vprašanje ali je združevanje ali ponovno baziranje boljše: upajmo, da boste videli, da ni tako enostavno. Git je močno orodje in vam omogoča narediti mnogo stvari in z vašo zgodovino, vendar vsaka ekipa in vsak projekt je drugačen. Sedaj ko veste kako obe stvari delujeta, je odvisno od vas, da se odločite, katera je najboljša za vašo določeno situacijo.
V splošnem način za dobiti najboljše obeh svetov je ponovno baziranje lokalnih sprememb, ki ste jih naredili vendar niste delili preden ste jih potisnili, da počistite vašo zgodbo, vendar nikoli ničesar ponovno bazirali, ste potisnili nekam.