Git ir Mercurial - palyginimas ir kontrastas

Jau kurį laiką naudoju savo asmeninius projektus.

Vis daugiau ir daugiau girdžiu apie „Git“ ir „Mercurial“ bei DVCS.

Norėčiau, kad visa DVCS būtų sūkurinė, bet nesu labai susipažinęs su jokia galimybe.

Kokie yra skirtumai tarp gyvsidabrio ir gito?

Atkreipkite dėmesį, kad nesistengiu išsiaiškinti, kuris iš jų yra „geriausias“ ar net koks turėčiau pradėti. Aš daugiausia ieško pagrindinių sričių, kuriose jos yra panašios, ir kur jos yra skirtingos, nes man įdomu žinoti, kaip jos skiriasi įgyvendinimo ir filosofijos požiūriu.

506
TM. 21 spalis 2009-10-21 07:46 '09, 07:46, 2009-10-21 07:46
@ 11 atsakymų

Atsakomybės apribojimas: naudoju „Git“, sekite „Git“ „Git“ adresų sąraše ir net prisidedu prie „Git“ (daugiausia „gitweb“). Žinau „Mercurial“ iš dokumentų ir kai kuriuos iš IRC kanalo #revctrl diskusijos apie FreeNode.

Dėkojame visiems žmonėms už #Mercurial IRC kanalą, kuris suteikė Mercurial pagalbą šiam įrašui.



Santrauka

Čia būtų malonu turėti tam tikrą lentelės sintaksę, pavyzdžiui, PHPMarkdown / MultiMarkdown / Maruku Markdown plėtinį

  • Sandėliavimo struktūra: Mercurial neleidžia aštuonkojų susijungimų (su daugiau nei dviem tėvais) ir nepažymi objektų be užrakinimo.
  • Žymos: „ Mercurial“ naudoja .hgtags versijos .hgtags su specialiomis taisyklėmis saugyklų žymėms ir taip pat palaiko vietines žymes .hg/localtags ; „Git“ žymėse nuorodų nuorodos yra refs/tags/ namespace ir automatiškai parenkamos pagal nutylėjimą, kai jos ištraukiamos ir reikalauja aiškaus paspaudimo.
  • Filialai: standartinė Mercurial darbo eiga naudoja anonimines antraštes; „Git“ naudoja šakas su lengvu pavadinimu ir turi specialius filialus (nuotolinio sekimo filialus), kurie seka nuotolinio saugyklos filialus.
  • Pavadinimų ir versijų intervalai: „ Mercurial“ pateikia versijos numerius, vietines saugyklas ir pagrįstus santykinius pokyčius (skaičiuojant nuo patarimo, ty dabartinio filialo) ir šios vietinės numeracijos redagavimo intervalus; „Git“ suteikia būdą nuorodai į peržiūrą, susijusią su šakos galu, ir peržiūros intervalai yra topologiniai (remiantis pakeitimų grafiku).
  • „Mercurial“ naudoja stebėjimo pervadinimą , o „Git“ naudoja pervadinimo apibrėžimą, kad galėtų dirbti su failų pervadinimu.
  • Tinklas: Mercurial palaiko SSH ir HTTP „protingus“ protokolus ir statinį HTTP protokolą; šiuolaikinis „Git“ palaiko SSH, HTTP ir „Git“ protinius protokolus, o HTTP (S) protokolas yra kvailas. Abu turi palaikymą paketų rinkmenoms, skirtoms neprisijungus transportavimui.
  • „Mercurial“ naudoja plėtinius („plugins“) ir įdiegta API; „Git“ turi scenarijų ir nustatytus formatus.

Yra keletas dalykų, kurie skiriasi nuo „Gcu“ nuo „Mercurial“, bet yra ir kitų dalykų, kurie leidžia juos atrodyti panašūs. Abu projektai vieni kitiems skolina idėjas. Pavyzdžiui, „Mercurial“ (anksčiau „bisect“ plėtinys ) „ hg bisect komanda įkvėpė git bisect komandą Git'e, o „ git bundle idėja įkvėpta „ hg bundle .

