Ghidul Mercurial pentru crearea de sucursale - note tehnice

Recent, m-am așezat pe canalele și irc #bitbucket #mercurial pe Freenode și am observat că de multe ori apare întrebarea „decât crearea de filiale în diferite Mercurial de git?»







Cu ceva timp în urmă pe Twitter am discutat cu Nick (Nick Quaranto) ramificare model Mercurial și git'e, ceea ce a dus în cele din urmă într-o notă rapidă despre diferențele principale. Am arătat această notă utilizatorilor, și se pare că le-a plăcut. Am decis să acorde mai multă atenție problemei.

Notă: această postare nu pretinde că este un ghid al utilizatorilor pentru comenzi din Mercurial. Acest manual descrie doar conceptul care se găsește în Mercurial pentru folosirea crengilor. Dacă sunteți în căutarea unei descrieri a comenzilor specifice, citiți manualul excelent numit hg book (și, dacă doriți, puteți cumpăra chiar și o versiune pe hârtie și să vedeți cea mai mare experiență din istoria imprimării).

În primul rând, să examinăm exemplul depozitului pe care l-am pregătit:

Ghidul Mercurial pentru crearea de sucursale - note tehnice

Depozitul este situat în director

/ src / test-project. Conține 3 modificări: 0, 1 și 2.

Notă pentru utilizatorii git: fiecare set de modificări în Mercurial are un identificator sub forma unui hash, ca în git. În plus, în Mercurial toate schimbările pentru confort au mai multe și mai multe numere. Această numerotare nu este globală pentru toate clonele repository, dar este definită în fiecare repository locală specifică, în funcție de secvența de tragere / împingere mai devreme.

În mod implicit, Mercurial are o singură ramură numită "implicită", dar vom reveni la acest punct mai târziu. Am mentionat ramura "default" acum, pentru ca în diagrama de mai sus există un marker corespunzător.

Limita punctată în diagrame înseamnă că, de fapt, nu există un obiect pentru un astfel de marker în depozit. Acest nume poate fi folosit pentru a identifica changeset în loc de hashes lungi sau de numere - Mercurial va calcula numărul de revizie în zbor.

În timp ce ignorăm marcatorul "implicit". Am marcat-o special în gri, pentru că pentru discuția actuală nu contează.

Slăbire prin clonare

Cea mai lentă, dar sigură modalitate de a face o nouă ramură în Mercurial este de a face o clonă:
$ cd

/ src
$ hg clone test-project test-project-feature-branch

Acum avem 2 copii ale depozitului. Să încercăm să facem schimbări în fiecare:

Ghidul Mercurial pentru crearea de sucursale - note tehnice

Deci, avem două copii ale repozitorului, fiecare dintre ele conținând modificări la momentul clonării. În plus, putem face un angajament pentru fiecare dintre exemplare în mod independent. Apoi, dacă, de exemplu, faceți un impuls din proiectul de testare în test-project-feature-branch, apoi changeset "Fix un bug critic" va cădea în copia dreaptă.

Notă pentru utilizatorii git: amintiți-vă că am spus că numerotarea changeset'ov în Mercurial este locală? Acest exemplu arată în mod clar: două changeset'a diferite două arhive au numărul 3. Acesta este motivul pentru care numerele funcționează mai bine decât într-un singur depozit, și pentru a sincroniza trage / împinge și atunci când se ocupă cu alte persoane, ar trebui să utilizați un hash - acestea sunt unice.

demnitate

Clonarea este o modalitate foarte sigură de a crea ramuri. Cele două depozite sunt absolut independente una de cealaltă și sunt sincronizate prin tragere / împingere. Nu există nici un pericol de a sparge ceva într-o ramură în timp ce lucrați pe celălalt.

Pentru a șterge o ramură dacă nu mai este nevoie, această abordare este foarte ușoară: rm -rf test-project-feature-branch. Nu este nevoie să vă împrăștiați cu depozitul, eliminând ceva din poveste.

deficiențe

