Git
Chapters ▾ 2nd Edition

9.1 Гит и остали системи - Гит као клијент

Свет није савршен. У већини случајева не можете одмах да пребаците сваки пројекат са којим дођете у контакт на Гит. Некад сте заглављени на пројекту који користи неки други VCS, а волели бисте да је то Гит. Први део овог поглавља ћемо посветити учењу начина на које можете да користите Гит као клијент када је пројекат на којем радите хостован на другом систему.

У једном тренутку ћете можда пожелети да конвертујете свој постојећи пројекат у Гит. Други део овог поглавља покрива начин миграције пројекта на Гит из неколико одређених система, као и метода која ће функционисати ако не постоје већ готови алати за увоз.

Гит као клијент

Програм Гит је програмерима толико угодан за коришћење да су многи људи открили како да га користе на својој радној станици, чак и ако остатак тима користи потпуно другачији VCS. Постоји много оваквих адаптера који се називају „мостови”. Овде ћемо покрити неке на које ћете највероватније наићи.

Гит и Subversion

Велики део развојних пројеката отвореног кода и порпиличан број корпоративних пројеката користе Subversion да управља њиховим изворним кодом. Присутан је већ више од десет година и већину тог времена је био де факто VCS избор за пројекте отвореног кода. У многим стварима је врло сличан са CVS који је пре тога био татамата света контроле изворног кода.

Једна од одличних могућности програма Гит је двосмерни мост према програму Subversion који се зове git svn. Овај алат вам омогућава да програм Гит користите као важећи клијент Subversion сервера, тако да можете користити све локалне могућности програма Гит и да их затим гурнете на Subversion сервер као да се и локално користили Subversion. Ово значи да можете радити локално гранање и спајање, користите стејџ, употребљавате ребазирање и избор (cherry-picking) и тако даље, док ваши сарадници настављају да раде на своје мрачне прастаре начине. То је добар начин да провучете програм Гит у корпоративно окружење и помогнете да ваше колеге програмери постану ефикаснији док ви лобирате да се инфраструктура промени тако да у потпуности подржава програм Гит. Subversion мост је уводна дрога у DVCS свет.

git svn

Основна команда у програму Гит за све команде премошћавања до Subversion је git svn. Постоји поприличан број команди, тако да ћемо приказати најчешће док пролазимо кроз неколико једноставних процеса рада.

Важно је приметити да када користите git svn, ви имате интеракцију са програмом Subversion, а то је систем који функционише веома различито у односу на програм Гит. Мада можете да радите локално гранање и спајање, у општем случају је најбоље да историју држите што је могуће више линеарном тако што ребазирате свој рад и избегавате да радите ствари као што је истовремена интеракција са удаљеним Гит репозиторијумом.

Немојте поново да исписујете своју историју и покушате поново да је гурнете и немојте да истовремено гурате на паралелни Гит репозиторијум како би сарађивали са колегама који за развој користе Гит. Subversion може да има са једну линеарну историју, и врло је једноставно да га збуните. Ако радите у тиму где неко користи SVN, а остали користе Гит, обезбедите да сви за сарадњу користе SVN сервер – на тај начин ће вам живот бити једноставнији.

Подешавање

Да бисте пробали ову функционалност, потребан вам је типичан SVN репозиторијум на који има те право уписа. Ако желите да копирате ове примере, мораћете да направите копију мог тест репозиторијума по којој можете да пишете. То једноставно можете урадити алатом који се зове svnsync и долази уз програм Subversion. Као подршку овим тестовима, направили смо нови Subversion репозиторијум на Google Code који је представљао делимичну копију пројекта protobuf, алата који кодира структуре података тако да могу да се преносе кроз мрежу.

Да бисте успешно пратили, најпре морате да креирате нови локални Subversion репозиторијум:

$ mkdir /tmp/test-svn
$ svnadmin create /tmp/test-svn

Затим омогућите свим корисницима право да мењају revprops – то се на једноставан начин ради тако да додате скрипту pre-revprop-change која увек враћа повратну вредност 0:

$ cat /tmp/test-svn/hooks/pre-revprop-change
#!/bin/sh
exit 0;
$ chmod +x /tmp/test-svn/hooks/pre-revprop-change

Овај пројекат сада можете да синхронизујете на своју локалну машину тако што позовете svnsync init са ’из’ и ’у’ репозиторијумима.

$ svnsync init file:///tmp/test-svn \
  http://progit-example.googlecode.com/svn/

Ово поставља особине за позив синхронизације. Затим клонирате кôд извршавајући:

$ svnsync sync file:///tmp/test-svn
Committed revision 1.
Copied properties for revision 1.
Transmitting file data .............................[...]
Committed revision 2.
Copied properties for revision 2.
[…]

Мада ова операција може да потраје само неколико минута, ако уместо на локални оригинални репозиторијум покушате да копирате на други удаљени репозиторијум, процес ће трајати скоро сат времена, мада постоји мање од 100 комитова. Subversion мора да клонира ревизије једну по једну, па да их затим гурне на други репозиторијум – потпуно неефикасно, али је то једини начин да се ово уради.

Први кораци

Сада када имате Subversion репозиторијум у који можете да уписујете, можете да прођете кроз типичан процес рада. Почећете да командом git svn clone која увози комплетан Subversion репозиторијум у локални Гит репозиторијум. Упамтите да ако увозите из реалног хостованог Subversion репозиторијума, фајл file:///tmp/test-svn приказан овде треба да замените са URL адресом вашег Subversion репозиторијума:

$ git svn clone file:///tmp/test-svn -T trunk -b branches -t tags
Initialized empty Git repository in /private/tmp/progit/test-svn/.git/
r1 = dcbfb5891860124cc2e8cc616cded42624897125 (refs/remotes/origin/trunk)
    A	m4/acx_pthread.m4
    A	m4/stl_hash.m4
    A	java/src/test/java/com/google/protobuf/UnknownFieldSetTest.java
    A	java/src/test/java/com/google/protobuf/WireFormatTest.java
…
r75 = 556a3e1e7ad1fde0a32823fc7e4d046bcfd86dae (refs/remotes/origin/trunk)
Found possible branch point: file:///tmp/test-svn/trunk => file:///tmp/test-svn/branches/my-calc-branch, 75
Found branch parent: (refs/remotes/origin/my-calc-branch) 556a3e1e7ad1fde0a32823fc7e4d046bcfd86dae
Following parent with do_switch
Successfully followed parent
r76 = 0fb585761df569eaecd8146c71e58d70147460a2 (refs/remotes/origin/my-calc-branch)
Checked out HEAD:
  file:///tmp/test-svn/trunk r75

Ово извршава еквивалент две команде – git svn init након које следи git svn fetch – над URL адресом коју наведете. Може да потраје. Тест пројекат има само око 75 комитова и база кода није толико велика, али програм Гит мора да одјави сваку верзију, једну по једну, па да је засебно комитује. За пројекат са стотинама или хиљадама комитова, ово буквално може да потраје сатима или чак данима док се не заврши.

-T trunk -b branches -t tags део говори програму Гит да овај Subversion репозиторијум прати основне конвенције гранања и означавања. Ако свом стаблу, гранама или ознакама желите да дате другачија имена, промените ове опције. Пошто је ово толико уобичајено, комплетан део можете да замените са -s, што значи стандардни распоред и подразумева све те опције. Следећа команда је еквивалентна:

$ git svn clone file:///tmp/test-svn -s

У овом тренутку би требало да имате исправан Гит репозиторијум које увезао ваше гране и ознаке:

