Erfaringer med Mercurial som versionskontrolsystem

De sidste to år har jeg arbejdet meget med Mercurial som versionskontrolsystem, og jeg vil gerne dele mine erfaringer.
Dette er ikke et forsvar for Mercurial i forhold til nogle af de andre "konkurrenter", såsom Subversion og Git.

Nedenstående kræver nok at I har øjet en del af http://hgbook.red-bean.com/ igennem. Det er ikke alt, der skal være nemt at læse :-D
Du skal ikke være bekymret for at at dette blog-indlæg evt. skal ligge et par år for det er relevant. Hvis du allerede er i gang med at
bruge Mercurial, så er jeg meget interesseret i dine vurderinger nedenfor.

Mercurial er ret nemt at komme i gang med på en Linux/BSD-maskine. Har jeg et par filer, som skal udvikles af mig hen over et par timer, så lægger jeg dem i Mercurial

hg init
hg add FIL1 FIL2 FIL3
hg commit -m "Tilføjede filerne"

og når jeg har lavet et par ændringer - f.eks. at koden oversætter - så laver jeg en version til.

hg commit -m "Ændring så det oversætter"

Den ekstra tid, jeg anvender på at sætte det op er så lille i forhold til de hjælp jeg har ved at kunne gå frem og tilbage i versionerne (med "hg update").
Fra tid til anden får jeg lavet noget kode, som "pludselig" er blevet værre. I det tilfælde er det guld at kunne gå tilbage,
Mercurial er smart ved at jeg kan lave lokal versionskontrol på et vilkårligt katalog uden at skulle have en systemadministrator med på vognen.

Mange brugere

En af de "let-negative" erfaringer med Mercurial er at hver bruger har en kopi af hele versions-historikken.
Derfor kan man let ende med at have ret store datamængder i ".hg" kataloget, som indeholder historikken.
Det er meget anderledes end f.eks. CVS, hvor hele versions-historikken kun ligger et sted i CVSROOT-kataloget.

Hvis jeg sammenligner CVS og Mercurial, så er noget af de der glæder mig mest opdateringshastigheden. Når jeg opdaterer i CVS til f.eks. et "tag", der ligger seks måneder tilbage, så koster det oftest 5-10 minutter for de større projekter jeg arbejder med. Det er dødens pølse....
Mercurial er lysår foran mht. opdateringshastighed - det tager for mine projekter et eller ganske få sekunder at opdatere til et ældre "tag".

Et reelt problem med Mercurial

Djævlen ligger i detaljen siger man, og et af de problemer med Mercurial, som jeg erfarede ret sent er man har valgt at man skal have committed alle sine ændrede filer før man kan merge.
Antag at brugerne Mads og Martin deler et projekt.

Martin: Redigerer FIL1
Mads: Redigerer FIL2 og FIL3
Martin: hg commit -m "Jeg har lappet et par fejl" FIL1; hg push
Mads: hg commit -m "Jeg roder videre med FIL2" FIL2

Når Mads nu vil se hvad der er lavet af ændringer fra andre personer (her er det fra Martin), så kører Mads "hg pull", hvilket giver en advarsel om at Mads skal merge Martins ændring i FIL1 ind lokalt.
Det går også fint, hvis Mads faktisk er klar til at committe alle sine ændringer. Jeg har erfaret at det jævnligt IKKE er tilfældet. Jeg forstår ikke denne begrænsning i Mercurials design, men det er jævnligt irriterende.
Heldigvis har en af de dygtige Martin Geisler løst det problem ved at brugeren kan droppe sin commit og dermed undgå en merge, Løsningen er en af de mange gode "stackoverflow"-diskussioner: http://stackoverflow.com/questions/10156906/mercurial-undoing-two-or-mor...

hg update "p1(min(outgoing()))"
hg revert --all --rev tip 
hg strip "outgoing()"
hg pull -u

Dette kræver at brugerne har dette tilføjet til ~/.hgrc

[extensions]
mq =

Overblik

Jeg anvender meget "hg view" til at få overblik over historik. Det er basalt, men udmærket.

Illustration: Privatfoto

