-
1. Začetek
- 1.1 O nadzoru različic
- 1.2 Kratka zgodovina Gita
- 1.3 Kaj je Git?
- 1.4 Ukazna vrstica
- 1.5 Namestitev Gita
- 1.6 Prva nastavitev 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 Aliasi Git
- 2.8 Povzetek
-
3. Veje Git
- 3.1 Veje na kratko
- 3.2 Osnove vej in združevanja
- 3.3 Upravljanje vej
- 3.4 Poteki dela z vejami
- 3.5 Oddaljene veje
- 3.6 Ponovno baziranje
- 3.7 Povzetek
-
4. Git na strežniku
- 4.1 Protokoli
- 4.2 Pridobitev Gita na strežniku
- 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 Možnosti gostovanja pri tretjih ponudnikih
- 4.10 Povzetek
-
5. Porazdeljeni Git
- 5.1 Porazdeljeni poteki dela
- 5.2 Prispevek k projektu
- 5.3 Vzdrževanje projekta
- 5.4 Povzetek
-
6. GitHub
-
7. Orodja Git
- 7.1 Izbira revizije
- 7.2 Interaktivno pripravljanje
- 7.3 Shranjevanje na varno (angl. stashing) in čiščenje
- 7.4 Podpisovanje vašega dela
- 7.5 Iskanje
- 7.6 Prepisovanje zgodovine
- 7.7 Demistifikacija ponastavitve
- 7.8 Napredno združevanje
- 7.9 Rerere
- 7.10 Razhroščevanje z Gitom
- 7.11 Podmoduli
- 7.12 Povezovanje v pakete
- 7.13 Zamenjava
- 7.14 Shramba poverilnic
- 7.15 Povzetek
-
8. Prilagoditev Gita
- 8.1 Konfiguracija Git
- 8.2 Atributi Git
- 8.3 Kljuke Git
- 8.4 Primer pravilnika, ki ga uveljavlja Git
- 8.5 Povzetek
-
9. Git in ostali sistemi
- 9.1 Git kot odjemalec
- 9.2 Migracija na Git
- 9.3 Povzetek
-
10. Notranjost Gita
- 10.1 Napeljava in keramika
- 10.2 Objekti Git
- 10.3 Reference Git
- 10.4 Packfiles (datoteke zmanjšanih podatkov)
- 10.5 Refspec
- 10.6 Protokoli prenosa
- 10.7 Vzdrževanje in obnovitev podatkov
- 10.8 Spremenljivke okolja
- 10.9 Povzetek
-
A1. Dodatek A: Git v drugih okoljih
- A1.1 Grafični vmesniki
- A1.2 Git v 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 sisteme napeljave
7.6 Orodja Git - Prepisovanje zgodovine
Prepisovanje zgodovine
Pri delu z Gitom se pogosto zgodi, da želite spremeniti zgodovino lokalnih potrditev.
Ena od prednosti Gita je, da vam omogoča sprejemanje odločitev v zadnjem trenutku.
Lahko se odločite, katere datoteke gredo v katero potrditev, tik preden jih potrdite s področjem priprave, lahko se odločite, da še ne želite delati na določenem delu z git stash
in prepišete lahko potrditve, ki so se že zgodile, tako da izgledajo, kot da so se zgodile drugače.
To lahko vključuje spreminjanje vrstnega reda potrditev, spreminjanje sporočil ali datotek v potrditvi, stiskanje skupaj ali razcepitev potrditev, ali pa popolno odstranjevanje potrditev — vse to, preden svoje delo delite z drugimi.
V tem razdelku boste videli, kako izvesti te naloge, tako da lahko svojo zgodovino potrditev uredite po želji, preden jo delite z drugimi.
Opomba
|
Ne potisnite svojega dela dokler niste z njim zadovoljni
Ena izmed ključnih pravil Gita je, da imate zaradi tega, ker je veliko dela lokalno v vašem klonu, veliko svobode pri spreminjanju vaše zgodovine lokalno. Vendar pa je to povsem druga zgodba, ko enkrat potisnete svoje delo, in takrat morate objavljeno delo obravnavati kot končno, razen če imate dober razlog za njegovo spreminjanje. Skratka, izogibati se morate potiskanju svojega dela, dokler niste z njim zadovoljni in ga pripravljeni deliti z ostalim svetom. |
Spreminjanje zadnje potrditve
Spreminjanje vaše zadnje potrditve je verjetno najpogostejše prepisovanje zgodovine, ki ga boste naredili. Pogosto boste želeli narediti dve osnovni stvari na svoji zadnji potrditvi: preprosto spremeniti sporočilo potrditve, ali pa spremeniti njeno dejansko vsebino z dodajanjem, odstranjevanjem in spreminjanjem datotek.
Če želite preprosto spremeniti sporočilo zadnje potrditve, je to precej enostavno:
$ git commit --amend
Zgoraj navedeni ukaz naloži sporočilo prejšnje potrditve v sejo urejevalnika, kjer lahko spremenite sporočilo, shranite spremembe in izstopite. Ko shranite in zaprete urejevalnik, se ustvari nova potrditev s posodobljenim sporočilom in postane vaša nova zadnja potrditev.
Če pa želite spremeniti dejansko vsebino zadnje potrditve, postopek deluje na enak način — najprej naredite spremembe, ki ste jih pozabili, shranite te spremembe in nato z uporabo ukaza git commit --amend
zamenjate zadnjo potrditev z vašo novo in izboljšano potrditvijo.
Pri tej tehniki morate biti previdni, saj spremeni vrednost SHA-1 potrditve. Gre za zelo majhno ponovno baziranje — ne spreminjajte zadnje potrditve, če ste jo že potisnili.
Namig
|
Spremenjena potrditev lahko (ali pa ne) potrebuje spremenjeno sporočilo potrditve
Ko popravljate potrditev, imate možnost spremeniti tako sporočilo potrditve kot tudi njeno vsebino. Če bistveno spremenite vsebino potrditve, bi morali skoraj zagotovo posodobiti njeno sporočilo, da odraža to spremenjeno vsebino. Po drugi strani če so vaše spremembe ustrezno nepomembne (popravljanje neumne tipkarske napake ali dodajanje datoteke, ki ste jo pozabili dati v področje priprave), tako da je prejšnje sporočilo potrditve v redu, lahko preprosto opravite spremembe, jih postavite v področje priprave in se v celoti izognete nepotrebnemu urejevalniku z:
|
Spreminjanje več sporočil potrditev
Če želite spremeniti potrditev, ki je dlje nazaj v zgodovini, morate uporabiti bolj zapletena orodja.
Git nima orodja za spreminjanje zgodovine, vendar lahko uporabite orodje ponovnega baziranja, da na novo nanesete serijo potrditev na HEAD, na kateri so bile prvotno zasnovane, namesto da jih premikate na drugo glavo.
Z interaktivnim orodjem ponovnega baziranja se lahko nato ustavite po vsaki potrditvi, ki jo želite spremeniti, in spremenite sporočilo, dodate datoteke, ali karkoli drugega želite narediti tam.
Ponovno baziranje lahko poganjate interaktivno tako, da dodate ukazu git rebase
možnost -i
.
Morali boste navesti, kako daleč nazaj želite preoblikovati potrditve, tako da ukazu poveste, na katero potrditev naj se ponovno baziranje izvaja.
Na primer, če želite spremeniti zadnja tri sporočila potrditev, ali katero koli sporočilo v tej skupini, argumentu git rebase -i
podate nadrejeno zadnje potrditve, ki jo želite urediti, kar je HEAD~2^
ali HEAD~3
.
Lahko si zapomnite ~3
, ker poskušate urediti zadnje tri potrditve, vendar imejte v mislih, da dejansko določate štiri potrditve nazaj, nadrejeno zadnje potrditve, ki jo želite urediti:
$ git rebase -i HEAD~3
Ponovno poudarjamo, da gre za ukaz ponovnega baziranja — vsaka potrditev v območju HEAD~3..HEAD
s spremenjenim sporočilom in vsi njeni potomci bodo preoblikovani.
Ne vključite nobene potrditve, ki ste jo že potisnili na osrednji strežnik — to bo druge razvijalce zmedlo z zagotavljanjem alternativne različice iste spremembe.
Zagon tega ukaza vam da seznam potrditev v urejevalniku besedil, ki je videti nekako takole:
pick f7f3f6d Change my name a bit
pick 310154e Update README formatting and add blame
pick a5f4a0d Add cat-file
# Rebase 710f0f8..a5f4a0d onto 710f0f8
#
# Commands:
# p, pick <commit> = use commit
# r, reword <commit> = use commit, but edit the commit message
# e, edit <commit> = use commit, but stop for amending
# s, squash <commit> = use commit, but meld into previous commit
# f, fixup <commit> = like "squash", but discard this commit's log message
# x, exec <command> = run command (the rest of the line) using shell
# b, break = stop here (continue rebase later with 'git rebase --continue')
# d, drop <commit> = remove commit
# l, label <label> = label current HEAD with a name
# t, reset <label> = reset HEAD to a label
# m, merge [-C <commit> | -c <commit>] <label> [# <oneline>]
# . create a merge commit using the original merge commit's
# . message (or the oneline, if no original merge commit was
# . specified). Use -c <commit> to reword the commit message.
#
# These lines can be re-ordered; they are executed from top to bottom.
#
# If you remove a line here THAT COMMIT WILL BE LOST.
#
# However, if you remove everything, the rebase will be aborted.
#
# Note that empty commits are commented out
Pomembno je opozoriti, da so te potrditve navedene v obratnem vrstnem redu, kot jih običajno vidite z uporabo ukaza log
.
Če zaženete log
, boste videli nekaj takega:
$ git log --pretty=format:"%h %s" HEAD~3..HEAD
a5f4a0d Add cat-file
310154e Update README formatting and add blame
f7f3f6d Change my name a bit
Opazite obratni vrstni red.
Interaktivno ponovno baziranje vam da skript, ki ga bo izvedel.
Začelo se bo pri potrditvi, ki jo določite v ukazni vrstici (HEAD~3
) in bo od vrha navzdol ponovilo spremembe, uvedene v vsaki od teh potrditev.
Najstarejšo potrditev na seznamu postavi na vrh, namesto najnovejše, ker jo bo najprej ponovilo.
Skript morate urediti, da se ustavi pri potrditvi, ki jo želite urediti.
Da bi to naredili, spremenite besedo pick
v besedo edit
za vsako potrditev, za katero želite, da se skript ustavi po njej.
Na primer, če želite spremeniti samo sporočilo tretje potrditve, spremenite datoteko, da je videti tako:
edit f7f3f6d Change my name a bit
pick 310154e Update README formatting and add blame
pick a5f4a0d Add cat-file
Ko shranite in zapustite urejevalnik, vas Git previje nazaj na zadnjo potrditev na seznamu in vas postavi v ukazno vrstico z naslednjim sporočilom:
$ git rebase -i HEAD~3
Stopped at f7f3f6d... Change my name a bit
You can amend the commit now, with
git commit --amend
Once you're satisfied with your changes, run
git rebase --continue
Ta navodila vam povedo točno, kar morate narediti. Vpišite:
$ git commit --amend
Spremenite sporočilo potrditve in zapustite urejevalnik. Nato poženite:
$ git rebase --continue
Ta ukaz bo samodejno uporabil drugi dve potrditvi in potem ste končali.
Če na več vrsticah spremenite pick
v edit
, lahko za vsako potrditev, ki jo spremenite v edit
, ponovite te korake.
Vsakič se bo Git ustavil, vam dovolil popraviti potrditev in nadaljeval, ko končate.
Preurejanje potrditev
Interaktivna ponovna baziranja lahko uporabite tudi za preureditev ali popolno odstranitev potrditev. Če želite odstraniti potrditev »Add cat-file« in spremeniti vrstni red, v katerem sta uvedeni drugi dve potrditvi, lahko spremenite skript ponovnega baziranja iz tega:
pick f7f3f6d Change my name a bit
pick 310154e Update README formatting and add blame
pick a5f4a0d Add cat-file
na to:
pick 310154e Update README formatting and add blame
pick f7f3f6d Change my name a bit
Ko shranite in zaprete urejevalnik, Git previje vašo vejo nazaj na nadrejeno teh potrditev, uporabi 310154e
in nato f7f3f6d
ter se nato ustavi.
Učinkovito ste spremenili vrstni red teh potrditev in popolnoma odstranili potrditev »Add cat-file«.
Stiskanje potrditev skupaj
Z interaktivnim orodjem ponovnega baziranja je možno združiti tudi serijo potrditev v eno samo potrditev. Skript v sporočilu ponovnega baziranja vključuje uporabna navodila:
#
# Commands:
# p, pick <commit> = use commit
# r, reword <commit> = use commit, but edit the commit message
# e, edit <commit> = use commit, but stop for amending
# s, squash <commit> = use commit, but meld into previous commit
# f, fixup <commit> = like "squash", but discard this commit's log message
# x, exec <command> = run command (the rest of the line) using shell
# b, break = stop here (continue rebase later with 'git rebase --continue')
# d, drop <commit> = remove commit
# l, label <label> = label current HEAD with a name
# t, reset <label> = reset HEAD to a label
# m, merge [-C <commit> | -c <commit>] <label> [# <oneline>]
# . create a merge commit using the original merge commit's
# . message (or the oneline, if no original merge commit was
# . specified). Use -c <commit> to reword the commit message.
#
# These lines can be re-ordered; they are executed from top to bottom.
#
# If you remove a line here THAT COMMIT WILL BE LOST.
#
# However, if you remove everything, the rebase will be aborted.
#
# Note that empty commits are commented out
Če namesto pick
ali edit
navedete squash
, Git uporabi tako spremembo kot tudi spremembo neposredno pred njo in vas prosi, da združite sporočila potrditev.
Če želite na primer ustvariti eno samo potrditev iz teh treh potrditev, lahko skript oblikujete na ta način:
pick f7f3f6d Change my name a bit
squash 310154e Update README formatting and add blame
squash a5f4a0d Add cat-file
Ko shranite in zapustite urejevalnik, bo Git uporabil vse tri spremembe in vas nato vrnil nazaj v urejevalnik, da združite tri sporočila potrditev.
# This is a combination of 3 commits.
# The first commit's message is:
Change my name a bit
# This is the 2nd commit message:
Update README formatting and add blame
# This is the 3rd commit message:
Add cat-file
Ko to shranite, boste imeli eno potrditev, ki vsebuje spremembe vseh treh prejšnjih potrditev.
Razdelitev potrditve
Razdelitev (angl. splitting) potrditve razveljavi potrditev in jo delno doda v področje priprave ter nato potrdi tolikokrat s kolikor potrditev želite končati.
Na primer, če želite razdeliti srednjo potrditev iz svojih treh potrditev.
Namesto »Update README formatting and add blame« jo želite razdeliti na dve potrditvi: »Update README formatting« za prvo in »Add blame« za drugo.
To lahko storite v skriptu rebase -i
, tako da spremenite navodila na potrditvi, ki jo želite razdeliti, na edit
:
pick f7f3f6d Change my name a bit
edit 310154e Update README formatting and add blame
pick a5f4a0d Add cat-file
Nato, ko vas skript spusti v ukazno vrstico, ponastavite to potrditev, vzamete spremembe, ki so bile ponastavljene, in iz njih ustvarite več potrditev.
Ko shranite in zaprete urejevalnik, se Git premakne nazaj na nadrejeno prve potrditve na vašem seznamu, uporabi prvo potrditev (f7f3f6d
), uporabi drugo (310154e
) in vas spusti v konzolo.
Tam lahko naredite mešano ponastavitev te potrditve z git reset HEAD^
, ki učinkovito razveljavi to potrditev in pusti spremenjene datoteke izven področja priprave.
Sedaj lahko označite in potrdite datoteke, dokler ne dobite več potrditev, in ko končate, zaženete git rebase --continue
:
$ git reset HEAD^
$ git add README
$ git commit -m 'Update README formatting'
$ git add lib/simplegit.rb
$ git commit -m 'Add blame'
$ git rebase --continue
Git uporabi zadnjo potrditev v skriptu (a5f4a0d
) in vaša zgodovina je videti takole:
$ git log -4 --pretty=format:"%h %s"
1c002dd Add cat-file
9b29157 Add blame
35cfb2b Update README formatting
f7f3f6d Change my name a bit
To spremeni SHA-1 treh najnovejših potrditev na vašem seznamu, zato poskrbite, da nobena spremenjena potrditev, ki se pojavi na tem seznamu, že ni bila potisnjena v skupno rabo.
Opazite, da je zadnja potrditev na seznamu (f7f3f6d
) nespremenjena.
Kljub temu, da je ta potrditev prikazana v skriptu, ker je bila označena kot pick
in je bila uporabljena pred vsemi spremembami ponovnega baziranja, Git pusti potrditev nespremenjeno.
Brisanje potrditve
Če želite odstraniti potrditev, jo lahko izbrišete s pomočjo skripta rebase -i
.
Na seznamu potrditev pred tisto, ki jo želite izbrisati, vnesite besedo drop
(ali pa samo izbrišite to vrstico iz skripta za ponovno baziranje):
pick 461cb2a This commit is OK
drop 5aecc10 This commit is broken
Zaradi načina, kako Git gradi objekte potrditev, bo brisanje ali spreminjanje potrditve povzročilo ponovno pisanje vseh potrditev, ki sledijo. Bolj, ko se pomikate nazaj v zgodovino svojega repozitorija, več potrditev bo treba ustvariti. Če imate v zaporedju veliko potrditev, ki so odvisne od tiste, ki ste jo pravkar izbrisali, lahko to povzroči veliko konfliktov med združevanjem.
Če se nekje na sredini ponovnega baziranja odločite, da to ni dobra ideja, se lahko vedno ustavite.
Vpišite git rebase --abort
in vaš repozitorij se bo povrnil v stanje, v katerem je bil pred začetkom ponovnega baziranja.
Če končate ponovno baziranje in se odločite, da to ni to, kar želite, lahko uporabite git reflog
, da obnovite prejšnjo različico svoje veje.
Glejte razdelek Obnovitev podatkov za več informacij o ukazu reflog
.
Opomba
|
Drew DeVault je pripravil praktični vodnik z vajami, ki vam pomaga se naučiti uporabljati |
Jedrska možnost: filter-branch
Obstaja še ena možnost spreminjanja zgodovine, ki jo lahko uporabite, če morate na neki skriptni način spremeniti večje število potrditev — na primer globalno spremeniti svoj e-poštni naslov ali odstraniti datoteko iz vsake potrditve.
Ukaz je filter-branch
in lahko ponovno napiše ogromne dele vaše zgodovine, zato ga verjetno ne bi smeli uporabljati, razen če vaš projekt še ni javen in drugi ljudje še niso temeljili na delu, ki ste ga ravno nameravali spremeniti.
Vendar pa je lahko zelo uporaben.
Naučili se boste nekaj običajnih uporab, da boste dobili predstavo o nekaterih stvareh, ki jih lahko naredi.
Pozor
|
|
Odstranjevanje datoteke iz vsake potrditve
To se zgodi pogostokrat.
Nekdo naključno doda veliko binarno datoteko z nepremišljenim git add .
in želite jo odstraniti povsod.
Morda ste nenamerno dali v repozitorij datoteko, ki vsebuje geslo, in želite svoj projekt narediti odprtokodni.
filter-branch
je orodje, ki ga verjetno želite uporabiti, da očistite celotno zgodovino.
Če želite iz celotne zgodovine odstraniti datoteko z imenom passwords.txt
, lahko uporabite možnost --tree-filter
v filter-branch
:
$ git filter-branch --tree-filter 'rm -f passwords.txt' HEAD
Rewrite 6b9b3cf04e7c5686a9cb838c3f36a8cb6a0fc2bd (21/21)
Ref 'refs/heads/master' was rewritten
Možnost --tree-filter
po vsakem izvleku projekta izvede navedeni ukaz in nato ponovno potrdi rezultate.
V tem primeru odstranite datoteko passwords.txt
iz vsakega posnetka, ne glede na to, ali obstaja ali ne.
Če želite odstraniti vse naključno dodane datoteke varnostnih kopij urejevalnika, lahko zaženete nekaj takega kot git filter-branch --tree-filter 'rm -f *~' HEAD
.
Lahko spremljate Git, ko ponovno piše drevesa in potrditve, nato pa premaknete kazalnik veje na konec.
Na splošno je dobra ideja to storiti v testni veji in nato trdo ponastaviti vašo vejo master
, ko ugotovite, da je rezultat tisto, kar resnično želite.
Če želite zagnati filter-branch
na vseh vejah, lahko ukazu podate --all
.
Izdelava podimenika v novi koren
Recimo, da ste uvozili projekt iz drugega sistema za nadzor nad izvorno kodo in imate poddirektorije, ki nimajo smisla (trunk
, tags
itd.).
Če želite narediti poddirektorij trunk
za nov koren projekta za vsako potrditev, vam lahko filter-branch
pomaga tudi pri tem:
$ git filter-branch --subdirectory-filter trunk HEAD
Rewrite 856f0bf61e41a27326cdae8f09fe708d679f596f (12/12)
Ref 'refs/heads/master' was rewritten
Zdaj je vaš novi projekt osnovna mapa, ki je bila vsakič v podmapi trunk
.
Git bo samodejno odstranil tudi potrditve, ki niso vplivale na podmapo.
Globalno spreminjanje e-poštnih naslovov
Še en pogost primer je, da ste pozabili zagnati git config
, da bi nastavili vaše ime in e-poštni naslov, preden ste začeli delati, ali pa morda želite objaviti projekt na delovnem mestu in spremeniti vse delovne e-poštne naslove v svoj osebni naslov.
V vsakem primeru lahko s filter-branch
spremenite e-poštne naslove v več potrditvah naenkrat.
Paziti morate, da spremenite samo tiste e-poštne naslove, ki so vaši, zato uporabite --commit-filter
:
$ git filter-branch --commit-filter '
if [ "$GIT_AUTHOR_EMAIL" = "schacon@localhost" ];
then
GIT_AUTHOR_NAME="Scott Chacon";
GIT_AUTHOR_EMAIL="schacon@example.com";
git commit-tree "$@";
else
git commit-tree "$@";
fi' HEAD
To gre skozi in prepiše vsako potrditev z vašim novim naslovom. Ker potrditve vsebujejo vrednosti SHA-1 njihovih nadrejenih, ta ukaz spremeni vrednosti SHA-1 vsake potrditve v vaši zgodovini, ne samo tistih, ki imajo prilegajoči se naslov e-pošte.