$ git branch -a
* master
  remotes/origin/my-calc-branch
  remotes/origin/tags/2.0.2
  remotes/origin/tags/release-2.0.1
  remotes/origin/tags/release-2.0.2
  remotes/origin/tags/release-2.0.2rc1
  remotes/origin/trunk

Приметите како овај алат управља Subversion ознакама као удаљеним референцама. Хајде да детаљније погледамо водоводном командом програма Гит show-ref:

$ git show-ref
556a3e1e7ad1fde0a32823fc7e4d046bcfd86dae refs/heads/master
0fb585761df569eaecd8146c71e58d70147460a2 refs/remotes/origin/my-calc-branch
bfd2d79303166789fc73af4046651a4b35c12f0b refs/remotes/origin/tags/2.0.2
285c2b2e36e467dd4d91c8e3c0c0e1750b3fe8ca refs/remotes/origin/tags/release-2.0.1
cbda99cb45d9abcb9793db1d4f70ae562a969f1e refs/remotes/origin/tags/release-2.0.2
a9f074aa89e826d6f9d30808ce5ae3ffe711feda refs/remotes/origin/tags/release-2.0.2rc1
556a3e1e7ad1fde0a32823fc7e4d046bcfd86dae refs/remotes/origin/trunk

Програм Гит ово не ради када клонира са Гит сервера; ево како изгледа репозиторијум након свежег клонирања:

$ git show-ref
c3dcbe8488c6240392e8a5d7553bbffcb0f94ef0 refs/remotes/origin/master
32ef1d1c7cc8c603ab78416262cc421b80a8c2df refs/remotes/origin/branch-1
75f703a3580a9b81ead89fe1138e6da858c5ba18 refs/remotes/origin/branch-2
23f8588dde934e8f33c263c6d8359b2ae095f863 refs/tags/v0.1.0
7064938bd5e7ef47bfd79a685a62c1e2649e2ce7 refs/tags/v0.2.0
6dcb09b5b57875f334f61aebed695e2e4193db5e refs/tags/v1.0.0

Програм Гит преузима ознаке директно у refs/tags, уместо да их третира као удаљене гране.

Комитовање назад на Subversion

Сада када имате функционалан репозиторијум, можете да урадите неки посао на пројекту и гурнете своје комитове узводно, тако што програм Гит ефективно користите као SVN клијент. Ако уредите један од фајлова и комитујете га, имаћете комит који постоји локално у програму Гит и не постоји на Subversion серверу:

$ git commit -am 'Adding git-svn instructions to the README'
[master 4af61fd] Adding git-svn instructions to the README
 1 file changed, 5 insertions(+)

Затим, своју измену морате да гурнете узводно. Приметите како ово мења начин на који радите са програмом Subversion – можете да урадите неколико комитова док ста ван мреже, па да их све одједном гурнете на Subversion сервер. Када желите да гурнете на Subversion сервер, извршите команду git svn dcommit:

$ git svn dcommit
Committing to file:///tmp/test-svn/trunk ...
    M	README.txt
Committed r77
    M	README.txt
r77 = 95e0222ba6399739834380eb10afcd73e0670bc5 (refs/remotes/origin/trunk)
No changes between 4af61fd05045e07598c553167e0f31c84fd6ffe1 and refs/remotes/origin/trunk
Resetting to the latest refs/remotes/origin/trunk

Ово узима све комитове које сте направили преко кода са Subversion сервера, за сваки од њих врши Subversion комит, па онда поново исписује ваш локални Гит комит тако да укључи јединствени идентификатор. То је важно јер значи да се све SHA-1 контролне суме ваших комитова мењају. Делимично због овог разлога, истовремени рад са удаљеним Гит верзијама вашег пројекта и Subversion сервером није добра идеја. Ако погледате последњи комит, можете видети уметнути нови git-svn-id:

$ git log -1
commit 95e0222ba6399739834380eb10afcd73e0670bc5
Author: ben <ben@0b684db3-b064-4277-89d1-21af03df0a68>
Date:   Thu Jul 24 03:08:36 2014 +0000

    Adding git-svn instructions to the README

    git-svn-id: file:///tmp/test-svn/trunk@77 0b684db3-b064-4277-89d1-21af03df0a68

Приметите да је SHA-1 контролна сума када сте раније комитовали почињала са 4af61fd, а да сада почиње са 95e0222. Ако желите да гурнете и на Гит и на Subversion сервер, прво морате да гурнете (dcommit) на Subversion сервер, јер та акција мења ваше комит податке.

Повлачење нових измена

Ако радите са другим програмерима, онда ће у неком тренутку један од вас гурнути, па ће онда неко други покушати да гурне измену која изазива конфликт. Та измена ће бити одбијена док не спојите њихов рад. У git svn то изгледа овако:

$ git svn dcommit
Committing to file:///tmp/test-svn/trunk ...

ERROR from SVN:
Transaction is out of date: File '/trunk/README.txt' is out of date
W: d5837c4b461b7c0e018b49d12398769d2bfc240a and refs/remotes/origin/trunk differ, using rebase:
:100644 100644 f414c433af0fd6734428cf9d2a9fd8ba00ada145 c80b6127dd04f5fcda218730ddf3a2da4eb39138 M	README.txt
Current branch master is up to date.
ERROR: Not all changes have been committed into SVN, however the committed
ones (if any) seem to be successfully integrated into the working tree.
Please see the above messages for details.

Да бисте разрешили ову ситуацију, можете да извршите git svn rebase, која повлачи евентуалне измене на серверу које још увек немате и ребазира ваш рад (ако га има) на врх онога што се налази на серверу:

$ git svn rebase
Committing to file:///tmp/test-svn/trunk ...

ERROR from SVN:
Transaction is out of date: File '/trunk/README.txt' is out of date
W: eaa029d99f87c5c822c5c29039d19111ff32ef46 and refs/remotes/origin/trunk differ, using rebase:
:100644 100644 65536c6e30d263495c17d781962cfff12422693a b34372b25ccf4945fe5658fa381b075045e7702a M	README.txt
First, rewinding head to replay your work on top of it...
Applying: update foo
Using index info to reconstruct a base tree...
M	README.txt
Falling back to patching base and 3-way merge...
Auto-merging README.txt
ERROR: Not all changes have been committed into SVN, however the committed
ones (if any) seem to be successfully integrated into the working tree.
Please see the above messages for details.

Сада је сав ваш рад преко онога што се налази на Subversion серверу, тако да можете успешно извршити dcommit:

$ git svn dcommit
Committing to file:///tmp/test-svn/trunk ...
    M	README.txt
Committed r85
    M	README.txt
r85 = 9c29704cc0bbbed7bd58160cfb66cb9191835cd8 (refs/remotes/origin/trunk)
No changes between 5762f56732a958d6cfda681b661d2a239cc53ef5 and refs/remotes/origin/trunk
Resetting to the latest refs/remotes/origin/trunk

Приметите да за разлику од програма Гит, који од вас захтева да пре него што гурнете спојите сав узводни рад који још увек немате локално, git svn од вас то тражи само ако измене изазивају конфликт (слично као што ради и Subversion). Ако неко други гурне измену једног фајла, панда ви гурнете измену неког другог фајла, ваша dcommit ће функционисати без проблема:

$ git svn dcommit
Committing to file:///tmp/test-svn/trunk ...
    M	configure.ac
Committed r87
    M	autogen.sh
r86 = d8450bab8a77228a644b7dc0e95977ffc61adff7 (refs/remotes/origin/trunk)
    M	configure.ac
