Hvorfor Git er bedre enn X

where "x" is one of
Denne siden er her fordi jeg synes å tilbringe mye tid på å forsvare Git-brukere mot anklager om å være partiske, favoriserende og at de kun velger Git fordi det er et populært valg. Her er de virkelige grunnene til at folk bytter til Git fra X, og hvorfor du burde gjøre det samme. Klikk på en grunn for å lese mer.
hg bzr svn perforce

Rask lokal branching

Den kanskje mest interessante egenskapen til Git er dens branching modell, og også en av årsakene til at det virkelig skiller seg ut fra nesten alle andre SCM du finner der ute. Den er totalt forskjellig fra alle modellene jeg sammenlikner med her, hvor de fleste mener at den beste måten å branche på er å klone hele arkivet til en ny mappe.
Git fungerer ikke slik. Git tillater deg å ha mange lokale brancher som kan være helt separert fra hverandre, og opprettelse, merging og sletting av disse utviklingslinjene tar kun sekunder.
Dette betyr at du kan gjøre ting som å:
  • Opprette en branch for å prøve ut en ny ide, gjøre noen commits, bytte tilbake til hvor du branchet ut fra, legg til en patch, bytt tilbake til den eksperimentelle branchen og merge den inn.
  • Ha en branch som alltid inneholder kun den koden som går ut i produksjon, en annen du merger arbeid inn i for testing, og mange mindre brancher for dag-til-dag arbeid.
  • Opprette en ny branch for hver ny ting du arbeider på, slik at du sømløst kan bytte fram og tilbake mellom dem, og slette hver av disse ettersom de blir merget inn i hovedbranchen din.
  • Opprette en ny branch å eksperimentere i, oppdage at det bare blir tull og koden aldri kommer til å fungere, slette branchen og forlate arbeidet —uten at noen vil få se det (selv om du har pushet til andre brancher i mellomtiden).
branches flowchart
Når du pusher til et fjernarkiv behøver du ikke pushe alle branchene dine. Du kan velge å kun dele en av branchene dine, og holde resten lokalt. Dette har en tendens til å gi folk spillerom til å prøve ut nye ideer uten å bekymre seg over når og hvordan de skal merge det inn eller dele det med andre.
Du kan finne måter å gjøre disse tingene med andre systemer, men arbeidet som er involvert er mye vanskeligere og utsatt for feil. Git gjør denne prosessen utrolig enkel, og det forandrer måten de fleste utviklere jobber på etter de har lært det.
jamis twitter trevorturk twitter thillerson twitter boblmartens twitter mathie twitter
svn perforce

Alt er lokalt

Dette er i hovedsak sant for alle distribuerte SCM, men i min erfaring enda mer sant med Git. Det er veldig lite utover 'fetch', 'pull', og 'push' som kommuniserer med noe annet enn harddisken din.
Dette gjør ikke bare de fleste operasjoner mye raskere enn du kanskje er vant til, men det lar deg også jobbe med ting når du er offline. Det høres kanskje ikke så viktig ut, men jeg blir stadig forbløffet over hvor ofte jeg faktisk jobber offline. Å ha muligheten til å branche, merge, gjøre commits og bla i arkivhistorien mens man sitter på flyet eller toget er veldig produktivt.
local repo to remote repo flowchart
Til og med i Mercurial, vanlige kommandoer som 'incoming' og 'outgoing' snakker med serveren, mens med Git kan du 'fetch' alle data fra servere før du logger av, og deretter jobbe med data som finnes på serveren, men som du ennå ikke har i dine lokale brancher.
Dette betyr at det er veldig enkelt å ha kopier av ikke bare dine egne brancher, men også kopier av dine Git-kollegers brancher uten å behøve å rote til dine egne data.
bzr svn perforce

Git er Raskt