Jeg ville gerne have have gang i Tortoisehg, fordi det ser ud til at give godt overblik og rig mulighed for at arbejde grafisk med Mercurial.
Pt. driller afhængighederne mig vildt og inderligt på Red Hat 6.x. De Qt-biblioteker, som følger med Red Hat passer ikke sammen med Tortoisehg - fest. Det problem har jeg ikke sat skovlen ned i endnu.

Kommenter gerne nedenfor...

/pto

Kommentarer (26)
sortSortér kommentarer
  • Ældste først
  • Nyeste først
  • Bedste først
Alexander Færøy

Når man læser om den her slags "problemmer" bliver man helt glad for sin git pull --rebase.

Jeg må indrømme at jeg heller ikke forstår din kommentar på stackoverflow artiklen om hvorvidt timestamping af commits har særlig stor relevans. Hvornår bør det timestamp være? Når vi går i krig med en ændring? Når vi committer en ændring lokalt? Når vi pusher en ændring? Rækkefølgen i den endelige graf er jeg rimelig ligeglad med.

Anyway, jeg har brugt Mercurial til et enkelt projekt hvor vi primært sad på Windows og dengang var jeg meget godt tilfreds med det. Hvis jeg selv kan vælge vil jeg dog til enhver tid vælge Git.

  • 1
  • 0
Jacob Nordfalk

SVN er på alle - 1 punkter bedre end CVS og det er heldigvis mange år siden at jeg har skullet trækkes med CVS.

Når jeg skriver 'alle - 1' er det fordi SVN gemmer en lokal skjult kopi af alle filerne, og derfor fylder mapper tjekket ud fra SVN dobbelt så meget som mapper tjekket ud fra CVS. Det gir så også fordelen at man ikke skal vente på netværket for at se hvilke ændringer man har lavet. Derudover er CVS og SVN stort set ens i dagligt brug (bemærk 'dagligt brug' omfatter ikke at lave tags etc).

Nu er jeg så hoppet på GIT-vognen, og det synes jeg er en befrielse fordi man som i HG har hele versionshistorikken hos sig selv og derfor kan comitte lokalt og distribuere ændringerne senere.

Men.... jeg har den holdning at jeg ikke gider læse lange manualer og forstå nye begreber når jeg skal bruge et nyt versionskontrolsystem. Det skal bare VIRKE så jeg har fred til at lave det jeg er god til, nemlig kode.

Og hvis man, som jeg, har for travlt med andre ting til at sætte sig ned og bruge en dags tid på at forstå GITs nye verden og begreber, så kan GIT udvikle sig til et mareridt hvor man intet får fra hånden, før man har fået et par magiske kommandoer a la dem du har beskrevet ovenfor til HG, eller har spildt en dags tid med at forstå systemet.

Så jeg fornemmer du siger at HG også er.... bøvlet ... når det kommer til stykket ?

  • 1
  • 0
Alexander Færøy

Det der med dagligdagsbrug ved jeg ikke helt om jeg er enig i (udover at tagging ikke er noget man gør hver dag).

Mit arbejdsflow med Git for projekter hvor vi er mere end 3 blegfede nørder, der hacker på noget kode på Github, er:

  1. Opret en feature branch. Hvis jeg har en bug hedder branchen som regel noget med "bug-XXXX-fix-whatever". Bug ID for reference. Tekst til at beskrive hvad målet er.
  2. Hack lidt, commit, hack lidt, commit, test, kaffe, hack, commit og test.
  3. Squash mine patches ind til en enkelt sammenhængende patch med en beskrivende besked.
  4. Hvis andre kan lide min patch, rebase den til min master branch og push'er til mit upstream repository. Hvis andre ikke kan lide den, gå til step 2 (eller hvis det er noget virkelig skodkode jeg har lavet, step 5).
  5. Slet feature branch.

En anden ting er at jeg ikke forstår den der "det skal bare virke"-mentalitet der er blandt os udviklere fra tid til anden.

Vi bruger adskillige mandeår af vores liv på at lære os selv op til at blive dygtige udviklere. Vi læser flere 1000 sider teoretisk tekst om alt fra hvor hurtig quicksort er til hvordan vi bør teste vores kode, men så snart vi skal bruge et værktøj til at arbejde med vores kildekode går vi i baglås fordi vi slet ikke har "tid" eller "lyst" til at sætte os ind i den slags nye "ting", da vi jo ikke har haft behov for det før.