r87 = f3653ea40cb4e26b6281cec102e35dcba1fe17c4 (refs/remotes/origin/trunk)
W: a0253d06732169107aa020390d9fefd2b1d92806 and refs/remotes/origin/trunk differ, using rebase:
:100755 100755 efa5a59965fbbb5b2b0a12890f1b351bb5493c18 e757b59a9439312d80d5d43bb65d4a7d0389ed6d M	autogen.sh
First, rewinding head to replay your work on top of it...

Ово је важно да се запамти, је крајњи исход стање пројекта које није постојало ни на једном од ваших компјутера када сте гурнули. Ако измене нису компатибилне али не изазивају конфликт, можете имати проблеме који се тешко откривају. То је разлика у односу на употребу Гит сервера – у програму Гит Git стање можете потпуно тестирати на свом клијентском систему пре него што га објавите, док у SVN, никада не можете бити сигурни да су стања непосредно пре и након комита идентична.

Ову команду би такође требало да извршите за повлачење измена са Subversion сервера, чак и ако сами нисте спремни да комитујете. Можете извршити git svn fetch да само преузмете нове податке, али git svn rebase преузима па ажурира ваше локалне комитове.

$ git svn rebase
    M	autogen.sh
r88 = c9c5f83c64bd755368784b444bc7a0216cc1e17b (refs/remotes/origin/trunk)
First, rewinding head to replay your work on top of it...
Fast-forwarded master to refs/remotes/origin/trunk.

Повремено извршавање git svn rebase обезбеђује да је ваш кôд увек у свежем стању. Ипак, да бисте ово извршили, морате бити сигурни да је ваш радни директоријум чист. Ако имате локалне измене, морате прво или да сакријете свој рад, или да га привремено комитујете пре покретања git svn rebase – у супротном ће команда прекинути извршавање ако види да ће резултат ребазирања изазвати конфликт при спајању.

Проблеми са Гит гранањем

Када вам Гит процес рада постане удобан, вероватно ћете почети да креирате тематске гране, радите на њима, па их спајате у главну. Ако гурате на Subversion сервер командом git svn, уместо да гране спајате могли бисте да свој рад ребазирате на једну грану. Ребазирање је пожељније од спајања јер Subversion има линеарну историју и не носи се са спајањима као што то ради програм Гит, тако да git svn следи само првог родитеља када конвертује снимке у Subversion комитове.

Претпоставимо да вам историја изгледа на следећи начин: креирали сте experiment грану, направили два комита, па их онда спојили назад у master. Када извршите dcommit, добијате следећи излаз:

$ git svn dcommit
Committing to file:///tmp/test-svn/trunk ...
    M	CHANGES.txt
Committed r89
    M	CHANGES.txt
r89 = 89d492c884ea7c834353563d5d913c6adf933981 (refs/remotes/origin/trunk)
    M	COPYING.txt
    M	INSTALL.txt
Committed r90
    M	INSTALL.txt
    M	COPYING.txt
r90 = cb522197870e61467473391799148f6721bcf9a0 (refs/remotes/origin/trunk)
No changes between 71af502c214ba13123992338569f4669877f55fd and refs/remotes/origin/trunk
Resetting to the latest refs/remotes/origin/trunk

Извршавање dcommit на грани са спојеном историјом ради како треба, није поново исписала ниједан од комитова које сте направили на experiment грани – уместо тога, све те измене се појављују у SVN верзији једног јединог комита спајања.

Када неко други клонира тај рад, све што види је комит спајања са комплетним радом сабијеним у њега, као да сте извршили git merge --squash; не види податке о томе одакле је комит дошао или када је направљен.

Subversion гранање

Гранање у програму Subversion није исто као гранање у програму Гит; вероватно је најбоље ако можете избећи да га често користите. Ипак, са git svn можете да креирате и комитујете Subversion гране.

Креирање нове SVN гране

Ако желите да креирате нову Subversion грану, извршите git svn branch [имегране]:

$ git svn branch opera
Copying file:///tmp/test-svn/trunk at r90 to file:///tmp/test-svn/branches/opera...
Found possible branch point: file:///tmp/test-svn/trunk => file:///tmp/test-svn/branches/opera, 90
Found branch parent: (refs/remotes/origin/opera) cb522197870e61467473391799148f6721bcf9a0
Following parent with do_switch
Successfully followed parent
r91 = f1b64a3855d3c8dd84ee0ef10fa89d27f1584302 (refs/remotes/origin/opera)

Ово је еквивалентно Subversion команди svn copy trunk branches/opera и оперише на Subversion серверу. Важно је приметити да она вас она не одјављује у ту грану; ако у овом тренутку комитујете, так комит иде у trunk на серверу, а не у opera.

Пребацивање активних грана

Програм Git открива на коју грану иду ваши dcommit тако што гледа на врх било које Subversion гране у вашој историји – требало би да имате само једну, а то би у исорији тренутне гране требало да буде последња са git-svn-id.

Ако желите истовремено да радите на више од једне гране, команди dcommit можете да подесите локалне гране на одређене Subversion грана започињући их као увезени Subversion комит за ту грану. Ако желите грану opera на којој можете одвојено да радите, извршите:

$ git branch opera remotes/origin/opera

Ако сада желите да своју opera грану спојите у trunk (односно вашу master грану), то можете урадити обичном git merge командом. Али морате навести описну комит поруку (са -m), или ће спајање уместо нечег корисниг да буде „Merge branch opera”.

Упамтите да мада за ову операцију користите git merge и спајање ће вероватно бити доста једноставније него што би било у програму Subversion (јер ће програм Гит аутоматски за вас да открије погодну базу за спајање), ово није уобичајен Гит комит спајања. Ове податке морате да гурнете назад Subversion серверу који не може да обради комит који прати више од једног родитеља; дакле, након што га гурнете узводно, изгледаће као један једини комит који је сабио сав рад на другој грани у један комит. Када једну грану спојите у другу, можете једноставно да се вратите назад и наставите да радите на тој грани, као и иначе што бисте у програму Гит. Команда dcommit коју извршавате брише било какве информације које кажу која грана је спојена, тако да ће накнадна израчунавања базе спајања вити погрешна – dcommit чини да резултат ваше git merge команде изгледа као да се извршили git merge --squash. Нажалост, не постоји добар начин да се избегне оваква ситуација – Subversion не може да забележи ову информацију, тако да ће вас увек спутавати његова ограничења док год га користите као свој сервер. Да бисте спречили проблеме, када је спојите у trunk требало би да обришете локалну грану (у овом случају, opera).

Subversion команде

git svn скуп алата обезбеђује већи број команди које помажу да се олакша прелаз на Гит нудећи неку функционалност која је слична оној коју имате у програму Subversion. Ево неколико команди које вам пружају оно што је Subversion.

Историја у SVN стилу

Ако сте навикли на Subversion и своју историју желите да видите као излаз у SVN стилу, you можете да извршите git svn log која вам приказује SVN форматирану комит историју:

$ git svn log
------------------------------------------------------------------------
r87 | schacon | 2014-05-02 16:07:37 -0700 (Sat, 02 May 2014) | 2 lines

autogen change

------------------------------------------------------------------------
r86 | schacon | 2014-05-02 16:00:21 -0700 (Sat, 02 May 2014) | 2 lines

Merge branch 'experiment'

------------------------------------------------------------------------
r85 | schacon | 2014-05-02 16:00:09 -0700 (Sat, 02 May 2014) | 2 lines

updated the changelog

Требало би да знате две важне ствари у вези команде git svn log. Прво, она за разлику од праве svn log команде која тражи податке од Subversion сервера тражи податке, ради ван мреже. Друго, она вам приказује само оне комитове који су комитовани на Subversion сервер. Локални Фит комитови над којима још нисте извршили dcommit се не појављују; као ни комитови које су у међувремену остали доставили на Subversion сервер. Она пре приказује последње познато стање комитова на Subversion серверу.