Crearea ramurilor prin clone locale este mai lentă decât alte metode. Dar dacă sistemul dvs. de operare suportă hardlink-uri, Mercurial le folosește și în acest caz clonarea nu ar trebui să fie prea lentă.

Cu toate acestea, ramificarea prin clonare poate încetini semnificativ evoluția echipei. Dacă publicați două filiale ca două depozite separate (de exemplu, stabil și versiunea 2), aceasta înseamnă că ceilalți participanți vor trebui să descarce separat depozitul, dacă doresc să aibă ambele filiale. Acest lucru poate dura mult timp cu depozite mari și cu un canal de comunicare îngust.

Dar există o modalitate de a evita traficul inutil, a fost descris de Guido Ostkamp și timeless_mbp pe canalul #mercurial. Ideea este clonarea unei singure ramuri de pe server și apoi tragerea tuturor celorlalte la cea deja disponibilă. După aceea, este necesar să împărțiți toate ramurile descărcate dintr-un depozit local în câteva ramuri locale de clone. Astfel, aceleași schimbări nu trebuie să fie pompate de mai multe ori.

Acest exemplu presupune că cunoașteți numerele de revizie (sau hash) ale vârfurilor tuturor ramurilor. Cel mai probabil, nu este așa, așa că trebuie să privească mai întâi în jurnal.

Al doilea fapt, care sugerează acest exemplu: toate sucursalele descărcate au un cap. Dacă există mai multe capete în orice ramură, atunci toate revizuirile lor vor trebui specificate în comanda clone când ramificațiile sunt împărțite în directoare separate.

În unele proiecte există o problemă cu căile spre anumite fișiere. Dacă ați creat o filială a clonelor, va trebui să redenumiți directoarele de fiecare dată când doriți să treceți la o altă ramură. În mod obișnuit, legarea tare la căile din cod nu este adesea, dar se întâmplă.

Personal, nu-mi place această metodă. Cu toate acestea, unii folosesc, în special, la dezvoltarea Mercurialului în sine, un model de clonă-clonă.

Comparație cu git

În acest caz, această abordare este de asemenea aplicabilă. Din punct de vedere tehnic, aceasta este aceeași cu crearea de furcă pe GitHub. Cu toate acestea, atunci când spunem "furculiță" și "ramură", înțelegem încă concepte oarecum diferite.

Succesiune cu marcaje

Următorul mod este să utilizați marcajele. De exemplu:

/ src / test-project
$ hg marcaj principal
Caracteristica $ hg bookmark







Acum aveți două marcaj pentru cele două ramuri viitoare din actualul set de modificări.

Pentru a merge la una dintre ramuri, puteți utiliza funcția de actualizare hg - actualizează directorul de lucru pentru a tipări modificările în ramura de caracteristici și marchează această ramură ca fiind funcțională. Când vă angajați, Mercurial va muta marcajul curent (caracteristică) la setul de modificări nou creat.

Mai multe detalii despre lucrul cu bookmark'ami pot fi citite pe pagina wiki corespunzătoare.

Iată cum va arăta depozitul dacă utilizați marcajul:

Ghidul Mercurial pentru crearea de sucursale - note tehnice

Diagrama este extrem de simplă: ramurile au fost împărțite pe setul de modificări 2 și apoi am adăugat un nou set de modificări la fiecare ramură.

Acum acordați atenție markerilor. "Implicit" este în această diagramă, dar continuăm să o ignorăm.

Două etichete suplimentare sunt un marcaj. Ați observat că acestea nu sunt reprezentate de o linie punctată? Fiecare marcaj este un obiect real pe disc, nu un link virtual!

Numele lor pot fi utilizate ca indicatori pentru numerele de revizie specifice atunci când lucrează cu Mercurial.

demnitate

Bookmark'i vă oferă o modalitate rapidă și ușoară de a da nume sucursalelor.

Puteți să le ștergeți dacă nu mai sunt necesare. De exemplu, dacă lucrările privind noile funcții au fost finalizate și am fuzionat modificările în ramura principală, nu mai trebuie să stocăm marcajul "caracteristică".

deficiențe