En del af det at være udvikler må da være at vi udvikler os hele tiden både i form af de sprog vi benytter os af, men også de værktøjer vi arbejder med til daglig.

Personligt er Vim og Git de to vigtigste værktøjer for mig som udvikler, så jeg forsøger da hele tiden at blive bedre til begge dele og lære fra andre, der er endnu bedre end mig selv.

  • 7
  • 1
Rene Nejsum

Hej Peter/

Du skriver at det er en "let-negativ" feature at repository er lokalt, er det manglende diskplads der er problemet ?

Det lokale repo, er i mine øjne noget af det bedste ved Git/Hg. Det giver en anden (og bedre) arbejdsgang omkring commit/branches/tagge. Desuden kan man dele opdateringer (nok mest værdi med mange udviklere)

Jeg er selv meget glad for Hg, vi bruger bitbucket.org (oprindeligt lavet af danske Jesper Nøhr) som vores "github".

  • 1
  • 0
Martin Geisler

Mercurials rebase fungerer på samme måde som Gits rebase og giver også mulighed for hg pull --rebase. Problemet her er at Peter vil jonglerer rundt (merge/rebase) med en dirty working copy -- noget som ikke giver mening da merge/rebase netop har brug for en working copy for at have et sted hvor man kan løse konflikter.

Det er en misforståelse at man skal merge efter at man har kørt hg pull. Man laver et merge når man har gjort sin feature færdig -- ikke når man laver en tilfældig hg pull.

Hvis man ikke er færdig med sin feature, men alligevel er helt vild i varmen for at få den nye kode integreret med det man har hevet ned, ja så kan man køre hg rebase for at flytte sin egen kode "op" efter den kode man har hentet. Her kan man eventuelt bruge hg rebase --collapse for at slå de lokale commits sammen til ét enkelt commit -- det er smart hvis man har lavet mange små commits som ikke nødvendigvis giver mening for andre og som man derfor ikke vil belemre andre med i fremtiden.

Ved at bruge hg rebase gentagne gange kan man holde sin feature branch opdateret uden at lave unødige merges. Man skal selvfølgelig stadig vente med hg rebase indtil man har en ren working copy -- man skal gøre det færdigt man er igang med før man begynder at flytte rundt på changesets.

Hvis nogen nu indvender at de har brug for de features der er i den kode der er blevet hentet og at de ikke kan køre hg commit fordi deres ting er ufærdige, ja så er det et tegn på at nogen har blandet tingene sammen på en uheldig måde. I teorien skulle du kunne lave din feature/bugfix færdig før du behøver at køre hg pull. Dermed kan du arbejde ud fra et stabilt grundlag og først bekymre dig om at merge/rebase når du er færdig med din opgave.

I praksis roder folk dog tit tingene sammen, og så kan det være rart at bruge ting som shelf til at gøre en working copy ren eller histedit til at redigere historien efter at man har lavet et "dummy" commit sådan at man kunne køre hg rebase.

  • 2
  • 0
Poul-Henning Kamp Blogger

Den gang FreeBSD evaluerede VCS faldt Mecurial på at de ikke havde nogen "obliterate" funktion.

Det vil site at når noget en gang var fyldt i repository, var der absolut ingen måde at slette alle spor igen, hvis f.eks en gnaven sagfører dokumenterede at repræsentere rettighederne til Tetris.

Er det fixet ?

  • 1
  • 0
Jacob Nordfalk

En anden ting er at jeg ikke forstår den der "det skal bare virke"-mentalitet der er blandt os udviklere fra tid til anden.

Det kan du vel have ret i, og jeg er heller ikke specielt stolt af at min mentalitet er sådan vedr versionskontrol, men det afhænger jo af hvem man er.

Jeg gider heller ikke bruge tid på at compilere min egen kerne eller sætte mig ind i hvilket lydsystem der pt er det der anvendes på min Linux.

Med skiftet CVS->SVN havde jeg da i sin tid også problemer (pga min mentalitet :-). Men kunne så lære 'svn up', 'svn diff' og 'svn commit' og så var jeg sådan set kørende.