Git er raskt. Alle—selv de fleste av kjernebrukerne av disse andre systemene—innrømmer det. Med Git er alle operasjoner utført lokalt, noe som gir et forsprang til SVN og Perforce som begge behøver nettverkstilgang for enkelte operasjoner. Men, selv sammenliknet med DSCM som også utfører operasjoner lokalt er Git raskt.
Dette er delvis fordi det ble bygd for å håndtere utviklingen av Linuxkjernen, hvilket betyr at det helt fra dag 1 måtte kunne jobbe effektivt med store kildekodearkiv. I tillegg er Git skrevet i C, noe som reduserer kodens kjøretid sammenliknet med språk på høyere nivå. En annen grunn til at Git er så raskt er at hovedutviklerne gjorde det til et av målene med systemet.
Følgende er kjøretidtester jeg har utført på 3 kopier av Djangos kildekodearkiv med 3 forskjellige SCM: Git, Mercurial og Bazaar. Jeg testet også noe av dette i SVN, men tro meg, det er tregere—ta Bazaars resultater og legg på nettverksforsinkelse...
init benchmarks add benchmarks status benchmarks diff benchmarks branching benchmarks
tag benchmarks log benchmarks large commit benchmarks small commit benchmarks
Sluttresultatet var at for alt bortsett fra å legge til nye filer, var Git raskest. (Også veldig store commits, noe Hg stort sett var lik på, men den commiten jeg testet var så stor at du sannsynligvis aldri vil komme borti en slik situasjon selv—normale commits er mye raskere i Git.)
Git Hg Bzr
Init 0.024s 0.059s 0.600s
Add 8.535s 0.368s 2.381s
Status 0.451s 1.946s 14.744s
Diff 0.543s 2.189s 14.248s
Tag 0.056s 1.201s 1.892s
Log 0.711s 2.650s 9.055s
Commit (Stor) 12.480s 12.500s 23.002s
Commit (Liten) 0.086s 0.517s 1.139s
Branch (Kald) 1.161s 94.681s 82.249s
Branch (Varm) 0.070s 12.300s 39.411s
Tallene for kald og varm braching er tall for den første og andre gangen jeg branchet et arkiv—det andre tallet er da branching med disk cache.
Det burde noteres at selv om 'add' resultatene er mye tregere, dette var for en massiv add-operasjon—over 2000 filer. For de fleste oppgaver folk gjør på en daglig basis, vil add-operasjoner i alle disse systemene ta mindre enn et sekund. Alle andre operasjoner testet her (muligens sett bort fra den store commiten) er bedre indikatorer på hva du sannsynligvis vil gjøre dag til dag.
Disse tallene er ikke vanskelig å gjenskape: klon Django-prosjektet i hvert av systemene og prøv ut de samme kommandoene i hvert system.
  • git clone git://github.com/brosner/django.git dj-git
  • hg clone http://hg.dpaste.com/django/trunk dj-hg
  • bzr branch lp:django dj-bzr
  • svn checkout http://code.djangoproject.com/svn/django/trunk dj-svn
svn

Git er liten

Git er veldig flink på å være konservativ med diskplass. Ditt Gitarkiv vil (generelt) være så vidt større enn en SVN checkout.—i visse tilfeller faktisk mindre (det bor tydeligvis mye i disse .svn-mappene).
De følgende tallene ble tatt fra kloner av Django-prosjektet i hver av dets semi-offisielle Git-speil ved samme tidspunkt i dets historie.
Git Hg Bzr Bzr* SVN
Arkiv Alene 24M 34M 45M 89M
Hele mappen 43M 53M 64M 108M 61M
* det andre Bzr-tallet er fra etter jeg kjørte 'bzr pack', noe jeg trodde ville gjøre det mindre, men endte opp med å gjøre det mye, mye større av en eller annen grunn.
hg bzr svn perforce

Forberedende område

Til forskjell fra de andre systemene har Git hva som kalles et 'forberedende område', eller 'index'. Dette er et mellomsteg hvor du kan sette opp hvordan neste commit skal være før du faktisk utfører den.
Det kule med dette, og hva som skiller Git ut fra alle disse andre verktøyene, er at du enkelt kan forberede enkeltfiler til en commit etter som du blir ferdige med dem, og deretter kjøre en commit på dem uten å inkludere andre modifiserte filer i arbeidsmappen, eller måtte liste dem opp på kommandolinjen mens du sjekker dem inn.
add commit workflow diagram
Dette tillater deg også å forberede enkelte deler av en modifisert fil. Borte er tiden når du gjorde to logisk uavhengige endringer i en fil før du oppdaget av du glemte å sjekke inn en av dem. Nå kan du rett og slett forberede endringen du behøver for denne innsjekken, og forberede den andre endringen til neste innsjekk. Denne egenskapen skalerer opp til så mange forskjellige endringer i en fil du måtte behøve.
Men selvsagt, Git gjør det også enkelt å ignorere denne egenskapen dersom du ikke vil ha den type kontroll—legg til en '-a' på commit-kommandoen for å legge til alle endringer i alle filer i innsjekk.
commit only workflow diagram
svn perforce

Distribuert

En av de kuleste egenskapene ved alle Distribuerte SCM, Git inkludert, er at det er distribuert. Dette betyr at istedet for å gjøre en 'checkout' av den nåværende spissen av kildekoden, får du en klone av hele arkivet.
Dette betyr at alle brukere har noe som essensielt er en komplett sikkerhetskopi av hovedserveren, selv om du benytter en sentrert arbeidsflyt. Hver av disse kopiene kan bli sendt inn for å erstatte koden på hovedserver dersom denne skulle krasje eller få harddiskfeil. Det finnes ganske enkelt ikke ett enkelt punkt hvor alt kan feile med Git, med mindre alt består av ett enkelt punkt.
Dette skaper ikke nevneverdige forsinkelser heller. En SVN-utsjekk er i gjennomsnitt bare marginalt raskere enn andre DSCM. Av de DSCM jeg har testet var Git raskest.
cloning benchmarks
Git 1m 59s
Hg 2m 24s
Bzr 5m 11s
SVN 1m 4s
svn perforce

Valgfri Arbeidsflyt

En av de forbløffende tingene med Git er at på grunn av dets distribuerte natur og fantastiske branching kan du enkelt implementere stort sett hvilken som helst arbeidsflyt du vil, relativt enkelt.