SVN означавање

На сличан начин на који git svn log команда симулира svn log команду ван мреже, еквивалент команде svn annotate можете добити извршавањем git svn blame [ФАЈЛ]. Излаз изгледа овако:

$ git svn blame README.txt
 2   temporal Protocol Buffers - Google's data interchange format
 2   temporal Copyright 2008 Google Inc.
 2   temporal http://code.google.com/apis/protocolbuffers/
 2   temporal
22   temporal C++ Installation - Unix
22   temporal =======================
 2   temporal
79    schacon Committing in git-svn.
78    schacon
 2   temporal To build and install the C++ Protocol Buffer runtime and the Protocol
 2   temporal Buffer compiler (protoc) execute the following:
 2   temporal

Опет, она не приказује комитове које сте локално направили у програму Гит, или оне који су у међувремену гурнути на Subversion сервер.

Информације о SVN серверу

Исту врсту информација које вам пружа svn info можете добити ако извршите git svn info:

$ git svn info
Path: .
URL: https://schacon-test.googlecode.com/svn/trunk
Repository Root: https://schacon-test.googlecode.com/svn
Repository UUID: 4c93b258-373f-11de-be05-5f7a86268029
Revision: 87
Node Kind: directory
Schedule: normal
Last Changed Author: schacon
Last Changed Rev: 87
Last Changed Date: 2009-05-02 16:07:37 -0700 (Sat, 02 May 2009)

Ово је слично са blame и log у томе што се извршава ван мреже и што је ажурно само до последњег тренутка када сте имали комуникацију са Subversion сервером.

Игнорисање онога што игнорише Subversion

Ако клонирате Subversion репозиторијум који негде има постављене svn:ignore особине, вероватно ћете хтети да поставите одговарајуће .gitignore фајлове тако да случајно не комитујете фајлове које не би требало. git svn има две команде које вам помажу у томе. Прва је git svn create-ignore, која уместо вас аутоматски креира одговарајуће .gitignore фајлове тако да ваш наредни комит не може да их укључи.

Друга команда је git svn show-ignore, која на stdout исписује линије које треба поставите у .gitignore фајл, тако њен излаз можете да преусмерите у фајл изузетака пројекта:

$ git svn show-ignore > .git/info/exclude

На тај начин не затрпавате пројекат .gitignore фајловима. Ово је добра опција у случају да сте једини Гит корисник у Subversion тиму и ваше колеге из тима не желе .gitignore фајлове у пројекту.

Git-Svn резиме

git svn алату су корисни ако сте заглављени на Subversion серверу, или у неком развојном окружењу у којем је неопходно покретање Subversion сервера. Ипак, требало би да га сматрате ограниченим програмом Гит, или ћете наићи на проблеме у превођењу коју могу да збуне и вас и ваше сараднике. Покушајте се држати следећих смерница како не бисте упали у невоље:

  • Одржавајте линеарну Гит историју која не садржи git merge комитове спајања. Ребазирајте сав рад који радите ван главне гране назад на њу; не спајајте у главну грану.

  • Не постављате и не сарађујте на одвојеном Гит серверу. По могућству имајте један који убрзава клонирања за нове програмере, али не гурајте на њега ништа што нема git-svn-id ставку. Чак можете да додате и pre-receive куку која проверава сваку комит поруку на постојање git-svn-id и одбија гурања које садрже комит поруке без ње.

Ако следите ове препоруке, рад са Subversion сервером може постати подношљив. Међутим, ако постоји могућност, пређите на прави Гит сервер, на тај начин ћете и ви и тим добити још много више.

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

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 грани, али су још увек присутни стари скупови измена. Ово може тотално да збуни ваше колеге из тима који користе Меркуријал, па би било добро да то не радите.

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

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

Гит и Базаар

Још један од чувених DVCS је Базаар. Базаар је слободан и отвореног кода и чини део ГНУ пројекта. Понаша се потпуно другачије од програма Гит. Понекада, ако желите да урадите исту ствар као у програму Гит, морате да употребите другу кључну реч, а неке заједничке кључне речи немају исто значење. Уствари, управљање гранама је веома различито и може да унесе забуну, посебно некоме ко долази из Гит света. Без обзира на све, могуће је радити на Базаар репозиторијуму из Гит репозиторијума.

Постоје многи пројекти који вам омогућавају да програм Гит користите као Базаар клијент. Овде ћемо употребити пројекат Фелипеа Контрераса који можете пронаћи на адреси https://github.com/felipec/git-remote-bzr. Да бисте га инсталирали, једноставно треба да преузмете фајл git-remote-bzr и поставите га у директоријум који је део $PATH:

$ wget https://raw.github.com/felipec/git-remote-bzr/master/git-remote-bzr -O ~/bin/git-remote-bzr
$ chmod +x ~/bin/git-remote-bzr

Такође је потребно да имате инсталиран програм Базаар. И то је све!

Креирање Гит репозиторијума из Базаар репозиторијума

Ово је једноставно. Довољно је да клонирате Базаар репозиторијум тако што испред имена наведете bzr::. Пошто и Гит и Базаар раде потпуно клонирање на вашу машину, Гит клон може да се прикачи на Базаар клон, али се то не препоручује. It’s much easier to attach your Git clone directly to the same place your Bazaar clone is attached to — the central repository.

Претпоставимо да сте радили са удаљеним репозиторијумом који се налази на адреси bzr+ssh://developer@mybazaarserver:myproject. Затим морате да га клонирате на следећи начин:

$ git clone bzr::bzr+ssh://developer@mybazaarserver:myproject myProject-Git
$ cd myProject-Git

У овом тренутку имате креиран Гит репозиторијум, али он није оптимизован за ефикасно искоришћење диска. Зато би требало да пречистите и сажмете ваш Гит репозиторијум, посебно ако је велики:

$ git gc --aggressive

Базаар гране

Базаар вам дозвољава само да клонирате гране, али репозиторијум може да садржи неколико грана, па git-remote-bzr може да клонира и једно и друго. На пример, ако желите да клонирате грану:

$ git clone bzr::bzr://bzr.savannah.gnu.org/emacs/trunk emacs-trunk

А да клонирате комплетан репозиторијум:

$ git clone bzr::bzr://bzr.savannah.gnu.org/emacs emacs

Друга команда клонира све гране које се налазе у emacs репозиторијуму; међутим, ипак је могуће да се укаже на поједине гране:

$ git config remote-bzr.branches 'trunk, xwindow'

Неки репозиторијуми вам не дозвољавају да видите њихове гране, па их у том случају морате ручно навести, мада бисте могли да наведете конфигурацију у команди клонирања, можда вам је ово лакше:

$ git init emacs
$ git remote add origin bzr::bzr://bzr.savannah.gnu.org/emacs
$ git config remote-bzr.branches 'trunk, xwindow'
$ git fetch

Игнорисање онога што се игнорише у .bzrignore

Пошто радите на пројекту којим управља Базаар, не би требало да креирате .gitignore фајл јер нехотично можете да га поставите под контролу верзија и то може засметати осталим људима који користе Базаар. Решење је да фајл .git/info/exclude креирате или као симболички линк или као обичан фајл. Касније ћемо видети како се решава ово питање.

Базаар за игнорисање фајлова користи исти модел као и програм Гит, али има и две могућности које немају свој еквивалент у програму Гит. Комплетан опис се налази у документацији. Могућности су следеће:

  1. „!!” вам дозвољава да игноришете одређене фајл шаблоне чак и када су наведени употребом „!” правила.

  2. "RE:" на почетку линије вам дозвољава да наведете Пајтон регуларни израз (програм Гит дозвољава само глобове љуске).