Sandėliavimo struktūra, versijos išsaugojimas

Objekto duomenų bazėje „Git“ yra keturių tipų objektai: blobobjektai, kuriuose yra failo turinys, hierarchiniai medžio objektai, saugantys katalogų struktūrą, įskaitant failų pavadinimus ir atitinkamas failų leidimų dalis (vykdomieji leidimai failams, kurie yra simbolinė nuoroda), įsipareigojimo objektas kurioje yra informacija apie autorystę, rodyklė į kapinyno būklės vaizdą peržiūros metu, atstovaujama įsipareigojimo (per viršutinio projekto katalogo medžio objektą) ir nuorodų į nulį ar daugiau tėvai ir žymėti objektus, kurie nurodo kitus objektus ir gali būti pasirašyti naudojant PGP / GPG.

„Git“ naudoja du būdus, kaip saugoti objektus: laisvą formatą, kuriame kiekvienas objektas yra saugomas atskirame faile (šie failai yra įrašomi vieną kartą ir niekada nepasikeitė) ir supakuotu formatu, kur daug objektų saugomi delta suspausta į atskirą failą. Operacijų automatiškumą užtikrina tai, kad po objekto rašymo nuoroda į naują objektą yra įrašoma (atominiu būdu, naudojant triuką sukurti + pervardyti).

Saugojimas

„Git“ reikalauja periodinės priežiūros su „ git gc (siekiant sumažinti vietos diske ir pagerinti našumą), nors „Git“ šiuo metu tai daro automatiškai. (Šis metodas užtikrina geresnį saugyklų suspaudimą.)

„Mercurial“ (kaip suprantu) saugo failų istoriją failų žurnale (kartu, manau, su papildomais metaduomenimis, pvz., Stebėjimo pervadinimu ir tam tikra papildoma informacija); ji naudoja plokščią struktūrą, vadinamą manifestu, kad palaikytų katalogų struktūrą ir struktūrą, vadinamą changelog, kurioje saugoma informacija apie pakeitimų rinkinius (pataisymus), įskaitant įsipareigojimo pranešimą ir nulį, vieną arba du tėvus.

„Mercurial“ naudoja operacijų žurnalą, kad užtikrintų, jog operacijos yra atominės ir priklauso nuo sutrumpintų failų, kad būtų išvalytos po nesėkmingo arba nutraukto veikimo. „Revlog“ tik pridėti.

Atsižvelgiant į saugyklų struktūrą „Git“, palyginti su „Mercurial“, galite matyti, kad „Git“ yra labiau panašus į objektų duomenų bazę (arba į turinį orientuotą failų sistemą), o „Mercurial“ yra labiau kaip tradicinė reliacinė duomenų bazė su fiksuotu lauku.

Skirtumai:
„Git“ medžio objektai sudaro hierarchinę struktūrą. ; „Mercurial manifest“ failas turi plokščią struktūrą. „Git“ bloko objekto saugykloje yra viena failo turinio versija ; Visa vieno failo istorija saugoma gyvsidabrio rinkmenoje (jei čia nemanome jokių komplikacijų). Tai reiškia, kad yra skirtingų operacijų sričių, kuriose „Git“ bus greitesnis už „Mercurial“, visi kiti laikomi lygiais (pvz., Sujungiant ar rodant projekto istoriją), taip pat sritys, kuriose „Mercurial“ bus greitesnis nei „Git“ (pvz., Naudojant pleistrus arba rodant vienos istorijos istoriją) failą). Ši problema gali būti svarbi galutiniam vartotojui.

Dėl fiksuoto „Mercurial“ struktūros pakeitimo „Mercurial“ gali būti tik du tėvai ; Įsipareigojimas „Git“ gali turėti daugiau nei du tėvus (vadinamąjį „aštuonkojų susijungimą“). Nors galite (teoriškai) pakeisti aštuonkojus su dviem tėvų susijungimais, tai gali sukelti komplikacijų konvertuojant tarp „Mercurial“ ir „Git“ saugyklas.