Înainte de versiunea lui Mercurial 1.6, marcajele nu au fost sincronizate între arhive (pull / push). Trebuiau să fie transferate manual ca fișiere.

Comparație cu git

Brancharea cu ajutorul marcajelor este foarte asemănătoare cu ramurile uzuale din git. Bookmark'i în Mercurial ca git refs: un pointer numit la changeset, care se mișcă împreună cu fiecare comitet nou.

Singura diferență mare până de curând (înainte de Mercurial 1.6) a fost aceea că git refs s-au sincronizat între depozite prin tragere / împingere și marcajul nu există în Mercurial.

Brancharea cu ramuri denumite

Al treilea mod de a crea o sucursală în Mercurial este de a utiliza așa-numitele ramuri denumite (denumite în continuare cuvântul „ramura“ Eu numesc conceptul de separare a codului în procesul de programare, iar ramura cuvânt - tehnologie specifică în Mercurial -.. Aprox interpret).

Pentru a crea o ramură numită:
$ cd

/ src / test-project
$ hg branch feature

Fiecare nou set de modificări va aparține aceleiași sucursale numite ca strămoșul său. Pentru a schimba ramura numită pentru modificările ulterioare, trebuie să folosiți din nou comanda hg branch

Iată cum va arăta depozitul nostru atunci când folosiți ramificațiile numite:

Ghidul Mercurial pentru crearea de sucursale - note tehnice

O diferență importantă a acestei metode este aceea că numele ramurii este scris direct în meta date ale setului de modificări (aceasta se vede în setul de modificări 4 din diagramă).

În mod implicit, există o ramură numită "implicită", dar numele său este ascuns când se afișează jurnalele, cu excepția cazului în care o solicitați explicit într-o anumită comandă cu opțiunea -v (-verbose).

Este timpul să explicați magia acestor etichete cu o margine întreruptă pe diagramă. Folosind numele ramurii, specificăm așa-numitul set de modificări a vârfului din această ramură numită. În acest exemplu:

  • Executați hg update default. vom actualiza directorul de lucru la changeset 3, care este vârful în ramura "implicită".
  • După ce a executat caracteristica de actualizare hg. vom actualiza directorul de lucru la changeset 4, care este un sfat în ramura "caracteristică".

Niciuna dintre aceste etichete nu este punctată fizic pe disc (spre deosebire de marcajele discutate mai devreme). Când se numește numit ramură Mercurial calculează numărul de revizie în zbor.

demnitate

Cel mai mare avantaj al utilizării numelor ramificate este că fiecare set de modificări stochează informații despre ramificația numită în metadatele sale, ceea ce este foarte convenabil, mai ales atunci când se utilizează graficlog.

deficiențe

Mulți oameni nu le place să strice metadatele cu nume de sucursale, în special pentru ramuri mici care se îmbină rapid cu ramura principală.

În trecut, Mercurial a avut o problemă cu faptul că sucursalele nu puteau fi "închise". Aceasta înseamnă că, în timp, lista sucursalelor numite ar putea crește semnificativ. De la Mercurial 1.2, a apărut opțiunea -close-branch pentru comanda hg commit.

Comparație cu git

Din câte știu, în git nu există nici un echivalent de ramuri numite de la Mercurial. Informațiile din ramificație nu sunt stocate niciodată în metadatele setului de modificări.

Sucuri anonime

Ultima metodă de creare a unor ramuri în Mercurial, pe care o vom acoperi, este cea mai rapidă și mai ușoară: actualizarea oricărei revizuiri și a unei comiteri. Nu este nevoie să vă gândiți la nume sau la alte acțiuni suplimentare, doar să actualizați și să vă angajați!

Mecanica este după cum urmează: atunci când faceți o actualizare pentru o anumită revizuire, această revizuire este marcată ca părinte pentru directorul de lucru. Când comiteți, setul de modificări creat la acel moment devine copilul aceleiași revizii care este părintele directorului de lucru.

Să ne angajăm să reparăm sacul critic, apoi să ne întoarcem la revizia 2, iar altul să ne angajeze "Adăugați o nouă caracteristică":