Det er klart at så enkelt kan det ikke være med GIT/HG og jeg vil sige at i hvert fald GIT var meget brugervenlig at komme i gang med (man skal bare skrive 'git status' og så kommer den med lange forklaringer til hvad man kan gøre, og hvordan). Så jeg ku hurtigt lære mine 'git pull origin master', 'git add', 'git commit'.

Men derefter synes jeg det har været op ad bakke. Der er åbenbart 3-4 forskellige måder at arbejde sammen på, og det er for meget. Hvis de kloge GIT-herrer kunne blive enige med hinanden om ÉN måde at gøre det på ville jeg blive glad.

Martin Geislers kommentarer/irrettesætninger til Peter Tofts "overlevelseskommandoer" (hg update "p1(min(outgoing()))", hg revert --all --rev tip, hg strip "outgoing()", hg pull -u) illustrerer det meget godt. Det er for indviklet at folk selv skal opfinde/fremsøge den slags.

Her kan jeg for resten godt lige Android-kildens stil, de har nemlig fastlagt én måde, og skrevet proceduren ned. Så er der ikke så meget at rafle om og diskutere og forvirre os med den forkerte mentalitet: http://source.android.com/source/submit-patches.html

  • 3
  • 0
Sune Marcher

En af de "let-negative" erfaringer med Mercurial er at hver bruger har en kopi af hele versions-historikken.

Nu har jeg ikke kigget på Mercurials dataformat, men for Gits vedkommende er der rimeligt effektiv komprimering involveret - så til sourcekode brug oplever jeg ikke at overhead er slemt. Og det er en kæmpe hastighedsmæssig fordel at have en lokal kopi af repo'et, ikke mindst hvis man sammenligner med subversion hvis netværksprotokol er HORRIBEL - jeg kan lave en fuld Git checkout af Notepad++ over min ADSL linie hurtigere end checkout af et væsentligt mindre projekt via subversion på gigabit LAN... og når man skal grave igennem history for at finde ud af hvornår en bug er introduceret er subversion decideret pinefuldt :-)

  • 0
  • 0
Flemming Jønsson

Jeg bruger både Git og Mercurial på forskellige projekter jeg arbejder på i det daglige og der er da forskelle. Men ikke så store at de generer mig voldsomt meget - eller at jeg ligefrem vil udråbe en vinder. Dog er jeg meget glad for Github, så mine private projekter ligger der.

Jeg sidder iøvrigt på Mac og kan godt anbefale SourceTree fra Atlassian som gui til Git/Mercurial og SVN - hvis man går kold i kommandoerne - eller bare vil have et grafisk overblik.

Den er faktisk ret fin, og understøtter f.eks. både Git-flow og Hg flow. SourceTree er gratis - prøv det af hvis i har lyst. I forhold til Git-flow og SourceTree kan denne artikel måske hjælpe lidt - http://blog.sourcetreeapp.com/2012/08/01/smart-branching-with-sourcetree...

En lille detalje man skal være opmærksom på er at de er løbet ind i nogen begrænsninger fra Apple i Mac App store - så den nye 1.5 skal hentes fra deres eget site og kommer ikke i Mac App Store - http://sourcetreeapp.com/

  • 0
  • 0
Martin Geisler

Det vil site at når noget en gang var fyldt i repository, var der absolut ingen måde at slette alle spor igen, hvis f.eks en gnaven sagfører dokumenterede at repræsentere rettighederne til Tetris.

Er det fixet ?

De moderne systemer (Git, Mercurial, ...) bygger alle på en model hvor indholdet i et repository bestemmer identiteten af repositoriet. Det skal forstås sådan at hvis du har et changeset med ID "41453d55b481", så er der kun én mulig historie der kan lede op til det changeset.

Med andre ord: hvis du vil slette noget fra historien, så kommer du også til at få andre changeset IDer. Det er nemt nok at gen-spille den gamle historie og udelade enkelte filer eller hele mapper: i Mercurial bruger man hg convert og i Git bruger man git filter-branch. Resultatet er i begge tilfælde et nyt repository som ikke indeholder det man har filtreret væk. Da det nye repository er anderledes vil det også have en ny identitet. Folk vil derfor blive nødt til at klone forfra.

Jeg synes ikke denne model skal fikses -- der er ganske enkelt tale om en mere striks model med langt større integritet end det de ældre systemer tilbyder.

  • 5
  • 0