Subversion-aktig Arbeidsflyt

Dette er en ganske vanlig arbeidsflyt med Git, spesielt hos folk som er i overgangen fra et sentralisert system. Git vil ikke tillate deg å sende inn endringer dersom noen andre har sendt inn sine endringer siden du sist oppdaterte, så en sentralisert modell modell hvor alle utviklere sender inn på samme server fungerer bra.
subversion-style workflow

Arbeidsflyt med Integrasjonsleder

En annen vanlig arbeidsflyt med Git inkluderer en integrasjonsleder— en enkelt person som gjør commits på et 'hellig' arkiv, og utviklere som kloner fra dette arkivet, sender inn til sine egne uavhengige arkiv og spør integrasjonssjefen om å dra inn endringer derfra. Denne arbeidsflyten vil du ofte se i open source prosjekter eller GitHub-arkiv.
integration manager workflow

Diktator og Løytnant

Mer massive prosjekter legge opp arbeidsflyten på samme måte som utviklingen av Linuxkjernen, hvor flere mennesker har ansvar for et spesifikt subsystem av prosjektet (løytnanter) og fletter inn alle endringer som har med deres system å gjøre. Deretter kan en annen integrator (diktatoren) hente inn endringer fra sine løytnanter og sende inn til det 'hellige' arkivet som alle andre kloner fra igjen.
dictator and lieutenants workflow

Igjen, Git er helt fleksibel på dette området, så du står helt fritt til å velge hvilken arbeidsflyt som passer best for deg.u.
hg bzr svn perforce

GitHub

octocat
Det er mulig jeg er partisk her, siden jeg jobber for GitHub, men jeg legger til denne seksjonen likevel, siden så mange mennesker sier at GitHub i seg selv var grunnen til at de valgte Git.
GitHub er for mange en grunn til å velge Git siden det er mer likt et sosialt nettverk for kildekode enn en enkelt hostingleverandør. Folk finner andre utviklere eller prosjekter som likner på tingene de selv driver med, og kan enkelt forgrene og hjelpe til. Dette skaper et livlig fellesskap rundt Git og prosjektene folk bruker det til.
Det finnes andre tjenester, både for Git og de andre systemene, men få er brukerorientert eller søker å bygge et fellesskap, og ingen har en brukerbase som er i nærheten. Dette sosiale aspektet ved GitHub er fantastisk, og dette i kombinasjon med de overnevnte egenskapene gjør å jobbe med Git og GitHub til en kraftig kombinasjon for rask utvikling av prosjekter med åpen kildekode.
Denne type fellesskap er ganske enkelt ikke tilgjengelig med de andre systemene.
puls twitter twitter
perforce

Enkelt å Lære

Dette var ikke tilfelle tidligere. Git var mer et sett verktøy som lot deg versjonere et filsystem på en distribuert måte. Nå om dagen er i midlertid kommandoene og læringskurven gor Git ganske lik hvilket som helst annet SCM, og til og med bedre enn enkelte.
Siden dette vanskelig kan bevises objektivt uten en form for inngående studie, vil jeg bare vise forskjeller mellom hjelpemenyen for Mercurial- og Git-kommandoer. Jeg har fremhevet kommandoer som er (nesten) identiske mellom dem. (I Hg får du en liste over rundt 40-kommandoer dersom du skriver 'hg help'.)

Mercurial Help

add        add the specified files ...
annotate   show changeset informati...
clone      make a copy of an existi...
commit     commit the specified fil...
diff       diff repository (or sele...
export     dump the header and diff...
init       create a new repository ...
log        show revision history of...
merge      merge working directory ...
parents    show the parents of the ...
pull       pull changes from the sp...
push       push changes to the spec...
remove     remove the specified fil...
serve      export the repository vi...
status     show changed files in th...
update     update working directory

Git Help

add        Add file contents to the index
bisect     Find the change that introduce...
branch     List, create, or delete branches
checkout   Checkout a branch or paths to ...
clone      Clone a repository into a new ...
commit     Record changes to the repository
diff       Show changes between commits, ...
fetch      Download objects and refs from...
grep       Print lines matching a pattern
init       Create an empty git repository
log        Show commit logs
merge      Join two or more development h...
mv         Move or rename a file, a direc...
pull       Fetch from and merge with anot...
push       Update remote refs along with ...
rebase     Forward-port local commits to ...
reset      Reset current HEAD to the spec...
rm         Remove files from the working ...
show       Show various types of objects
status     Show the working tree status
tag        Create, list, delete or verify...
Før Git 1.6 var alle kommandoene i program PATH, noe som var veldig forvirrende for brukerne. Selv om Git fortsatt gjenkjenner alle de kommandoene er nå den eneste kommandoen i PATH, 'git'. Dersom du ser på Mercurial og Git har Git et nesten identisk kommandosett og hjelpesystem —det er i dag veldig få forskjeller sett fra perspektivet til en som akkurat har plukket dem opp.
Det er nå temmelig vanskelig å hevde at Mercurial eller Bazaar er enklere å lære enn Git.