Kiek aš žinau, „Mercurial“ neturi „Git“ anotuotų žymų (žymos objektų) ekvivalento. Specialus anotuotų žymų atvejis yra pasirašytos žymos (su PGP / GPG parašu); ekvivalentas „Mercurial“ gali būti atliekamas naudojant „ GpgExtension“ , kurios plėtinys platinamas su „Mercurial“. Negalite pažymėti „blokuojančio“ objekto „Mercurial“, kaip jūs galite, „Git“, bet manau, kad tai nėra labai svarbu (kai kurie „Git“ saugyklos naudoja pažymėtą „blob“, kad platintų PGP viešąjį raktą, skirtą patikrinti pasirašytas žymes).

Nuorodos: filialai ir žymos

„Git“ nuorodos (filialai, nuotoliniai pėdsakai ir žymės) yra už DAG ribų (kaip turėtų būti). Nuorodos refs/heads/ namespace ( vietiniai filialai ) nurodo įsipareigojimą ir paprastai atnaujinamos su „git saistības“; jie nurodo šakos viršūnę (galvą), todėl toks pavadinimas. Nuorodos refs/remotes/<remotename>/ ( nuotolinio stebėjimo filialai ) nurodo, kad nuotolinio saugykloje yra seka, seka filialus <remotename> ir atnaujinama naudojant git fetch arba ekvivalentą. Nuorodos refs/tags/ namespace paprastai nurodo fiksacijas (šviesos žymes) arba žymos objektus (anotuotas ir pasirašytas žymes) ir nėra skirtos keisti.

Žymos

„Mercurial“ galite suteikti nuolatinį peržiūros pavadinimą su žyma ; žymės yra saugomos taip pat, kaip ignoravimo modeliai. Tai reiškia, kad pasauliniu mastu matomos žymos yra saugomos duomenų saugykloje .hgtags faile. Tai turi dvi pasekmes: pirma, „Mercurial“ turi naudoti specialias taisykles, kad šis failas gautų dabartinį visų žymių sąrašą ir atnaujintų tokį failą (pvz., Jis perskaito paskutinę peržiūrėtą failo versiją, o ne šiuo metu patvirtintą versiją); Antra, turite atlikti šio failo pakeitimus, kad naujas žymuo būtų matomas kitiems naudotojams / kitoms saugykloms (kaip suprantu).

„Mercurial“ taip pat palaiko vietos žymes, saugomas hg/localtags , kurios nėra matomos kitiems (ir, žinoma, nėra perkeliamos)

„Git“ žymėse yra (konstantų) pavadinimų nuorodos į kitus objektus (dažniausiai žymos objektus, kurie savo ruožtu nurodo įsipareigojimus), saugomus vardų srityje refs/tags/ . Pagal numatytuosius nustatymus, kai perkate arba spustelėsite pakeitimų rinkinį, „Git“ automatiškai išskleidžia arba stumia žymes, rodančias, kad pasirinksite arba vilkite pataisas. Tačiau tam tikru mastu galite valdyti žymes, kurios yra išgautos arba paspaudžiamos.

„Git“ valdo šviesos žymes (nukreipdamas tiesiogiai į įsipareigojimus) ir anotuotas žymas (nurodydamas žymėti objektus, kuriuose yra žyma, kuri nebūtinai apima PGP parašą, kuris, savo ruožtu, rodo pataisą), šiek tiek skiriasi, pavyzdžiui, pagal numatytuosius nustatymus tik anotuoti žymenys, kai aprašomi įsipareigojimai naudojant „git description“.

„Git“ „Mercurial“ vietinių žymenų atitikmuo nėra griežtas. Tačiau „Git“ rekomendacijose rekomenduojama sukurti atskirą viešą atvirą saugyklą, į kurią spustelėsite paruoštus pakeitimus ir iš kurių kiti būtų klonuojami ir ištraukiami. Tai reiškia, kad žymės (ir filialai), kurių nespaudžiate, yra privačios jūsų saugyklai. Kita vertus, galite naudoti ir kitokią vardų erdvę nei heads , remotes ar tags , pvz., local-tags vietos žymes.