Као последица, постоје две различите ситуације о којима треба да размислите:

  1. Ако .bzrignore фајл не садржи ниједан од ова два посебна префикса, онда једноставно у репозиторијуму можете направити симболички линк на њега: ln -s .bzrignore .git/info/exclude.

  2. У супротном, морате да креирате фајл .git/info/exclude и да га прилагодите тако да се игноришу потпуно исти фајлови као у .bzrignore.

Шта год да је случај, мораћете остати на опрезу у случају било какве измене фајла .bzrignore и да осигурате да фајл .git/info/exclude увек пресликава .bzrignore. Заиста, ако би измена .bzrignore фајла садржала једну или више линија које почињу са „!!” или „RE:”, како програм Git не може те линије да интерпретира, морали бисте да преправите свој .git/info/exclude фајл тако да игнорише исте фајлове као оне које игнорише .bzrignore фајл. Уз то, ако је .git/info/exclude фајл уствари симболички линк, прво морате да обришете симболички линк, копирате .bzrignore у .git/info/exclude па да онда прилагодите овај други. Међутим, будите опрезни у вези креирања овог фајла, јер је са програмом Гит немогуће поновно укључивање фајла ако је директоријум родитељ тог фајла искључен.

Преузимање измена са удаљеног репозиторијума

Да бисте преузели измене са удаљеног, повлачите измене као и обично, употребом команди програма Гит. Под претпоставком да су ваше измене на master грани, спајате или ребазирате свој рад на origin/master грану:

$ git pull --rebase origin

Гурање вашег рада на удаљени репозиторијум

Пошто и Базаар има концепт комитова спајања, неће бити проблема ако гурнете комит спајања. Тако да можете радити на грани, спојити измене у master и гурнути свој рад. Затим, креирате своје гране, тестирате и комитујете рад као и обично. На крају гурнете свој рад на Базаар репозиторијум:

$ git push origin master

Ограничења

Радни оквир програма Гит за удаљене помоћнике има нека ограничења која важе. Тачније, следеће команде не функционишу:

  • git push origin :грана-за-брисање (Базаар не прихвата овакав начин брисања референци)

  • git push origin old:new (гурнуће се old)

  • git push --dry-run origin branch (извршиће се гурање)

Резиме

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

Гит и Перфорс

Перфорс је веома популаран систем за контролу верзија у корпоративним окружењима. На тржишту је од 1995. године што га чини најстаријим системом који је покривен овим поглављем. Као такав, дизајниран је са ограничењима која су важила тих дана; претпоставља да сте увек повезани на један централни сервер и на локалном диску се чува само једна верзија. Истини за вољу, његове могућности и ограничења су прилагођене неколицини специфичних проблема, али постоји много пројеката који користе Перфорс тамо где би Гит у суштини функционисао боље.

Постоје две опције ако желите да мешате употребу програма Перфорс и Гит. Прва коју ћемо представите је Git Fusion мост који праве творци програма Перфорс и који вам дозвољава да подстабла Перфорс депоа изложите као Гит репозиторијума по којима може да се чита и пише. Друга је git-p4, мост на клијентској страни који вам омогућава да програм Гит користите као Перфорс клијент, без потребе било какве реконфигурације Перфорс сервера.

Git Fusion