Jon Bendtsen

Jeg ville ikke bruge et source kode versionerings system til den slags. Måske noget, der er rettet mod binære filer såsom Sonatype Nexus eller Archivia.

Eller noget andet webdav baseret.

Jeg havde håbet på offline funktionalitet, altså at folk kan tilgå data uden at være online når de først er kopieret til den lokale harddisk. Jeg kan rigtig godt lide ideen med at lave en "checkout" til den lokale harddisk, og bagefter skubbe det tilbage igen.

Jeg har ikke kunnet finde ud af mere om Archivia, gider du uddybe?

  • 0
  • 0
Helge Svendsen

Off topic ..

Argh, den anmeld knap sidder altså for tæt på svar knappen ...

On topic ..

Begge dele er systemer til at håndtere binære artefakter (filer) fra Maven. Det er et byggeværktøj fra Java verdenen, men der er nu ikke noget i vejen for, at bruge det til at styre binære filer andetsteds fra.

Sonatype Nexus:

http://www.sonatype.org/nexus/go

Archiva:

http://archiva.apache.org/

  • 0
  • 0
Svenne Krap

En af de features jeg er mest glad for i git er, at man skal add filer til det lokale index inden de kan comittes.

Dette kombineret med partial adds, gør at man nemt kan splitte flere uafhæninge ændringer ad, hvis man ikke har fået committed undervejs.

Har hg det samme, eller er den ligesom de andre, der betragter hele workdir som ændringen?

  • 0
  • 0
Jon Bendtsen
  • 0
  • 0
Martin Geisler

Har hg det samme, eller er den ligesom de andre, der betragter hele workdir som ændringen?

Mercurial har ikke et index som standard og det fungerer altså ligesom CVS, SVN som udgangspunkt. (Man kan selvfølgelig køre hg commit foo.c bar.h for at lave et commit som ignorerer ændringer i andre filer.)

Hvis man vil have noget der ligner, så kan man bruge mq. Den extension giver dig mulighed for langsomt at bearbejde en patch (faktisk en stak af patches) og du kan tilføje ændringer til en patch lidt af gangen. Med record kan du lave partielle commits hvor du kun committer dele af ændringerne i en fil, altså i stil med git add -i.

De to extensions jeg nævner ovenfor er "standard extensions" hvilket betyder at de kommer sammen med Mercurial og får samme support som resten af Mercurial. De er blot ikke slået til som standard idet ikke alle har brug for denne funktionalitet.

På den måde er filosofien lidt anderledes i Mercurial i forhold til Git: Mercurial kommer med en lille kerne og en masse udvidelser mens Git kommer med en hel masse kommandoer fra starten.

Men hvis man kigger nærmere på implementationen af de forskellige kommandoer i Git, så vil man se at de også er bygget på den måde at de bruger Gits kerne-kommandoer -- git rebase er et shell script som bruger en håndfuld andre Git kommandoer internt. På samme måde er hg rebase et Python modul som bruger et internt API. På dem måde minder de to systemer faktisk meget om hinanden.

  • 0
  • 0
Peter Toft

Hukommelsesforbruget er ikke noget stort problem, men hvis der er store GB filer og mange udviklere, så er det værd at have i mente. Til gengæld - som allerede nævnt - er hastigheden på "hg update" der hvor man vinder stort med Mercurial (vist det samme med Git)

  • 0
  • 0
Peter Toft

Jeg fatter heller ikke kommentaren. CVS er ikke et ringe VCS, men udviklingsmæssigt er det DØDT. Og der er så gammelt, at andre har lært hvad der kan forbedres i designet. Derfor fik vi Subversion. Og da andre havde lært af problemerne i Subversion mv så fik vi (bla.) Git og Mercurial. Evolution....

  • 0
  • 0
Anders Kreinøe

Hg kommer som standard med en large file extension, som du måske kunen bruge til formålet: http://mercurial.selenic.com/wiki/LargefilesExtension

Der er også en BigFile extension, hvis formål er det samme, men som konfigureres lidt anderledes. Den er dog ikke inkluderet i mercurial som standard, så den må man selv installere:

http://mercurial.selenic.com/wiki/BigfilesExtension

  • 0
  • 0
Log ind eller Opret konto for at kommentere