Asmeninė nuomonė :. Mano nuomone, žymos turėtų būti ne peržiūros grafiko ribose, nes jos yra jos išorės ribos (tai rodo pokyčių tvarkaraštį). Žymos neturėtų būti versijos, bet nešiojamos. Gyvsidabrio pasirinkimas, naudojant mechanizmą, panašų į failų ignoravimo mechanizmą, reiškia, kad jis arba turi apdoroti .hgtags konkrečiai (failas medyje yra nešiojamas, bet įprastas variantas) arba turi vietos, kurios yra vietinės ( .hg/localtags nėra versija, bet .hg/localtags ).

Filialai

„Git“ vietinis filialas (filialas ar filialas) yra nuoroda į įsipareigojimą, kuriame galite auginti naujus įsipareigojimus. Filialas taip pat gali reikšti aktyvią plėtros liniją, t.y. Visi tvirtinimai pasiekiami nuo šakos galo. Vietos filialai yra refs/heads/ namespace, pvz., Visas pagrindinio filialo pavadinimas yra refs / heads / master.

Dabartinis filialas „Git“ (reiškia pažymėtą šaką ir šaką, kurioje bus atliktas naujas įsipareigojimas) yra HEAD nurodytas filialas. HEAD galite nukreipti tiesiai į įsipareigojimą, o ne į simbolinę nuorodą; ši padėtis anoniminėje nepažymėtoje šakoje vadinama atjungta HEAD („git filialas“ rodo, kad esate „(be filialo)“).

„Mercurial“ turi anoniminius filialus (šakos filialus) ir galite naudoti žymes ( pratęsiant žymę ). Tokios skirtukų šakos yra grynai vietinės, ir šie pavadinimai (iki 1.6 versijos) nėra nešiojami naudojant „Mercurial“. Galite naudoti rsync arba scp .hg/bookmarks failo .hg/bookmarks kopijavimui į nuotolinę saugyklą. Taip pat galite naudoti hg id -r <bookmark> <url> kad gautumėte dabartinės žymės patarimo peržiūros kodą.

