Skip to content

Latest commit

 

History

History
398 lines (334 loc) · 20.1 KB

File metadata and controls

398 lines (334 loc) · 20.1 KB

Гит и Меркуријал

DVCS свет није само Гит. Уствари, постоји много других система од којих сваки има свој угао посматрања на то како се исправно врши дистрибуирана контрола верзија. Осим програма Гит, најпопуларнији је Меркуријал и они су слични у многим аспектима.

Добра вест је, ако вам се свиђа понашање програма Гит на клијентској страни, али радите на пројекту чији изворни кôд контролише репозиторијум који хостује Меркуријал, постоји начин да програм Гит користите као клијент Меркуријал репозиторијума. Пошто је начин на који програм Гит разговара са серверским репозиторијумима помоћу удаљених референци, не би требало да буде изненађење што је овај мост имплементиран као удаљени помоћник. Име пројекта је git-remote-hg, и може да се пронађе на адреси https://github.com/felipec/git-remote-hg.

git-remote-hg

Најпре је потребно да инсталирате git-remote-hg. То практично значи да поставите његов фајл негде на путању, отприлике овако:

$ curl -o ~/bin/git-remote-hg \
  https://raw.githubusercontent.com/felipec/git-remote-hg/master/git-remote-hg
$ chmod +x ~/bin/git-remote-hg

…уз претпоставку да се ~/bin налази у вредности ваше $PATH променљиве. Git-remote-hg има још једну зависност: mercurial библиотеку за Пајтон. Ако имате инсталиран језик Пајтон, то је просто као пасуљ:

$ pip install mercurial

Ако још увек немате инсталиран Пајтон, најпре посетите https://www.python.org/ и набавите га.

Последња ствар која вам је потребна је Меркуријал клијент. Посетите https://www.mercurial-scm.org/ и инсталирајте га, ако то већ нисте учинили.

Сада можете да пређете на ствар. Потребан вам је само Меркуријал репозиторијум на који можете да гурате. На срећу, сваки Меркуријал репозиторијум може да се понаша на овај начин, тако да ћемо једноставно употребити „hello world” репозиторијум који користи свако да научи Меркуријал:

$ hg clone http://selenic.com/repo/hello /tmp/hello
Први кораци

Сада када имамо погодан „серверски” репозиторијум, можемо да прођемо кроз типични процес рада. Као што можете да видите, ова два система су довољно слична тако да нема много трења.

Најпре клонирамо, као што је увек и обичај у програму Гит:

$ 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

Приметићете да рад са Меркуријал репозиторијумом користи стандардну git clone команду. То је зато јер git-remote-hg функционише на прилично ниском нивоу, користећи сличне механизме којима је имплементиран HTTP/S протокол у програму Гит (удаљени помоћници). Пошто су и Гит и Меркуријал дизајнирани тако да сваки клијент има комплетну копију историје репозиторијума, ова команда креира потпуни клон, укључујући комплетну историју пројекта, а то обавља прилично брзо.

Log команда приказује два комита, од којих на последњи показује читава шума референци. Испоставља се да неке од њих заиста и нису ту. Хајде да погледамо шта се заиста налази у .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 покушава да ствари буду што природније у Гит стилу, али под хаубом он управља концептуалним мапирањем између два незнатно различита система. Директоријум refs/hg је место где се чувају стварне референце. На пример, refs/hg/origin/branches/default је фајл Гит референце који садржи SHA-1 што почиње на „ac7955c” и то је комит на који показује master. Тако да је директоријум refs/hg нека врста лажног refs/remotes/origin, али уз додато прављење разлике између маркера и грана.

Фајл notes/hg је почетна тачка из које git-remote-hg мапира Гит комит хешеве у Меркуријал идентификаторе скупа измена. Хајде да истражимо мало:

$ 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

Дакле, refs/notes/hg показује на стабло које у Гит бази података објеката представља листу осталих објеката са именима. git ls-tree исписује режим, тип, хеш објекта и име фајла за ставке унутар стабла. Када дођемо да једне од ставке стабла, видимо да се у њој налази блоб под именом „ac9117f” (SHA-1 хеш комита на који показује master), и садржајем „0a04b98” (ID Меркуријал скупа измена на врху default гране).

Добра вест је да углавном уопште нема потребе да бринемо о свему овоме. Типичан процес рада се неће много разликовати од рада са Гит удаљеним репозиторијумом.

Постоји још једна ствар коју би требало да обрадимо пре него што наставимо: игнорисања. Меркуријал и Гит за то користе врло сличан механизам, али вероватно не желите да заиста комитујете .gitignore фајл у Меркуријал репозиторијум. На сву срећу, програм Гит има начин да игнорише фајлове који су локални репозиторијуми на диску, а Меркуријал формат је компатибилан са Гит форматом, тако да једноставно можете да га прекопирате:

$ cp .hgignore .git/info/exclude

Фајл .git/info/exclude се понаша као .gitignore, али није део комитова.

Процес рада

Хајде да претпоставимо да смо урадили неки посао и направили неколико комитова на master грану, па сте сада спремни да их гурнете на удаљени репозиторијум. Ево како наш репозиторијум сада изгледа:

$ 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

Наша master грана се налази два комита испред origin/master, али та два комита постоје само на нашој локалној машини. Хајде да видимо да ли је још неко у исто време радио важан посао:

$ 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

Пошто смо употребили заставицу --all, видимо „notes” референце које git-remote-hg интерно користи, али их можемо занемарити. Остатак је оно што смо и очекивали; origin/master је напредовала за један комит, па се наша историја сада раздвојила. За разлику од осталих система са којима радимо у овом поглављу, Меркуријал је способан да обради спајања, тако да нема потребе да радимо било шта спектакуларно.

$ 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

Савршено. Покрећемо тестове и све пролази како треба, тако да смо спремни да свој рад поделимо са остатком тима:

$ git push
To hg::/tmp/hello
   df85e87..0c64627  master -> master

И то је то! Ако погледате Меркуријал репозиторијум видећете да је ова команда урадила оно што смо и очекивали:

$ 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

Скуп измена под бројем 2 је направио Меркуријал, а скупове измена 3 и 4 git-remote-hg, гурањем комитова који су креирани програмом Гит.

Гране и маркери

Програм Git има само једну врсту грана: референцу која се помера када се направе комитови. У програму Меркуријал се ова врста референце назива „маркер” (bookmark) и понаша се скоро исто као и грана у програму Гит.

Концепт „гране” у програму Меркуријал има много дубље значење. Грана на којој се креира скуп измена се чува заједно са скупом измена, што значи да ће увек бити у историји репозиторијума. Ево примера комита који је направљен на develop грани:

$ hg log -l 1
changeset:   6:8f65e5e02793
branch:      develop
tag:         tip
user:        Ben Straub <ben@straub.cc>
date:        Thu Aug 14 20:06:38 2014 -0700
summary:     More documentation

Приметите линију која почиње са „branch”. Програм Гит ово не може у потпуности да преслика (и нема потребе за тим; оба типа гране се могу представити као Гит референца), али git-remote-hg мора да разуме разлику, јер је Меркуријал прави.

Креирање Меркуријал маркера је једноставно као креирање Гит грана. На Гит страни:

$ git checkout -b featureA
Switched to a new branch 'featureA'
$ git push origin featureA
To hg::/tmp/hello
 * [new branch]      featureA -> featureA

И то је све. На Меркуријал страни, изгледа овако:

$ 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

Приметите нову ознаку [featureA] на ревизији 5. Оне се понашају потпуно исто као Гит гране са стране програма Гит, уз један изузетак: маркер не можете да обришете са стране програма Гит (ово је ограничење помоћника за удаљене).

Такође можете да радите и на „тешким” Меркуријал гранама: једноставно ставите грану у 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

Ево како то изгледа са Меркуријал стране:

$ 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 <ben@straub.cc>
|  date:        Thu Aug 14 20:21:09 2014 -0700
|  summary:     A permanent change
|
| @  changeset:   6:8f65e5e02793
|/   branch:      develop
|    user:        Ben Straub <ben@straub.cc>
|    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 <ben@straub.cc>
| |  date:        Thu Aug 14 20:02:21 2014 -0700
| |  summary:     Merge remote-tracking branch 'origin/master'
[...]

Име гране „permanent” је снимљено са скупом измена под ознаком 7.

Гледано са Гит стране, рад са било којоим од ова два стила грана је сити: једноставно одјављујете, комитујете, преузимате, спајате, повлачите и гурате као и иначе. Једна ствар коју би требало да знате је да Меркуријал не подржава поновно исписисвање историје, може само да додаје у историју. Ево како наш Меркуријал репозиторијум изгледа након интерактивног ребазирања и наметнутог гурања:

$ 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

Креирани су скупови измена 8, 9, и 10 и припадају permanent грани, али су још увек присутни стари скупови измена. Ово може тотално да збуни ваше колеге из тима који користе Меркуријал, па би било добро да то не радите.

Меркуријал резиме

Програми Гит и Меркуријал су довољно слични да је рад са друге стране границе прилично безболан. Ако избегнете мењање историје која је остала на вашој машини (као што се и иначе препоручује), можда нећете ни приметите да је са друге стране Меркуријал.