Перфорс нуди производ под називом Git Fusion (доступан на http://www.perforce.com/git-fusion), који са серверске стране синхронизује Перфорс сервер са Гит репозиторијумима.

Подешавање

У нашим примерима ћемо користи најлакшу методу инсталације програма Git Fusion, која представља преузимање виртуелне машине која извршава Перфорс даемон и Git Fusion. Слику виртуелне машине можете преузети са адресе http://www.perforce.com/downloads/Perforce/20-User, па када се преузимање заврши, увезете је у свој омиљени софтвер за виртуелизацију (овде ћемо користити VirtualBox).

Када по први пут покренете машину, питаће вас да подесите лозинку за три Линукс корисника (root, perforce, и git) и наведете име инстанце, које се користи да се та инсталација разликује од осталих на истој мрежи. Када се све то заврши, видећете следеће:

Екран при покретању _Git Fusion_ виртуелне машине
Слика 145. Екран при покретању Git Fusion виртуелне машине

Требало би да прибележите IP адресу која се овде прикаже, касније ћемо је користити. Затим ћемо да креирамо Перфорс корисника. Изаберите опцију „Login” на дну екрана и притисните ентер (или направите SSH везу са машином), и пријавите се као root. Затим употребите следеће команде да креирате корисника:

$ p4 -p localhost:1666 -u super user -f john
$ p4 -p localhost:1666 -u john passwd
$ exit

Прва команда ће покренути VI едитор да прилагодите корисника, али можете и прихватити подразумевана подешавања тако што откуцате :wq и притиснете ентер. Друга ће од вас захтевати да двапут унесете лозинку. То је све што је потребно да се уради у одзиву љуске, па напустите сесију.

Следећа ствар коју морате урадити је да програму Гит наложите да не проверава SSL сертификате. Git Fusion слика долази са сертификатом, али он је за домен који се не подудара са IP адресом ваше виртуелне машине, тако да ће програм Гит одбити да успостави HTTPS везу. Ако ће ово бити стална инсталација, консултујте Перфорс Git Fusion упутство да бисте инсталирали одговарајући сертификат; за наше потребе, следеће ће бити довољно:

$ export GIT_SSL_NO_VERIFY=true

Сада можете проверити да ли све ради како треба.

$ git clone https://10.0.1.254/Talkhouse
Cloning into 'Talkhouse'...
Username for 'https://10.0.1.254': john
Password for 'https://john@10.0.1.254':
remote: Counting objects: 630, done.
remote: Compressing objects: 100% (581/581), done.
remote: Total 630 (delta 172), reused 0 (delta 0)
Receiving objects: 100% (630/630), 1.22 MiB | 0 bytes/s, done.
Resolving deltas: 100% (172/172), done.
Checking connectivity... done.

Слика виртуелне машине долази опремљена са примером пројекта који можете да клонирате. Овде ћемо да клонирамо преко HTTPS, користећи john корисника којег смо управо креирали изнад; програм Git тражи акредитиве за ову везу, али ће нам кеш акредитива омогућити да онај корак прескочимо у наредним захтевима.

Fusion конфигурација

Када инсталирате програм Git Fusion, пожелећете да измените конфигурацију. Ово је у суштини прилично лако употребом вашег омиљеног Перфорс клијента; једноставно мапирајте //.git-fusion директоријум на Перфорс серверу у свој радни простор. Структура фајлова изгледа овако:

$ tree
.
├── objects
│   ├── repos
│   │   └── [...]
│   └── trees
│       └── [...]
│
├── p4gf_config
├── repos
│   └── Talkhouse
│       └── p4gf_config
└── users
    └── p4gf_usermap

498 directories, 287 files

Директоријум objects интерно користи програм Git Fusion да мапира Перфорс објекте у Гит и обрнуто, нема потребе да се тамо петљате са било чиме. У овом директоријуму постоји глобални p4gf_config фајл, као и по један са сваки репозиторијум – ово су конфигурациони фајлови који одређују како се програм Git Fusion понаша. Хајде да погледамо фајл у корену:

[repo-creation]
charset = utf8

[git-to-perforce]
change-owner = author
enable-git-branch-creation = yes
enable-swarm-reviews = yes
enable-git-merge-commits = yes
enable-git-submodules = yes
preflight-commit = none
ignore-author-permissions = no
read-permission-check = none
git-merge-avoidance-after-change-num = 12107

[perforce-to-git]
http-url = none
ssh-url = none

[@features]
imports = False
chunked-push = False
matrix2 = False
parallel-push = False

[authentication]
email-case-sensitivity = no

Овде нећемо улазити у значење ових заставица, али приметите да је ово само текстуални фајл у INI формату, сличан ономе који и програм Гит користи за конфигурацију. Овај фајл наводи глобалне опције које затим могу да се преиначе у конфигурационим фајловима одређеног репозиторијума, као што је repos/Talkhouse/p4gf_config. Ако отворите овај фајл, видећете [@repo] одељак са неким подешавањима која се разликују од глобалних подразумеваних. Такође чете видети и одељак који изгледа овако:

[Talkhouse-master]
git-branch-name = master
view = //depot/Talkhouse/main-dev/... ...

Ово је мапирање између Перфорс гране и Гит гране. Име одељка може бити произвољно, докле год је јединствено. git-branch-name вам омогућава да конвертујете путању депоа која би била незгодна за употребу у програму Гит на неко згодније име. Поставка view контролише како се Перфорс фајлови мапирају у Гит репозиторијум, користећи стандардну синтаксу мапирања погледа. Може да се наведе више од једног мапирања, као у следећем примеру:

[multi-project-mapping]
git-branch-name = master
view = //depot/project1/main/... project1/...
       //depot/project2/mainline/... project2/...

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

Последњи фајл о коме ћемо причати је users/p4gf_usermap који мапира Перфорс кориснике на Гит кориснике и који вам можда никада неће бити ни потребан. Када се Перфорс скуп измена конвертује у Гит комит, подразумевано понашање програма Git Fusion је да потражи Перфорс корисника и употреби тамо сачувану имејл адресу и пуно име за поље аутор/комитер у програму Гит. Када се конвертује у другу страну, подразумевано се претражује Перфорс корисник са имејл адресом сачуваном у Гит пољу аутор комита, па се скуп измена подноси као тај корисник (уз примену дозвола). У већини случајева, ово понашање је сасвим у реду, али размотрите следећи фајл мапирања:

john john@example.com "John Doe"
john johnny@appleseed.net "John Doe"
bob employeeX@example.com "Anon X. Mouse"
joe employeeY@example.com "Anon Y. Mouse"

Свака линија је у формату <корисник> <имејл> "<пуно име>", и креира једно мапирање корисника. Прве две линије мапирају две различите имејл адресе у исти Перфорс кориснички налог. Ово је корисно ако сте креирали Гит комитове користећи неколико различитих имејл адреса (или променили имејл адресе), али желите да се све мапирају у истог Перфорс корисника. Када се из Перфорс скупа измена креира Гит комит, прва линија која се подудара са Перфорс корисником ће се употребити за Гит информације о ауторству комита.

Последње две линије маскирају стварна имена и имејл адресе Боба и Џоа у креираним Гит комитовима. Ово је лепо ако желите да отворите кôд неког интерног пројекта, али не желите да целом свету објавите свој директоријум запослених. Приметите да би имејл адресе и пуна имена требало да буду јединствени, осим ако не желите да се Гит комитови приписују једном фиктивном аутору.

Процес рада

Перфорс Git Fusion је двосмерни мост између Перфорс и Гит контроле верзија. Хајде да погледамо како изгледа рад са Гит стране. Претпоставићемо да смо мапирали „Jam” пројекат користећи конфигурациони фајл као што је показано изнад и који можемо да клонирамо на следећи начин:

$ git clone https://10.0.1.254/Jam
Cloning into 'Jam'...
Username for 'https://10.0.1.254': john
Password for 'https://ben@10.0.1.254':
remote: Counting objects: 2070, done.
remote: Compressing objects: 100% (1704/1704), done.
Receiving objects: 100% (2070/2070), 1.21 MiB | 0 bytes/s, done.
remote: Total 2070 (delta 1242), reused 0 (delta 0)
Resolving deltas: 100% (1242/1242), done.
Checking connectivity... done.
$ git branch -a
* master
  remotes/origin/HEAD -> origin/master
  remotes/origin/master
  remotes/origin/rel2.1
$ git log --oneline --decorate --graph --all
* 0a38c33 (origin/rel2.1) Create Jam 2.1 release branch.
| * d254865 (HEAD, origin/master, origin/HEAD, master) Upgrade to latest metrowerks on Beos -- the Intel one.
| * bd2f54a Put in fix for jam's NT handle leak.
| * c0f29e7 Fix URL in a jam doc
| * cc644ac Radstone's lynx port.
[...]

Када по први пут урадите ово, може да потраје. Оно што се дешава је да Git Fusion конвертује све примењиве скупове измена из Перфорс Историје у Гит комитове. Ово се ради локално на серверу, тако да је релативно брзо, али ако имате доста историје, ипак ће потрајати. Наредна преузимања врше инкременталну конверзију, тако да ће личити на природну Гит брзину.

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

# ...
$ git log --oneline --decorate --graph --all
* cfd46ab (HEAD, master) Add documentation for new feature
* a730d77 Whitespace
* d254865 (origin/master, origin/HEAD) Upgrade to latest metrowerks on Beos -- the Intel one.
* bd2f54a Put in fix for jam's NT handle leak.
[...]

Имамо два нова комита. Хајде сада да видимо да ли је још неко радио:

$ git fetch
remote: Counting objects: 5, done.
remote: Compressing objects: 100% (3/3), done.
remote: Total 3 (delta 2), reused 0 (delta 0)
Unpacking objects: 100% (3/3), done.
From https://10.0.1.254/Jam
   d254865..6afeb15  master     -> origin/master
$ git log --oneline --decorate --graph --all
* 6afeb15 (origin/master, origin/HEAD) Update copyright
| * cfd46ab (HEAD, master) Add documentation for new feature
| * a730d77 Whitespace
|/
* d254865 Upgrade to latest metrowerks on Beos -- the Intel one.
* bd2f54a Put in fix for jam's NT handle leak.
[...]

Изгледа да јесте! Не бисте то знали из овог погледа, али 6afeb15 је уствари креиран Перфорс клијентом. Изгледа као још један комит из перспективе програма Гит, што и јесте поента. Хајде да видимо како се Перфорс сервер носи са комитом спајања:

$ git merge origin/master
Auto-merging README
Merge made by the 'recursive' strategy.
 README | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
$ git push
Counting objects: 9, done.
Delta compression using up to 8 threads.
Compressing objects: 100% (9/9), done.
Writing objects: 100% (9/9), 917 bytes | 0 bytes/s, done.
Total 9 (delta 6), reused 0 (delta 0)
remote: Perforce: 100% (3/3) Loading commit tree into memory...
remote: Perforce: 100% (5/5) Finding child commits...
remote: Perforce: Running git fast-export...
remote: Perforce: 100% (3/3) Checking commits...
remote: Processing will continue even if connection is closed.
remote: Perforce: 100% (3/3) Copying changelists...
remote: Perforce: Submitting new Git commit objects to Perforce: 4
To https://10.0.1.254/Jam
   6afeb15..89cba2b  master -> master

Програм Гит сматра да је све прошло успешно. Хајде да погледамо историју README фајла из перспективе програма Перфорс, користећи граф ревизија могућност команде p4v:

Перфорс граф ревизија као резултат извршења Гит команде push
Слика 146. Перфорс граф ревизија као резултат извршења Гит команде push

Ако овај поглед раније нисте видело, може вас донекле збунити, али он приказује исти концепт као и графички приказ Гит историје. Посматрамо историју README фајла, тако да стабло директоријума горе лево приказује само тај фајл како се појављује у разним гранама. Горе десно имамо визуелни граф веза између различитих ревизија, а доле десно приказ овог графа у целости. Остатак погледа приказује детаље изабране ревизије (у овом случају 2).

Једна ствар коју треба приметити је да граф изгледа потпуно исто као онај из Гит историје. Перфорс није имао именоване гране у које да смести комитове 1 и 2, па је креирао грану „anonymous” у .git-fusion директоријуму и сместио их у њу. Ово ђе се десити и именованим Гит гранама које не одговарају именованој Перфорс грани (а касније можете да их мапирате у Перфорс грану помоћу конфигурационог фајла).

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

Git-Fusion резиме

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

Ако администратора свог сервера не можете убедити да постави Git Fusion, и даље постоји начин да ова два алата користите заједно.

Git-p4

Git-p4 је двосмерни мост између програма Гит и Перфорс. Потпуно се извршава у вашем Гит репозиторијуму, тако да вам не треба никакав приступ Перфорс серверу (осим корисничких акредитива, наравно). Git-p4 није тако флексибилно или комплетно решење као Git Fusion, али омогућава да урадите већину онога што бисте желели да урадите, а да не залазите у окружење сервера.

Белешка

Да бисте радили са git-p4, потребно је да негде на PATH имате алат p4. У време писања, он је слободно доступан на адреси http://www.perforce.com/downloads/Perforce/20-User.

Подешавање

У сврху примера, извршаваћемо Перфорс сервер из Git Fusion OVA (виртуелне машине) као што је приказано изнад, али ћемо прескочити Git Fusion сервер и директно прећи на Перфорс контролу верзија.

Да бисте користили p4 клијента из командне линије (од којег git-p4 зависи), потребно је да поставите неколико променљивих окружења:

$ export P4PORT=10.0.1.254:1666
$ export P4USER=john
Први кораци

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

$ git p4 clone //depot/www/live www-shallow
Importing from //depot/www/live into www-shallow
Initialized empty Git repository in /private/tmp/www-shallow/.git/
Doing initial import of //depot/www/live/ from revision #head into refs/remotes/p4/master

Ово креира оно што се у Гит терминологији назива „shallow” (плитки) клон; у Гит се увози само најновија Перфорс ревизија; упамтите, програм Перфорс није дизајниран тако да сваком кориснику достави сваку ревизију. Ово је довољно да се програм Гит користи као Перфорс клијент, али за остале сврхе није довољно.

Када се заврши, имамо потпуно функционални Гит репозиторијум:

$ cd myproject
$ git log --oneline --all --graph --decorate
* 70eaf78 (HEAD, p4/master, p4/HEAD, master) Initial import of //depot/www/live/ from the state at revision #head

Приметите да за Перфорс сервер постоји „p4” удаљени репозиторијум, али све остало изгледа као стандардни клон. То уствари и није тачно, јер тамо заправо нема никаквог удаљеног репозиторијума.

$ git remote -v

У овом репозиторијуму нема ниједног удаљеног репозиторијума. Git-p4 је креирао неке референце које представљају стање сервера и команди git log оне изгледају као удаљене референце, али њима не управља сам програм Гит и не можете да гурнете на њих.

Процес рада

У реду, хајде да одрадимо неки посао. Претпоставимо да сте постигли неки напредак на веома важној могућности и спремни сте да их покажете остатку свог тима.

$ git log --oneline --all --graph --decorate
* 018467c (HEAD, master) Change page title
* c0fb617 Update link
* 70eaf78 (p4/master, p4/HEAD) Initial import of //depot/www/live/ from the state at revision #head

Направили смо два нова комита које желимо да проследимо Перфорс серверу. Хајде да проверимо да ли је још неко радио данас:

$ git p4 sync
git p4 sync
Performing incremental import into refs/remotes/p4/master git branch
Depot paths: //depot/www/live/
Import destination: refs/remotes/p4/master
Importing revision 12142 (100%)
$ git log --oneline --all --graph --decorate
* 75cd059 (p4/master, p4/HEAD) Update copyright
| * 018467c (HEAD, master) Change page title
| * c0fb617 Update link
|/
* 70eaf78 Initial import of //depot/www/live/ from the state at revision #head

Изгледа као да се се измене и master и p4/master разишли. Систем грана програма Перфорс уопште не личи на систем програма Гит, тако да достављање комитова спајања нема никаквог смисла. Git-p4 препоручује да ребазирате своје комитове, па чак обезбеђује и пречицу за то:

$ git p4 rebase
Performing incremental import into refs/remotes/p4/master git branch
Depot paths: //depot/www/live/
No changes to import!
Rebasing the current branch onto remotes/p4/master
First, rewinding head to replay your work on top of it...
Applying: Update link
Applying: Change page title
 index.html | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

Вероватно можете видети у излазу, git p4 rebase је пречица за git p4 sync иза које следи git rebase p4/master. У суштини је мало паметније од тога, посебно када се ради са више грана, али ово је добра апроксимација.

Сада је наша историја поново линеарна, па смо спремни да измене допринесемо назад на Перфорс. Команда git p4 submit ће покушати да креира нову Перфорс ревизију за сваки Гит комит између p4/master и master. Када је покренете прелазите у свој омиљени едитор и садржај фајла који вам се приказује изгледа отприлике овако:

# A Perforce Change Specification.
#
#  Change:      The change number. 'new' on a new changelist.
#  Date:        The date this specification was last modified.
#  Client:      The client on which the changelist was created.  Read-only.
#  User:        The user who created the changelist.
#  Status:      Either 'pending' or 'submitted'. Read-only.
#  Type:        Either 'public' or 'restricted'. Default is 'public'.
#  Description: Comments about the changelist.  Required.
#  Jobs:        What opened jobs are to be closed by this changelist.
#               You may delete jobs from this list.  (New changelists only.)
#  Files:       What opened files from the default changelist are to be added
#               to this changelist.  You may delete files from this list.
#               (New changelists only.)

Change:  new

Client:  john_bens-mbp_8487

User: john

Status:  new

Description:
   Update link

Files:
   //depot/www/live/index.html   # edit


######## git author ben@straub.cc does not match your p4 account.
######## Use option --preserve-user to modify authorship.
######## Variable git-p4.skipUserNameCheck hides this message.
######## everything below this line is just the diff #######
--- //depot/www/live/index.html  2014-08-31 18:26:05.000000000 0000
+++ /Users/ben/john_bens-mbp_8487/john_bens-mbp_8487/depot/www/live/index.html   2014-08-31 18:26:05.000000000 0000
@@ -60,7 +60,7 @@
 </td>
 <td valign=top>
 Source and documentation for
-<a href="http://www.perforce.com/jam/jam.html">
+<a href="jam.html">
 Jam/MR</a>,
 a software build tool.
 </td>

Ово је углавном исти садржај који бисте видели и да извршите p4 submit, осим дела на крају који је git-p4 згодно убацио. Када треба да достави име за комит или скуп измена Git-p4 покушава да поштује појединачно ваша Гит и Перфорс подешавања, али у неким случајевима бисте то пожелели да преиначите. На пример, ако је Гит комит који увозите написао сарадник који нема Перфорс кориснички налог, ипак желите да крајњи скуп измена изгледа тако да га је написала та особа (а не ви).

Git-p4 је корисно увезао поруку из Гит комита као садржај овог Перфорс скупа измена, па све што је потребно да се уради јесте да фајл сачувамо и напустимо едитор, двапут (по једном за сваки комит). Коначни излаз у љуски ће изгледати слично следћем:

$ git p4 submit
Perforce checkout for depot path //depot/www/live/ located at /Users/ben/john_bens-mbp_8487/john_bens-mbp_8487/depot/www/live/
Synchronizing p4 checkout...
... - file(s) up-to-date.
Applying dbac45b Update link
//depot/www/live/index.html#4 - opened for edit
Change 12143 created with 1 open file(s).
Submitting change 12143.
Locking 1 files ...
edit //depot/www/live/index.html#5
Change 12143 submitted.
Applying 905ec6a Change page title
//depot/www/live/index.html#5 - opened for edit
Change 12144 created with 1 open file(s).
Submitting change 12144.
Locking 1 files ...
edit //depot/www/live/index.html#6
Change 12144 submitted.
All commits applied!
Performing incremental import into refs/remotes/p4/master git branch
Depot paths: //depot/www/live/
Import destination: refs/remotes/p4/master
Importing revision 12144 (100%)
Rebasing the current branch onto remotes/p4/master
First, rewinding head to replay your work on top of it...
$ git log --oneline --all --graph --decorate
* 775a46f (HEAD, p4/master, p4/HEAD, master) Change page title
* 05f1ade Update link
* 75cd059 Update copyright
* 70eaf78 Initial import of //depot/www/live/ from the state at revision #head

Резултат је исти као да смо само извршили git push, што и јесте најприближнија аналогија ономе што се заиста одиграло.

Приметите да се током овог процеса сваки Гит комит претворио у Перфорс скуп измена; ако желите да их згњечите у један једини скуп измена, урадите то интерактивним ребазирањем пре него што извршите git p4 submit. Такође приметите да су се SHA-1 хешеви свих комитова који су достављени као скупови измена променили; то је зато што git-p4 додаје линију на крај сваког комита који конвертује:

$ git log -1
commit 775a46f630d8b46535fc9983cf3ebe6b9aa53145
Author: John Doe <john@example.com>
Date:   Sun Aug 31 10:31:44 2014 -0800

    Change page title

    [git-p4: depot-paths = "//depot/www/live/": change = 12144]

Шта се дешава ако покушате да доставите комит спајања? Хајде да пробамо. Ево ситуације у којој смо се нашли:

$ git log --oneline --all --graph --decorate
* 3be6fd8 (HEAD, master) Correct email address
*   1dcbf21 Merge remote-tracking branch 'p4/master'
|\
| * c4689fc (p4/master, p4/HEAD) Grammar fix
* | cbacd0a Table borders: yes please
* | b4959b6 Trademark
|/
* 775a46f Change page title
* 05f1ade Update link
* 75cd059 Update copyright
* 70eaf78 Initial import of //depot/www/live/ from the state at revision #head

Гит и Перфорс историје су се разишле након 775a46f. Гит страна има два комита, па затим комит спајања са Перфорс главом, затим још један комит. Покушаћемо да их доставимо као један једини скуп измена на Перфорс страну. Хајде да видимо шта би се догодило ако сада покушамо да доставимо:

$ git p4 submit -n
Perforce checkout for depot path //depot/www/live/ located at /Users/ben/john_bens-mbp_8487/john_bens-mbp_8487/depot/www/live/
Would synchronize p4 checkout in /Users/ben/john_bens-mbp_8487/john_bens-mbp_8487/depot/www/live/
Would apply
  b4959b6 Trademark
  cbacd0a Table borders: yes please
  3be6fd8 Correct email address

Заставица -n је скраћеница за --dry-run, а то покушава да извести шта би се догодило ако би се команда достављања заиста извршила. У овом случају изгледа да би се креирала три Перфорс скупа измена, што се подудара са три комитова који нису спајање и који још увек не постоје на Перфорс серверу. То звучи управо као оно што желимо, па хајде да видимо како ће да испадне:

$ git p4 submit
[…]
$ git log --oneline --all --graph --decorate
* dadbd89 (HEAD, p4/master, p4/HEAD, master) Correct email address
* 1b79a80 Table borders: yes please
* 0097235 Trademark
* c4689fc Grammar fix
* 775a46f Change page title
* 05f1ade Update link
* 75cd059 Update copyright
* 70eaf78 Initial import of //depot/www/live/ from the state at revision #head

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

Гранање

Ако ваш Перфорс пројекат има више грана, ипак имате среће; git-p4 то може да обради на начин да којим се чини као да је природно у програму Гит. Рецимо да је ваш Перфорс депо постављен на следећи начин:

//depot
  └── project
      ├── main
      └── dev

И рецимо да имате dev грану која поседује следећу спецификацију погледа:

//depot/project/main/... //depot/project/dev/...

Git-p4 може аутоматски да детектује такву ситуацију и уради одговарајућу ствар:

$ git p4 clone --detect-branches //depot/project@all
Importing from //depot/project@all into project
Initialized empty Git repository in /private/tmp/project/.git/
Importing revision 20 (50%)
    Importing new branch project/dev

    Resuming with change 20
Importing revision 22 (100%)
Updated branches: main dev
$ cd project; git log --oneline --all --graph --decorate
* eae77ae (HEAD, p4/master, p4/HEAD, master) main
| * 10d55fb (p4/project/dev) dev
| * a43cfae Populate //depot/project/main/... //depot/project/dev/....
|/
* 2b83451 Project init

Приметите спецификатор „@all” у путањи депоа; он говори git-p4 да клонира не само последњи скуп измена за то подстабло, већ и све скупове измена које су икада дотакле те путање. То је приближније концепту клонирања у програму Гит, али ако радите на пројекту са дугачком историјом, могло би да потраје.

Заставица --detect-branches налаже да git-p4 искористи Перфорс спецификације гране за мапирање грана у Гит референце. Ако се ова мапирања не налазе на Перфорс серверу (што је савршено исправан начин да се користи Перфорс), можете сами навести git-p4 мапирања грана, па добијате исти резултат:

$ git init project
Initialized empty Git repository in /tmp/project/.git/
$ cd project
$ git config git-p4.branchList main:dev
$ git clone --detect-branches //depot/project@all .

Постављање git-p4.branchList конфигурационе променљиве на main:dev говори команди git-p4 да су и „main” и „dev” гране, као и да је друга дете прве.

Ако сада извршимо git checkout -b dev p4/project/dev и направимо неколико комитова, git-p4 је довољно паметна да циља на праву грану када извршимо git p4 submit. Нажалост, git-p4 не може да меша плитке клонове и вишеструке гране; ако имате огроман пројекат и желите да радите на више од једне гране, мораћете да извршите git p4 clone по једном за сваку грану на коју желите да достављате измене.

За креирање или интегрисање грана мораћете да користите Перфорс клијент. Git-p4 може само да синхронизује и доставља на постојеће гране и то само као један линеарни скуп измена одједном. Ако у програму Гит спојите две гране и покушате да доставите нови скуп измена, све што ће се забележити биће гомила измена над фајловима; изгубиће се сви метаподаци о гранама које су умешане у интеграцију.

Гит и Перфорс резиме

Git-p4 омогућава да се са Перфорс сервером употребљава Гит процес рада, и прилично је добра у томе. Међутим, важно је упамтити да је Перфорс управља изворним кодом, а ви програм Гит користите само за рад у локалу. Само будите врло пажљиви са дељењем Гит комитова; ако имате удаљени репозиторијум који користе и други људи, не гурајте било које комитове који већ нису достављени Перфорс серверу.

Ако желите да слободно мешате упторебу програма Перфорс и програма Гит као клијената за контролу изворног кода, а администратора сервера можете убедити да га инсталира, Git Fusion чини да Гит постане првокласни клијент Перфорс сервера за контролу верзија.