Ghidul Mercurial pentru crearea de sucursale - note tehnice

Cum să comutați între aceste ramuri? Pentru a face acest lucru, utilizați ultimul număr de revizie din ramură ca indicatorul de ramură: hg update -check (-check poate fi scurtat la -c).

Notă: opțiunea -check a apărut în Mercurial 1.3, dar nu a funcționat. Într-adevăr, a funcționat de la versiunea 1.3.1. Dacă aveți o versiune anterioară de Mercurial, vă recomandăm să faceți upgrade.

Comenzi precum hg log și hg graphlog vor afișa toate modificările din depozit, așa că nu vă fie frică să pierdeți numărul ramurii anonime. În plus, există o comandă hg capete, care arată toate capetele (de fapt, aceasta este ramuri anonime).

demnitate

Acesta este cel mai simplu mod de a crea sucursale. Nu vă mai puteți face griji cu privire la numele ramurilor sau la închiderea / ștergerea acestora.

Această metodă este ideală pentru fixări rapide, care constau în două sau trei schimbări în ramură.

deficiențe

A doua consecință a anonimatului este că trebuie să vă referiți la sucursale prin numere de revizie sau hash, care trebuie mai întâi să fie găsite cu hg log sau hg graphlog (sau hg heads). Dacă de multe ori trebuie să comutați între ramuri, acest lucru poate fi dificil.

Comparație cu git

În git, această metodă nu funcționează. Desigur, puteți să faceți o actualizare și să vă angajați oriunde, dar dacă nu creați un refuz (numit) în acest moment și apoi treceți la o altă ramură, va fi dificil să reveniți la "anonim". Singura modalitate de a găsi este să utilizați grep pe rezultatele jurnalului.

Sunt de acord, uneori, nu există dorința de a gândi un nume pentru o ramură, dacă este o sucursală scurtă pentru o rezolvare momentală a erorilor. Dar în git trebuie să dai un nume noii ramuri. În Mercurial, acest lucru nu este necesar.

O altă diferență între Mercurial și Git

Există o altă mare diferență între Mercurial și Git în problema sucursalei:

Mercurial face push / pull de toate ramurile în mod implicit. Git, pe de altă parte, face să împingă / trage numai ramura curentă.

Acest lucru este foarte important dacă sunteți un utilizator git și doriți să lucrați cu Mercurial. Dacă doriți să sincronizați (pull / apăsare), doar o singură ramură în Mercurial, trebuie să utilizați -rev opțiunea (-r pentru scurt), și specificați revizuirea vârfului (sau o referire la revizuirea de vârf în formă de ramură numită sau marcaj):

$ hg push -rev branchname
$ hg push -rev nume de marcă
$ hg push -rev 4

Dacă specificați o revizuire, Mercurial va trage / împinge această revizuire și toți strămoșii care nu se află în depozitul de destinații.

Clarificare: dacă utilizați modelul "Branching by Cloning", pull / push nu va putea trimite toate ramificațiile, deoarece clonele ramură sunt depozite izolate și sunt în diferite directoare.

concluzie

Sper că acest ghid a fost util. Dacă observați ceva ce mi-a ratat, mai ales în descrierea comportamentului git (nu folosesc eu singur, doar dacă trebuie) sau aveți orice întrebări - scrieți!

În secțiunea "Sucuri anonime", reparați "Fixați sacul critic" la "Remediați o eroare critică" pentru a se potrivi imaginii.

De asemenea, un subiect puțin, dar în Git, nu există nicio problemă specială de a avea acces la "ramura anonimă", deoarece depozitul obișnuit Git rulează așa-numitul. "Reflog" este un jurnal de schimbări globale în care puteți vedea toate comitetele, inclusiv comitetele făcute în statul "detașat" (analog al unei sucursale anonime în Hg). În plus, după schimbarea ramurii vârfului liniei istorice de la care a fost efectuată tranziția, este disponibil sub numele ORIG_HEAD.

Multumesc pentru articol: Nu folosesc Hg, dar mă interesează întrebarea, iar postul a reușit să clarifice multe.







Trimiteți-le prietenilor: