-
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.13 Orodja Git - Zamenjava
Zamenjava
Kot smo poudarili že prej, objekti v objektni podatkovni bazi Git niso spremenljivi, vendar Git ponuja zanimiv način pretvarjanja zamenjave objektov v svoji podatkovni bazi z drugimi objekti.
Ukaz replace
vam omogoča določiti objekt v Gitu in povedati »vsakič, ko se sklicuješ na ta objekt, se pretvarjaj, da je drugačen objekt«.
To je najpogostejše uporabno za zamenjavo ene potrditve v vaši zgodovini z drugo, brez da morate ponovno zgraditi celo zgodovino z recimo git filter-branch
.
Na primer, predpostavimo, da imate veliko zgodovino kode in želite razdeliti svoj repozitorij v eno hitro zgodovino za nove razvijalce in eno veliko daljšo in večjo zgodovino za ljudi, ki jih zanima rudarjenje podatkov. Presadite lahko eno zgodovino v drugo z zamenjavo najnovejše potrditve v novi vrstici z najnovejšo potrditvijo na stari. To je dobro, ker pomeni, da vam ni treba dejansko prepisati vsake potrditve v novi zgodovini, kot bi običajno morali, da ju združite skupaj (ker nadrejenost vpliva na SHA-1).
Poskusimo to.
Vzemimo obstoječi repozitorij, ga razdelimo v dva repozitorija, enega novejšega in enega zgodovinskega, ter nato bomo videli, kako lahko ponovno kombiniramo oba brez sprememb zadnjih vrednosti SHA-1 repozitorija preko replace
.
Uporabili bomo enostaven repozitorij s petimi enostavnimi potrditvami:
$ git log --oneline
ef989d8 Fifth commit
c6e1e95 Fourth commit
9c68fdc Third commit
945704c Second commit
c1822cf First commit
To želimo prelomiti v dve liniji zgodovine. Ena linija gre iz prve potrditve v četrto potrditev — ta bo zgodovinska. Druga linija bo vsebovala samo potrditvi štiri in pet — to bo novejša zgodovina.
Torej, ustvarjanje zgodovinske zgodovine je enostavno, lahko damo zgolj vejo v zgodovino in nato potisnemo to vejo v vejo master
novega oddaljenega repozitorija.
$ git branch history c6e1e95
$ git log --oneline --decorate
ef989d8 (HEAD, master) Fifth commit
c6e1e95 (history) Fourth commit
9c68fdc Third commit
945704c Second commit
c1822cf First commit
history
Sedaj lahko potisnemo novo vejo history
v vejo master
našega novega repozitorija:
$ git remote add project-history https://github.com/schacon/project-history
$ git push project-history history:master
Counting objects: 12, done.
Delta compression using up to 2 threads.
Compressing objects: 100% (4/4), done.
Writing objects: 100% (12/12), 907 bytes, done.
Total 12 (delta 0), reused 0 (delta 0)
Unpacking objects: 100% (12/12), done.
To git@github.com:schacon/project-history.git
* [new branch] history -> master
Dobro, sedaj je torej naša zgodovina objavljena. Sedaj je težji del skrajšanje naše novejše zgodovine navzdol, da je manjša. Narediti moramo prekrivanje, da lahko zamenjamo potrditev v eni enakovredni potrditvi v drugo, torej bomo skrajšali to na samo potrditvi štiri in pet (torej se potrditev štiri prekrije).
$ git log --oneline --decorate
ef989d8 (HEAD, master) Fifth commit
c6e1e95 (history) Fourth commit
9c68fdc Third commit
945704c Second commit
c1822cf First commit
V tem primeru je uporabno ustvariti osnovno potrditev, da ima navodila, kako razširiti zgodovino, tako da drugi razvijalci vejo, kaj narediti, če pridejo do prve potrditve v skrajšani zgodovini in morajo imeti več. Torej, kar bomo naredili, je ustvarjanje začetnega objekta potrditve kot naše osnovne točke z navodili, nato pa bomo ponovno bazirali ostali potrditvi (štiri in pet) na vrhu le te.
Da to naredimo, moramo izbrati točko za razdelitev, ki bo za nas tretja potrditev, ki je 9c68fdc
v jeziku SHA.
Torej naša osnovna potrditev bo osnovana na tem drevesu.
Ustvarimo lahko našo osnovno potrditev z uporabo ukaza commit-tree
, ki samo vzame drevo in nam vrne popolnoma nov objekt potrditve SHA-1 brez nadrejene.
$ echo 'Get history from blah blah blah' | git commit-tree 9c68fdc^{tree}
622e88e9cbfbacfb75b5279245b9fb38dfea10cf
Opomba
|
Ukaz |
commit-tree
Torej sedaj, ko imamo osnovno potrditev, lahko naredimo ponovno baziranje na naši preostali zgodovini na vrhu tega z git rebase --onto
.
Argument --onto
bo SHA-1, ki smo ga ravno dobili iz commit-tree
, in točka ponovnega baziranja bo tretja potrditev (nadrejena prve potrditve, ki jo želimo obdržati, 9c68fdc
):
$ git rebase --onto 622e88 9c68fdc
First, rewinding head to replay your work on top of it...
Applying: fourth commit
Applying: fifth commit
Torej sedaj smo prepisali svojo novejšo zgodovino na vrhu ovržene osnovne potrditve, ki ima sedaj v njej navodila, kako rekonstruirati celotno zgodovino, če to želimo. Potisnemo lahko to novo zgodovino v nov projekt in sedaj, ko bodo ljudje klonirali ta repozitorij, bodo videli samo zadnji dve potrditvi in nato osnovno potrditev z navodili.
Sedaj preklopimo vloge nekomu, ki prvič klonira projekt, in želi celotno zgodovino. Da dobimo podatke zgodovine po kloniranju tega skrajšanega repozitorija, bi nekdo moral dodati drugo daljavo za zgodovinski repozitorij in jo prenesti:
$ git clone https://github.com/schacon/project
$ cd project
$ git log --oneline master
e146b5f Fifth commit
81a708d Fourth commit
622e88e Get history from blah blah blah
$ git remote add project-history https://github.com/schacon/project-history
$ git fetch project-history
From https://github.com/schacon/project-history
* [new branch] master -> project-history/master
Sedaj bi sodelavec moral imeti svoje zadnje potrditve v veji master
in zgodovinske potrditve v veji project-history/master
.
$ git log --oneline master
e146b5f Fifth commit
81a708d Fourth commit
622e88e Get history from blah blah blah
$ git log --oneline project-history/master
c6e1e95 Fourth commit
9c68fdc Third commit
945704c Second commit
c1822cf First commit
Da jih kombinirate, lahko enostavno pokličete git replace
s potrditvijo, ki jo želite zamenjati, in nato dodate potrditev, ki jo želite z njo zamenjati.
Torej želimo zamenjati četrto potrditev v veji master
s četrto potrditvijo v veji project-history/master
:
$ git replace 81a708d c6e1e95
Če sedaj pogledate zgodovino veje master
, je videti nekako takole:
$ git log --oneline master
e146b5f Fifth commit
81a708d Fourth commit
9c68fdc Third commit
945704c Second commit
c1822cf First commit
Odlično, kajne? Brez da moramo spremeniti vse SHA-1 povratnega toka, smo lahko zamenjali eno potrditev v naši zgodovini s popolnoma drugo potrditvijo in vsa običajna orodja (bisect
, blame
itd) bodo delovala, kakor pričakujemo.
git replace
Zanimivo je, da še vedno kaže 81a708d
kot SHA-1, čeprav dejansko uporablja podatke potrditve c6e1e95
, s katero smo jo zamenjali.
Tudi če poženete ukaz, kot je cat-file
, vam bo pokazal zamenjane podatke:
$ git cat-file -p 81a708d
tree 7bc544cf438903b65ca9104a1e30345eee6c083d
parent 9c68fdceee073230f19ebb8b5e7fc71b479c0252
author Scott Chacon <schacon@gmail.com> 1268712581 -0700
committer Scott Chacon <schacon@gmail.com> 1268712581 -0700
fourth commit
Zapomniti si je dobro, da je bila dejansko nadrejena 81a708d
označba mesta potrditve (622e88e
) in ne 9c68fdce
, kakor je tu zabeleženo.
Druga zanimiva stvar je, da so ti podatki vključeni v naših referencah:
$ git for-each-ref
e146b5f14e79d4935160c0e83fb9ebe526b8da0d commit refs/heads/master
c6e1e95051d41771a649f3145423f8809d1a74d4 commit refs/remotes/history/master
e146b5f14e79d4935160c0e83fb9ebe526b8da0d commit refs/remotes/origin/HEAD
e146b5f14e79d4935160c0e83fb9ebe526b8da0d commit refs/remotes/origin/master
c6e1e95051d41771a649f3145423f8809d1a74d4 commit refs/replace/81a708dd0e167a3f691541c7a6463343bc457040
To pomeni, da je našo zamenjavo enostavno deliti z drugimi, ker lahko potisnemo to na svoj strežnik in drugi ljudje lahko to enostavno prenesejo. To ni toliko koristno v primeru presajanja zgodovine, kot smo šli skozi tu (ker bi vsak prenesel obe zgodovini tako ali tako, torej zakaj ju sploh ločevati?), vendar je lahko uporabno v drugih okoliščinah.