Vesolje DVCS (porazdeljenega nadzora nad različicami) je večje od samega Gita. Dejansko obstaja veliko drugih sistemov na tem področju, vsak s svojim pristopom, kako pravilno izvajati porazdeljeni nadzor različic. Poleg Gita je najbolj priljubljen Mercurial, oba pa sta si v mnogih pogledih zelo podobna.
Dobra novica, če vam je vedenje odjemalca Gita ljubše, vendar delate na projektu, kjer je koda shranjena v sistemu Mercurial, je, da obstaja način uporabe Gita kot odjemalca za Mercurialov repozitorij. Ker Git na strežniku uporablja daljave, ni presenetljivo, da je ta mostovna povezava implementirana kot pomožni program za daljave. Projekt se imenuje git-remote-hg in najdete ga na spletnem naslovu https://github.com/felipec/git-remote-hg.
Najprej morate namestiti git-remote-hg. To v bistvu vključuje odlaganje njegove datoteke nekam v vašo pot, takole:
$ curl -o ~/bin/git-remote-hg \
https://raw.githubusercontent.com/felipec/git-remote-hg/master/git-remote-hg
$ chmod +x ~/bin/git-remote-hg
… če je ~/bin
v vaši $PATH
.
Git-remote-hg ima še eno odvisnost: knjižnico mercurial
za Python.
Če imate Python nameščen, je to zelo preprosto:
$ pip install mercurial
Če nimate nameščenega Pythona, obiščite https://www.python.org/ in ga najprej namestite.
Zadnja stvar, ki jo boste potrebovali, je odjemalec Mercurial. Če ga še niste namestili, obiščite https://www.mercurial-scm.org/ in ga namestite.
Zdaj ste pripravljeni za uporabo. Potrebujete samo repozitorij Mercurial, kamor lahko potiskate. Na srečo lahko vsak repozitorij Mercurial deluje na ta način, zato bomo uporabili repozitorij »hello world«, ki ga vsi uporabljajo za učenje Mercuriala:
$ hg clone http://selenic.com/repo/hello /tmp/hello
Zdaj, ko imamo ustrezen repozitorij »strežniške strani«, lahko opravimo običajen potek dela. Kot boste videli, sta ta dva sistema dovolj podobna, da ni veliko trenja.
Kot vedno pri Gitu, najprej kloniramo:
$ git clone hg::/tmp/hello /tmp/hello-git
$ cd /tmp/hello-git
$ git log --oneline --graph --decorate
* ac7955c (HEAD, origin/master, origin/branches/default, origin/HEAD, refs/hg/origin/branches/default, refs/hg/origin/bookmarks/master, master) Create a makefile
* 65bb417 Create a standard 'hello, world' program
Opazili boste, da delo z Mercurialovim repozitorijem uporablja standardni ukaz git clone
.
To je zato, ker git-remote-hg deluje na precej nizki ravni in uporablja podoben mehanizem, kot je implementacija Gitovega protokola HTTP/S (oddaljeni pomočniki).
Ker sta Git in Mercurial zasnovana tako, da ima vsak odjemalec polno kopijo zgodovine repozitorija, ta ukaz naredi celotno kopijo, vključno z vso zgodovino projekta, in to relativno hitro.
Ukaz log
prikaže dve spremembi, najnovejša od teh je označena z velikim številom referenc.
Izkazalo se je, da nekatere od teh referenc dejansko ne obstajajo.
Poglejmo, kaj je dejansko v direktoriju .git
:
$ tree .git/refs
.git/refs
├── heads
│ └── master
├── hg
│ └── origin
│ ├── bookmarks
│ │ └── master
│ └── branches
│ └── default
├── notes
│ └── hg
├── remotes
│ └── origin
│ └── HEAD
└── tags
9 directories, 5 files
Git-remote-hg skuša stvari narediti bolj v slogu, ki je bolj podoben Gitu, toda v ozadju upravlja osnovno preslikavo med dvema nekoliko drugačnima sistemoma.
Mapiranje med oddaljenimi referencami dejansko poteka v mapi refs/hg
.
Na primer, datoteka z referenco Git refs/hg/origin/branches/default
vsebuje SHA-1, ki se začne z »ac7955c«, to pa je tista potrditev, na katero kaže master
.
Tako je mapa refs/hg
nekako lažna različica refs/remotes/origin
, vendar ima dodatno razlikovanje med zaznamki in vejami.
Datoteka notes/hg
je izhodišče za preslikavo med Gitovimi zgoščenimi vrednostmi potrditev in ID-ji sprememb Mercuriala, ki jih uporablja git-remote-hg.
Poglejmo si to nekoliko podrobneje:
$ cat notes/hg
d4c10386...
$ git cat-file -p d4c10386...
tree 1781c96...
author remote-hg <> 1408066400 -0800
committer remote-hg <> 1408066400 -0800
Notes for master
$ git ls-tree 1781c96...
100644 blob ac9117f... 65bb417...
100644 blob 485e178... ac7955c...
$ git cat-file -p ac9117f
0a04b987be5ae354b710cefeba0e2d9de7ad41a9
Torej refs/notes/hg
kaže na drevo, ki je v Gitovi objektni bazi podatkov seznam drugih objektov z imeni.
git ls-tree
izpiše način, vrsto, zgoščeno vrednost objekta in ime datoteke za elemente znotraj drevesa.
Ko se potopimo v enega od elementov drevesa, odkrijemo, da je znotraj njega objekt z imenom ac9117f
(zgoščena vrednost SHA-1 potrditve, na katero kaže master
), z vsebino 0a04b98
(to je ID nabora sprememb Mercurial na vrhu veje default
).
Dobra novica je, da se nam s tem večinoma ni treba ukvarjati. Tipičen potek dela ne bo preveč drugačen od dela z oddaljenim repozitorijem Git.
Preden nadaljujemo, moramo rešiti še eno stvar: ignoriranje datotek.
Mercurial in Git uporabljata za to zelo podoben mehanizem, vendar verjetno ne želite dejansko shraniti datoteke .gitignore
v repozitorij Mercurial.
Na srečo ima Git način za ignoriranje datotek, ki je lokalno za posamezen diskovni repozitorij, in format Mercuriala je združljiv z Gitom, zato ga le prekopirajte:
$ cp .hgignore .git/info/exclude
Datoteka .git/info/exclude
se obnaša enako kot .gitignore
, vendar v potrditvah ni vključena.
Naj predpostavimo, da smo opravili nekaj dela in naredili nekaj potrditev na veji master
ter ste pripravljeni, da jih pošljete na oddaljeni repozitorij.
Tako je videti naš repozitorij trenutno:
$ git log --oneline --graph --decorate
* ba04a2a (HEAD, master) Update makefile
* d25d16f Goodbye
* ac7955c (origin/master, origin/branches/default, origin/HEAD, refs/hg/origin/branches/default, refs/hg/origin/bookmarks/master) Create a makefile
* 65bb417 Create a standard 'hello, world' program
Naša veja master
je dva predhodnika pred origin/master
, toda ti dve potrditvi obstajata le na našem lokalnem računalniku.
Poglejmo, ali je kdo drug v istem času opravljal kakšno pomembno delo:
$ git fetch
From hg::/tmp/hello
ac7955c..df85e87 master -> origin/master
ac7955c..df85e87 branches/default -> origin/branches/default
$ git log --oneline --graph --decorate --all
* 7b07969 (refs/notes/hg) Notes for default
* d4c1038 Notes for master
* df85e87 (origin/master, origin/branches/default, origin/HEAD, refs/hg/origin/branches/default, refs/hg/origin/bookmarks/master) Add some documentation
| * ba04a2a (HEAD, master) Update makefile
| * d25d16f Goodbye
|/
* ac7955c Create a makefile
* 65bb417 Create a standard 'hello, world' program
Ker smo uporabili zastavico --all
, vidimo tudi reference »notes«, ki jih uporablja git-remote-hg, vendar jih lahko ignoriramo.
Preostalo je tako, kot smo pričakovali; origin/master
se je premaknil za eno potrditev in naša zgodovina se je zdaj razcepila.
V primerjavi z drugimi sistemi, s katerimi delamo v tem poglavju, lahko Mercurial upravlja združevanja, zato ne bomo počeli ničesar zapletenega.
$ git merge origin/master
Auto-merging hello.c
Merge made by the 'recursive' strategy.
hello.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
$ git log --oneline --graph --decorate
* 0c64627 (HEAD, master) Merge remote-tracking branch 'origin/master'
|\
| * df85e87 (origin/master, origin/branches/default, origin/HEAD, refs/hg/origin/branches/default, refs/hg/origin/bookmarks/master) Add some documentation
* | ba04a2a Update makefile
* | d25d16f Goodbye
|/
* ac7955c Create a makefile
* 65bb417 Create a standard 'hello, world' program
Odlično. Zaženemo teste in vse poteka brez napak, zato smo pripravljeni deliti svoje delo z ostalimi člani ekipe:
$ git push
To hg::/tmp/hello
df85e87..0c64627 master -> master
To je vse! Če si ogledamo repozitorij Mercurial, vidimo, da je ta ukaz storil, kar smo pričakovali:
$ hg log -G --style compact
o 5[tip]:4,2 dc8fa4f932b8 2014-08-14 19:33 -0700 ben
|\ Merge remote-tracking branch 'origin/master'
| |
| o 4 64f27bcefc35 2014-08-14 19:27 -0700 ben
| | Update makefile
| |
| o 3:1 4256fc29598f 2014-08-14 19:27 -0700 ben
| | Goodbye
| |
@ | 2 7db0b4848b3c 2014-08-14 19:30 -0700 ben
|/ Add some documentation
|
o 1 82e55d328c8c 2005-08-26 01:21 -0700 mpm
| Create a makefile
|
o 0 0a04b987be5a 2005-08-26 01:20 -0700 mpm
Create a standard 'hello, world' program
Spremenitve z oznako 2 so bile narejene z Mercurialom, spremembe z oznakami 3 in 4 pa so bile narejene z git-remote-hg, s pomočjo potiskanja potrditev, narejenih z Gitom.
Git ima samo eno vrsto veje: referenco, ki se premika, ko so narejene potrditve. V Mercurialu se ta vrsta reference imenuje »zaznamek« (angl. bookmark) in se obnaša podobno kot Gitova veja.
Mercurialova zasnova »veje« je bolj obremenjujoča.
Veja, na kateri je bil narejen nabor sprememb, je zabeležena z naborom sprememb, kar pomeni, da bo vedno v zgodovini repozitorija.
Tu je primer za potrditev, ki je bila izvedena na veji develop
:
$ hg log -l 1
changeset: 6:8f65e5e02793
branch: develop
tag: tip
user: Ben Straub <[email protected]>
date: Thu Aug 14 20:06:38 2014 -0700
summary: More documentation
Poglejte vrstico, ki se začne z »branch«. Git tega ne more dejansko ponoviti (in tudi ne potrebuje; oba tipa vej lahko predstavimo kot Git ref), vendar mora git-remote-hg razumeti razliko, saj Mercurial skrbi za to.
Ustvarjanje zaznamkov Mercurial je enostavno, kot ustvarjanje vej Git. Na strani Git:
$ git checkout -b featureA
Switched to a new branch 'featureA'
$ git push origin featureA
To hg::/tmp/hello
* [new branch] featureA -> featureA
To je vse, kar spada sem. Na strani Mercurial je videti takole:
$ hg bookmarks
featureA 5:bd5ac26f11f9
$ hg log --style compact -G
@ 6[tip] 8f65e5e02793 2014-08-14 20:06 -0700 ben
| More documentation
|
o 5[featureA]:4,2 bd5ac26f11f9 2014-08-14 20:02 -0700 ben
|\ Merge remote-tracking branch 'origin/master'
| |
| o 4 0434aaa6b91f 2014-08-14 20:01 -0700 ben
| | update makefile
| |
| o 3:1 318914536c86 2014-08-14 20:00 -0700 ben
| | goodbye
| |
o | 2 f098c7f45c4f 2014-08-14 20:01 -0700 ben
|/ Add some documentation
|
o 1 82e55d328c8c 2005-08-26 01:21 -0700 mpm
| Create a makefile
|
o 0 0a04b987be5a 2005-08-26 01:20 -0700 mpm
Create a standard 'hello, world' program
Opazite novo oznako [featureA]
v reviziji 5.
Te se obnašajo enako kot veje Git na strani Git, do ene izjeme: iz Gitove strani ne morete izbrisati zaznamka (to je omejitev oddaljenih pomočnikov).
Prav tako lahko delate na »težkih« vejah Mercurial: preprosto postavite vejo v imenski prostor branches
:
$ git checkout -b branches/permanent
Switched to a new branch 'branches/permanent'
$ vi Makefile
$ git commit -am 'A permanent change'
$ git push origin branches/permanent
To hg::/tmp/hello
* [new branch] branches/permanent -> branches/permanent
Takole bo videti stran Mercurial:
$ hg branches
permanent 7:a4529d07aad4
develop 6:8f65e5e02793
default 5:bd5ac26f11f9 (inactive)
$ hg log -G
o changeset: 7:a4529d07aad4
| branch: permanent
| tag: tip
| parent: 5:bd5ac26f11f9
| user: Ben Straub <[email protected]>
| date: Thu Aug 14 20:21:09 2014 -0700
| summary: A permanent change
|
| @ changeset: 6:8f65e5e02793
|/ branch: develop
| user: Ben Straub <[email protected]>
| date: Thu Aug 14 20:06:38 2014 -0700
| summary: More documentation
|
o changeset: 5:bd5ac26f11f9
|\ bookmark: featureA
| | parent: 4:0434aaa6b91f
| | parent: 2:f098c7f45c4f
| | user: Ben Straub <[email protected]>
| | date: Thu Aug 14 20:02:21 2014 -0700
| | summary: Merge remote-tracking branch 'origin/master'
[...]
Ime veje »permanent« je bilo zabeleženo z označenim naborom sprememb 7.
S stališča Gita je delo z enim od teh načinov vej enako: preprosto izvlečete, potrdite, pridobite, združite, povlečete in potisnite, kot bi sicer storili. Ena stvar, ki jo morate vedeti, je, da Mercurial ne podpira ponovnega pisanja zgodovine, ampak samo dodajanje k njej. Tako je videti naš repozitorij Mercurial po interaktivnem ponovnem baziranju in prisilnem potiskanju:
$ hg log --style compact -G
o 10[tip] 99611176cbc9 2014-08-14 20:21 -0700 ben
| A permanent change
|
o 9 f23e12f939c3 2014-08-14 20:01 -0700 ben
| Add some documentation
|
o 8:1 c16971d33922 2014-08-14 20:00 -0700 ben
| goodbye
|
| o 7:5 a4529d07aad4 2014-08-14 20:21 -0700 ben
| | A permanent change
| |
| | @ 6 8f65e5e02793 2014-08-14 20:06 -0700 ben
| |/ More documentation
| |
| o 5[featureA]:4,2 bd5ac26f11f9 2014-08-14 20:02 -0700 ben
| |\ Merge remote-tracking branch 'origin/master'
| | |
| | o 4 0434aaa6b91f 2014-08-14 20:01 -0700 ben
| | | update makefile
| | |
+---o 3:1 318914536c86 2014-08-14 20:00 -0700 ben
| | goodbye
| |
| o 2 f098c7f45c4f 2014-08-14 20:01 -0700 ben
|/ Add some documentation
|
o 1 82e55d328c8c 2005-08-26 01:21 -0700 mpm
| Create a makefile
|
o 0 0a04b987be5a 2005-08-26 01:20 -0700 mpm
Create a standard "hello, world" program
Nabori sprememb 8, 9 in 10 so bili ustvarjeni in spadajo v vejo permanent
, vendar so stari nabori sprememb še vedno tam.
To lahko zelo zmede vaše sodelavce, ki uporabljajo Mercurial, zato se temu poskusite izogniti.