Kadangi 1.6 žymes galima paspausti / rodyti. Puslapyje „ BookmarksExtension “ yra skyrius „ Darbas su nuotoliniais saugyklomis“ . „Mercurial“ žymių skirtumai yra visuotiniai, tuo tarpu „nuotolinio“ sąvokos apibrėžimas „Git“ taip pat apibūdina filialų vardų atvaizdavimą iš nuotolinio saugyklos pavadinimų su vietinės nuotolinio stebėjimo šakų pavadinimais; pvz., refs/heads/*:refs/remotes/origin/* rodymas reiškia, kad nuotolinio saugykloje nuotolinio šaltinio / pagrindinio stebėjimo („refs / nuotolinio valdymo pultai / kilmė / šeimininkas "").

„Mercurial“ taip pat turi vadinamuosius vadinamus filialus, kuriuose filialo pavadinimas yra įterptas į įvykį (pakeitimų rinkinyje). Toks pavadinimas visame pasaulyje (perduodamas, kai gaunamas). Šie filialų pavadinimai yra nuolat registruojami kaip dalis \ t Šiuolaikinio Mercurial pagalba galite uždaryti „pavadintą filialą“ ir nustoti įrašyti filialo pavadinimą. Šiuo atveju filialų galai apskaičiuojami skristi.

Mano nuomone, Mercurial „pavadintos filialai“ turėtų būti vadinamos priskirti etiketes , nes būtent tai yra. Yra situacijų, kai „pavadintas filialas“ gali turėti keletą patarimų (kelis vaikus be įpareigojimų) ir gali sudaryti ir kelios nesuderinamos keitimo grafiko dalys.

„Git“ neturi „Mercurial“ šių „įterptųjų šakų“ ekvivalento; Be to, „Git“ filosofija yra ta, kad nors galima teigti, kad filialas apima tam tikrą fiksaciją, tai nereiškia, kad fiksacija priklauso bet kuriam filialui.

Atkreipkite dėmesį, kad „Mercurial“ dokumentuose vis dar siūloma naudoti atskirus klonus (atskiras saugyklas), bent jau ilgaamžiškiems filialams (atskiras saugyklos darbo eigos filialas) ir taip pat šakoti per klonavimą.

Filialai paspaudimu

„Mercurial“ pagal nutylėjimą spaudžia visas galvutes . Jei norite paspausti vieną šaką ( vieną galvą ), turite nurodyti šakos, kurią norite spustelėti, versijos versiją. Jūs galite nurodyti atsakymo užklausą dėl jos versijos numerio (lokaliai saugykloje), peržiūros identifikatorių, žymės pavadinimą (lokaliai saugykloje, neperduotą) arba integruotą šakos pavadinimą (su filialo pavadinimu).

Kiek aš suprantu, jei spustelėsite keletą pakeitimų, kuriuose yra „Mercurial“ kalba pažymėti „tam tikroje šakoje“, šį „pavadintą filialą“ turėsite saugykloje, kurią spustelėsite. Tai reiškia, kad tokių integruotų filialų („pavadintų filialų“) pavadinimai yra pasauliniai (palyginti su šio saugyklos / projekto klonais).

Pagal numatytuosius nustatymus (atsižvelgiant į „ push.default konfigūracijos parametrą) „git push“ arba „git push < remote >“ „Git“ spustelės atitinkamus filialus , t. tik tie vietiniai filialai, kurių ekvivalentas jau yra nuotolinėje saugykloje, į kurią prisijungėte. Jei norite spustelėti visus filialus , galite naudoti „-it“ parinktį, skirtą „git -push“ („git push -all“), galite naudoti „git push < remote > < branch >“, kad spragtelėtų ant konkretaus filialo , ir galite naudoti „git spauskite < remote > HEAD “, kad pastumtumėte dabartinį filialą .

Visa tai reiškia, kad „Git“ nėra sukonfigūruotas, o filialai spragtelėjo remote.<remotename>.push per konfigūracijos kintamuosius.

Mėginiai

Pastaba: čia naudoju „Git“ terminologiją, kur „parsisiuntimas“ reiškia pakeitimų įkėlimą iš nuotolinio saugyklos, neįtraukiant šių pakeitimų į vietinį darbą. Štai ką git fetch ir hg pull .

Jei teisingai suprantu, „Mercurial“ ištraukia visus skyrius iš nuotolinio saugyklos, tačiau galite nurodyti filialą, kurį norite išgauti „ hg pull --rev <rev> <url> “ arba „ hg pull <url>#<rev> “ į gauti vieną filialą . Galite nurodyti <rev> naudodami peržiūros identifikatorių, pavadinimo „pavadintas filialas“ (šakos, įdėtos į pakeitimo žurnalą) pavadinimą arba žymės pavadinimą. Tačiau žymos pavadinimas (bent jau šiuo metu) neperduodamas. Visi „pavadinti filialai“, kuriuos gaunate, priklauso perdavimui. „hg pull“ saugo šakų galus, kuriuos jis surinko kaip anonimines, nenurodytas galvas.

„Git“, pagal numatytuosius nustatymus („kilmės“ grupei, sukurtai „git klonu“, ir konsolėms, sukurtoms naudojant „git remote add“), „ git fetch “ (arba „ git fetch <remote> “) gauna visus nuotolinio saugyklos filialus (iš refs/heads/ namespace) ir saugo juos refs/remotes/ . Tai reiškia, kad, pavyzdžiui, filialas, pavadintas „kapitonas“ (vardas, pavardė: „refs / heads / master“) nuotoliniame „šaltinyje“ bus išsaugotas (išsaugotas) kaip „kilmės / šeimininko“ nuotolinio stebėjimo filialas (visas pavadinimas: „refs / nuotolinio valdymo pultas / kilmė / kapitonas “).

Jūs galite gauti atskirą filialą „Git“, naudodami „ git fetch <remote> <branch> - „Git“, kad išsaugotumėte prašomus filialus „FETCH_HEAD“, kuris yra panašus į nepatvirtintus „Mercurial“ vadovus.

Tai yra galingų Git refspec sintaksės pavyzdžių pavyzdžiai: su refspecs pagalba galite nurodyti ir / arba konfigūruoti, kuriuos filialus norite gauti ir kur juos saugoti. Pavyzdžiui, pagal nutylėjimą „visų filialų atsiėmimas“ yra simbolis „+ refs / heads / *: refs / remotes / origin / *“, o „fetch single branch“ yra „refs / heads / <branch> ::“ santrumpa. Refspecs naudojami filialų pavadinimams (refs) suderinti nuotoliniame saugykloje su vietinių nuorodų pavadinimais. Tačiau jums nereikia žinoti (daug), kad refspecs gali efektyviai dirbti su „Git“ (daugiausia dėl git nuotolinio valdymo).

Asmeninė nuomonė: aš asmeniškai manau, kad „vardiniai filialai“ (su filialų pavadinimais, įterptais į pokyčių metaduomenis) Mercurial yra klaidingas dizainas su pasauline vardų erdve, ypač paskirstytos versijos valdymo sistemai. ir Bobas turi „pavadintą filialą“, pavadintą jo-joe savo saugyklose, kurių filialai neturi nieko bendro. Tačiau Joe saugykloje šie du filialai būtų žiauriai nagrinėjami kaip vienas filialas. Taigi jūs kažkaip sugalvojote susitarimą apsaugoti filialo pavadinimo konfliktus. Tai nėra problema su Gitu, kur Joe saugyklos filialas „Joe“ iš Alice bus „alice / for-joe“, o iš Bobo bus „bob / for-joe“. Taip pat žiūrėkite, atskirdami filialo pavadinimą iš filialo identifikatoriaus, išleisto Mercurial wiki puslapyje.

„Mercurial“ „etikečių filialuose“ šiuo metu nėra branduolio paskirstymo mechanizmo.

Skirtumai:
Ši sritis yra vienas iš pagrindinių „Mercurial“ ir „Git“ skirtumų, kaip atsakydavo Jemenas Woodyatt ir Steve Losh . „Mercurial“ nustatoma, kad naudojami anoniminiai lengvi kodai, kurie jų terminologijoje vadinami galvomis. „Git“ naudoja lengvus, sušvirkštus filialus, kad atitiktų nuotolinio saugyklos filialų pavadinimus su nuotolinio stebėjimo šakų pavadinimais. Git "заставляет" вас называть ветки (ну, за исключением единственной неназванной ветки, ситуация, называемая отсоединенной HEAD), но я думаю, что это лучше работает с отраслевыми рабочими процессами, такими как рабочий процесс ветки дерева, что означает несколько ветвей в единой парадигме репозитория.

Именование версий

В Git существует много способов переименования версий (описано, например, в Git rev-parse manpage):

  • Полное имя объекта SHA1 (40-байтная шестнадцатеричная строка) или подстрока такого, которая уникальна в репозитории
  • Символьное имя ссылки, например. 'master' (ссылаясь на ветвь master) или 'v1.5.0' (ссылаясь на тег) или 'origin/next' (ссылаясь на ветвь удаленного отслеживания)
  • Суффикс ^ для параметра ревизии означает первый родитель объекта фиксации, ^n означает n-й родительский элемент слияния. Суффикс ~n для параметра ревизии означает n-й предок фиксации в прямой строке первого родителя. Эти суффиксы могут быть объединены, чтобы сформировать спецификатор ревизии по пути от символьной ссылки, например. 'Пу ~ 3 ^ 2 ~ 3'
  • Вывод "git описать", т.е. ближайший тег, необязательно сопровождаемый тире и количеством коммитов, за которым следует тире, "g" и сокращенное имя объекта, например "v1.6.5.1-75-g5bf8097'.