Git e Mercurial - Confronto e contrasto


520

Da un po 'di tempo utilizzo sovversione per i miei progetti personali.

Sempre più continuo a sentire grandi cose su Git, Mercurial e DVCS in generale.

Vorrei dare un giro completo all'intera DVCS, ma non ho troppa familiarità con nessuna delle due opzioni.

Quali sono alcune delle differenze tra Mercurial e Git?

Nota: Sto non cercando di scoprire che uno è "migliore" o anche che quello che dovrebbe iniziare con. Sono principalmente alla ricerca di aree chiave in cui sono simili e in cui sono diverse, perché sono interessato a sapere come differiscono in termini di implementazione e filosofia.



Risposte:


451

Disclaimer: utilizzo Git, seguo lo sviluppo di Git sulla mailing list di Git e contribuisco anche un po 'a Git (principalmente gitweb). Conosco Mercurial dalla documentazione e alcuni dalla discussione sul canale IRC #revctrl su FreeNode.

Grazie a tutte le persone sul canale IRC #mercurial che hanno fornito aiuto su Mercurial per questo writeup



Sommario

Qui sarebbe bello avere qualche sintassi per la tabella, qualcosa come nell'estensione PHPMarkdown / MultiMarkdown / Maruku di Markdown

  • Struttura del repository: Mercurial non consente le unioni di polpo (con più di due genitori), né l'etichettatura di oggetti non commit.
  • Tag: Mercurial utilizza .hgtagsfile con versione con regole speciali per i tag per repository e ha anche il supporto per i tag locali .hg/localtags; in Git i tag sono ref che risiedono nello refs/tags/spazio dei nomi e, per impostazione predefinita, vengono automaticamente seguiti al recupero e richiedono il push esplicito.
  • Filiali: in Mercurial il flusso di lavoro di base si basa su teste anonime ; Git utilizza rami con nome leggero e ha un tipo speciale di rami (rami di tracciamento remoto ) che seguono i rami nel repository remoto.
  • Denominazione e intervalli di revisione : Mercurial fornisce numeri di revisione , da locale a repository e basa le revisioni relative (conteggio dalla punta, ovvero il ramo corrente) e gli intervalli di revisione su questa numerazione locale ; Git fornisce un modo per fare riferimento alla revisione relativa alla punta del ramo e gli intervalli di revisione sono topologici (basati sul grafico delle revisioni)
  • Mercurial utilizza il monitoraggio della ridenominazione , mentre Git utilizza il rilevamento della ridenominazione per gestire la ridenominazione dei file
  • Rete: Mercurial supporta i protocolli "intelligenti" SSH e HTTP e il protocollo HTTP statico; Git moderno supporta i protocolli "intelligenti" SSH, HTTP e GIT e il protocollo "stupido" HTTP (S). Entrambi hanno il supporto per i file bundle per il trasporto off-line.
  • Mercurial utilizza estensioni (plugin) e API consolidate; Git ha la scriptabilità e i formati stabiliti.

Ci sono alcune cose che differiscono da Mercurial a Git, ma ci sono altre cose che le rendono simili. Entrambi i progetti prendono in prestito idee l'uno dall'altro. Ad esempio il hg bisectcomando in Mercurial (precedentemente estensione bisect ) è stato ispirato dal git bisectcomando in Git, mentre l'idea di è git bundlestata ispirata hg bundle.

Struttura del deposito, memorizzazione delle revisioni

In Git ci sono quattro tipi di oggetti nel suo database di oggetti: oggetti BLOB che contengono il contenuto di un file, oggetti gerarchici ad albero che memorizzano la struttura delle directory, inclusi i nomi dei file e le parti pertinenti delle autorizzazioni dei file (autorizzazione eseguibile per i file, essendo un collegamento simbolico) , oggetto di commit che contiene informazioni sulla paternità, puntatore allo snapshot dello stato del repository al momento della revisione rappresentato da un commit (tramite un oggetto albero della directory superiore del progetto) e riferimenti a zero o più commit principali e tag oggetti che fanno riferimento ad altri oggetti e possono essere firmato usando PGP / GPG.

Git utilizza due modi per archiviare gli oggetti: il formato sciolto , in cui ogni oggetto è memorizzato in un file separato (quei file sono scritti una volta e mai modificati) e il formato compresso in cui molti oggetti sono memorizzati delta-compressi in un singolo file. L'atomicità delle operazioni è fornita dal fatto che il riferimento a un nuovo oggetto viene scritto (atomicamente, usando il trucco create + rename) dopo aver scritto un oggetto.

I repository Git richiedono una manutenzione periodica mediante git gc(per ridurre lo spazio su disco e migliorare le prestazioni), anche se oggigiorno Git lo fa automaticamente. (Questo metodo fornisce una migliore compressione dei repository.)

Mercurial (per quanto ho capito) memorizza la cronologia di un file in un file di registro (insieme, penso, con metadati extra come il tracciamento della ridenominazione e alcune informazioni di supporto); utilizza una struttura piatta chiamata manifest per memorizzare la struttura delle directory e una struttura chiamata log delle modifiche che memorizza le informazioni sui changeset (revisioni), incluso il messaggio di commit e zero, uno o due genitori.

Mercurial utilizza il journal delle transazioni per fornire atomicità delle operazioni e si affida al troncamento dei file per la pulizia dopo un'operazione non riuscita o interrotta. I revlog sono di sola aggiunta.

Osservando la struttura del repository in Git rispetto a Mercurial, si può vedere che Git è più simile a un database di oggetti (o un file system indirizzato al contenuto) e Mercurial più come un tradizionale database relazionale a campo fisso.

Differenze:
in Git gli oggetti dell'albero formano una struttura gerarchica ; nel file manifest mercuriale è una struttura piatta . Nell'oggetto BLOB Git archiviare una versione del contenuto di un file; nel Mercelial filelog memorizza tutta la storia di un singolo file (se non prendiamo in considerazione qui eventuali complicazioni con i nomi). Ciò significa che ci sono diverse aree di operazioni in cui Git sarebbe più veloce di Mercurial, tutte le altre cose considerate uguali (come le fusioni, o mostrando la storia di un progetto) e aree in cui Mercurial sarebbe più veloce di Git (come applicare patch o mostrare cronologia di un singolo file).Questo problema potrebbe non essere importante per l'utente finale.

A causa della struttura a registro fisso della struttura del log delle modifiche di Mercurial , i commit in Mercurial possono avere solo un massimo di due genitori ; si impegna in Git può avere più di due genitori (il cosiddetto "polpo merge"). Sebbene sia possibile (in teoria) sostituire l'unione di polpo con una serie di fusioni a due genitori, ciò potrebbe causare complicazioni durante la conversione tra i repository Mercurial e Git.

Per quanto ne so, Mercurial non ha equivalenti di tag annotati (oggetti tag) di Git. Un caso speciale di tag annotati sono tag firmati (con firma PGP / GPG); l'equivalente in Mercurial può essere fatto usando GpgExtension , la cui estensione viene distribuita insieme a Mercurial. Non puoi taggare un oggetto non-commit in Mercurial come puoi fare in Git, ma questo non è molto importante, penso (alcuni repository git usano BLOB con tag per distribuire la chiave PGP pubblica da usare per verificare i tag firmati).

Riferimenti: rami e tag

In Git i riferimenti (filiali, filiali e tag di tracciamento remoto) risiedono al di fuori del DAG di commit (come dovrebbero). I riferimenti nello refs/heads/spazio dei nomi ( filiali locali ) indicano commit e di solito vengono aggiornati da "git commit"; indicano la punta (testa) del ramo, ecco perché tale nome. I riferimenti nello refs/remotes/<remotename>/spazio dei nomi ( rami di tracciamento remoto ) puntano a eseguire il commit, seguono i rami nel repository remoto <remotename>e vengono aggiornati da "git fetch" o equivalente. I riferimenti nello refs/tags/spazio dei nomi ( tag ) in genere indicano commit (tag leggeri) o oggetti tag (tag con annotazioni e firmati) e non intendono cambiare.

tag

In Mercurial puoi dare un nome persistente alla revisione usando il tag ; i tag sono archiviati in modo simile ai modelli ignora. Significa che i tag visibili a livello globale sono memorizzati nel .hgtagsfile controllato dalla revisione nel repository. Ciò ha due conseguenze: in primo luogo, Mercurial deve utilizzare regole speciali per questo file per ottenere l'elenco corrente di tutti i tag e aggiornare tale file (ad esempio, legge la revisione del file più recente impegnata, versione attualmente non verificata); in secondo luogo, è necessario eseguire il commit delle modifiche a questo file per rendere visibile il nuovo tag ad altri utenti / altri repository (per quanto ne so).

Mercurial supporta anche tag locali , memorizzati in hg/localtags, che non sono visibili ad altri (e ovviamente non sono trasferibili)

In Git i tag sono fissi (costanti) riferimenti denominati ad altri oggetti (generalmente tag object, che a loro volta puntano a commit) memorizzati nello refs/tags/spazio dei nomi. Per impostazione predefinita, quando recupera o invia una serie di revisioni, git recupera o invia automaticamente i tag che indicano che le revisioni vengono recuperate o inviate. Tuttavia puoi controllare in una certa misura quali tag vengono recuperati o inviati.

Git tratta tag leggeri (che puntano direttamente ai commit) e tag annotati (che puntano a oggetti tag, che contengono un messaggio tag che include facoltativamente la firma PGP, che a sua volta punta per eseguire il commit) in modo leggermente diverso, ad esempio per impostazione predefinita considera solo i tag annotati durante la descrizione si impegna usando "git descrivono".

Git non ha un equivalente rigoroso dei tag locali in Mercurial. Tuttavia le migliori pratiche di git raccomandano di impostare un repository nudo pubblico separato, in cui si spingono le modifiche pronte e da cui altri clonano e recuperano. Ciò significa che i tag (e i rami) che non si spinge, sono privati ​​nel proprio repository. D'altra parte puoi anche usare uno spazio dei nomi diverso da heads, remoteso tags, ad esempio, local-tagsper i tag locali.

Opinione personale: a mio avviso i tag dovrebbero risiedere al di fuori del grafico di revisione, in quanto sono esterni ad esso (sono puntatori nel grafico delle revisioni). I tag devono essere senza versione, ma trasferibili. La scelta di Mercurial di utilizzare un meccanismo simile a quello per ignorare i file, significa che deve essere trattato in modo .hgtagsspeciale (il file nella struttura ad albero è trasferibile, ma ordinario è con versione), oppure ha tag solo locali ( .hg/localtagsnon con versione, ma non trasferibile).

filiali

In Git la filiale locale (punta del ramo o testa del ramo) è un riferimento denominato a un commit, in cui è possibile aumentare i nuovi commit. Branch può anche significare una linea di sviluppo attiva, ovvero tutti gli commit sono raggiungibili dalla punta del branch. Le filiali locali risiedono nello refs/heads/spazio dei nomi, quindi ad esempio il nome completo della diramazione "master" è "refs / heads / master".

Il ramo corrente in Git (che significa ramo estratto e ramo in cui andrà il nuovo commit) è il ramo a cui fa riferimento il riferimento HEAD. Si può avere HEAD che punta direttamente a un commit, piuttosto che essere un riferimento simbolico; questa situazione di trovarsi su un ramo anonimo senza nome si chiama distaccato HEAD ("git branch" mostra che ci si trova su "(nessun ramo)").

In Mercurial ci sono rami anonimi (teste di rami) e si possono usare i segnalibri (tramite l' estensione dei segnalibri ). Tali rami dei segnalibri sono puramente locali e quei nomi erano (fino alla versione 1.6) non trasferibili tramite Mercurial. È possibile utilizzare rsync o scp per copiare il .hg/bookmarksfile in un repository remoto. È inoltre possibile utilizzare hg id -r <bookmark> <url>per ottenere l'id di revisione di un suggerimento corrente di un segnalibro.

Dal momento che 1.6 segnalibri possono essere spinti / tirati. La pagina BookmarksExtension ha una sezione su Lavorare con i repository remoti . C'è una differenza nel fatto che in Mercurial i nomi dei segnalibri sono globali , mentre la definizione di "remoto" in Git descrive anche la mappatura dei nomi dei rami dai nomi nel repository remoto ai nomi dei rami di localizzazione remota; ad esempio, la refs/heads/*:refs/remotes/origin/*mappatura significa che è possibile trovare lo stato del ramo 'master' ('refs / heads / master') nel repository remoto nel ramo di tracciamento remoto 'origin / master' ('refs / remotes / origin / master').

Mercurial ha anche i cosiddetti rami denominati , in cui il nome del ramo è incorporato in un commit (in un changeset). Tale nome è globale (trasferito al recupero). I nomi di tali rami sono registrati in modo permanente come parte dei metadati del changeset. Con il moderno Mercurial puoi chiudere "branch chiamato" e interrompere la registrazione del nome del branch. In questo meccanismo le punte dei rami sono calcolate al volo.

I "rami nominati" di Mercurial dovrebbero invece essere chiamati etichette di commit , perché è quello che sono. Esistono situazioni in cui "ramo denominato" può avere più suggerimenti (più commit senza figli) e può anche essere costituito da diverse parti disgiunte del grafico delle revisioni.

Non esiste un equivalente di quei "rami incorporati" di Mercurial in Git; inoltre la filosofia di Git è che, sebbene si possa dire che un ramo include un certo commit, ciò non significa che un commit appartenga a un certo ramo.

Si noti che la documentazione di Mercurial propone ancora di utilizzare cloni separati (repository separati) almeno per i rami di lunga durata (singolo ramo per flusso di lavoro del repository), ovvero la ramificazione mediante clonazione .

Rami in spinta

Mercurial di default spinge tutte le teste . Se si desidera spingere un singolo ramo ( testa singola ), è necessario specificare la revisione della punta del ramo che si desidera spingere. È possibile specificare la punta del ramo in base al numero di revisione (locale al repository), all'identificatore di revisione, al nome del segnalibro (locale al repository, non viene trasferito) o al nome del ramo incorporato (nome del ramo).

Per quanto ho capito, se si spinge una serie di revisioni che contengono commit contrassegnati come presenti su un "ramo denominato" nel linguaggio mercuriale, si avrà questo "ramo denominato" nel repository in cui si spinge. Ciò significa che i nomi di tali rami incorporati ("rami denominati") sono globali (rispetto ai cloni di un determinato repository / progetto).

Per impostazione predefinita (soggetto alla push.defaultvariabile di configurazione) "git push" o "git push < remote >" Git spingerebbe i rami corrispondenti , cioè solo quei rami locali che hanno il loro equivalente già presente nel repository remoto in cui si inserisce. Puoi usare l' --allopzione per git-push ("git push --all") per spingere tutti i rami , puoi usare "git push < remoto > < ramo >" per spingere un dato singolo ramo , e puoi usare "git push < remote > HEAD "per spingere il ramo corrente .

Tutto quanto sopra presuppone che Git non sia configurato su quali rami inviare tramite remote.<remotename>.push variabili di configurazione.

Rami in recupero

Nota: qui uso la terminologia di Git dove "fetch" significa scaricare le modifiche dal repository remoto senza integrare tali modifiche con il lavoro locale. Questo è ciò che " git fetch" e " hg pull" fanno.

Se lo capisco correttamente, per impostazione predefinita Mercurial recupera tutte le teste dal repository remoto, ma è possibile specificare il ramo da recuperare tramite " hg pull --rev <rev> <url>" o " hg pull <url>#<rev>" per ottenere un ramo singolo . È possibile specificare <rev> utilizzando l'identificatore di revisione, il nome "ramo denominato" (ramo incorporato nel log delle modifiche) o il nome del segnalibro. Il nome del segnalibro tuttavia (almeno attualmente) non viene trasferito. Tutte le revisioni "rami denominati" che ottieni appartengono al trasferimento. "hg pull" memorizza le punte dei rami che ha preso come teste anonime e senza nome.

In Git per impostazione predefinita (per il telecomando 'origin' creato da "git clone" e per i telecomandi creati usando "git remote add") " git fetch" (o " git fetch <remote>") ottiene tutti i rami dal repository remoto (dallo refs/heads/spazio dei nomi) e li memorizza in refs/remotes/namespace. Ciò significa ad esempio che il ramo denominato "master" (nome completo: "refs / heads / master") in "origine" remota verrà archiviato (salvato) come ramo di monitoraggio remoto "origin / master" (nome completo: "refs / telecomandi / origin / master ').

Puoi recuperare un singolo ramo in Git usando git fetch <remote> <branch>- Git memorizzerebbe i rami richiesti in FETCH_HEAD, che è qualcosa di simile alle teste senza nome Mercurial.

Questi sono solo esempi di casi predefiniti di potente sintassi refspec Git: con refspecs è possibile specificare e / o configurare quali rami si desidera recuperare e dove memorizzarli. Ad esempio il caso predefinito "recupera tutti i rami" è rappresentato da '+ refs / heads / *: refs / remotes / origin / *' wildcard refspec, e "recupera singolo ramo" è una scorciatoia per 'refs / heads / <branch>:' . I refspec sono usati per mappare i nomi dei rami (refs) nel repository remoto ai nomi refs locali. Ma non è necessario conoscere (molto) refspecs per poter lavorare efficacemente con Git (grazie principalmente al comando "git remote").

Opinione personale: personalmente penso che i "rami denominati" (con i nomi dei rami incorporati nei metadati del changeset) in Mercurial siano design errato con il suo spazio dei nomi globale, specialmente per un sistema di controllo di versione distribuito . Ad esempio, prendiamo il caso in cui sia Alice che Bob abbiano "ramo chiamato" chiamato "for-joe" nei loro repository, rami che non hanno nulla in comune. Nel repository di Joe, tuttavia, quei due rami sarebbero stati maltrattati come un singolo ramo. Quindi in qualche modo hai escogitato una convenzione che protegge dagli scontri con i nomi delle filiali. Questo non è un problema con Git, dove nel repository Joe il ramo "for-joe" di Alice sarebbe "alice / for-joe", e da Bob sarebbe "bob / for-joe".

I "rami dei segnalibri" di Mercurial attualmente non dispongono di un meccanismo di distribuzione in-core.

Differenze:
questa area è una delle principali differenze tra Mercurial e Git, come hanno affermato nelle loro risposte James Woodyatt e Steve Losh . Mercurial, per impostazione predefinita, utilizza codeline leggere anonime, che nella sua terminologia sono chiamate "teste". Git utilizza rami con nome leggero, con mappatura iniettiva per mappare i nomi dei rami nel repository remoto ai nomi dei rami di tracciamento remoto. Git ti "obbliga" a nominare i rami (beh, ad eccezione di un singolo ramo senza nome, situazione chiamata HEAD distaccato), ma penso che questo funzioni meglio con flussi di lavoro pesanti come il flusso di lavoro di argomento, che significa più rami in un singolo paradigma di repository.

Revisioni dei nomi

In Git ci sono molti modi per nominare le revisioni (descritte ad esempio nella manpage git rev-parse ):

  • Il nome completo dell'oggetto SHA1 (stringa esadecimale di 40 byte) o una sottostringa di tale univoca all'interno del repository
  • Un nome di riferimento simbolico, ad esempio "master" (riferito al ramo "master") o "v1.5.0" (riferito al tag), o "origine / successivo" (riferito al ramo di tracciamento remoto)
  • Un suffisso ^per il parametro di revisione indica il primo genitore di un oggetto commit, ^nsignifica n-esimo genitore di un commit unione. Un suffisso ~nper il parametro di revisione indica l'ennesimo antenato di un commit nella riga diretta del primo genitore. Questi suffissi possono essere combinati, per formare lo specificatore di revisione seguendo il percorso da un riferimento simbolico, ad esempio 'pu ~ 3 ^ 2 ~ 3'
  • Output di "git descrivono", ovvero un tag più vicino, facoltativamente seguito da un trattino e un numero di commit, seguito da un trattino, una 'g' e un nome oggetto abbreviato, ad esempio 'v1.6.5.1-75- g5bf8097' .

Esistono anche identificatori di revisione che coinvolgono reflog, non menzionati qui. In Git ogni oggetto, sia esso commit, tag, albero o BLOB ha il suo identificatore SHA-1; esiste una sintassi speciale come ad esempio "next: Documentation" o "next: README" per fare riferimento all'albero (directory) o al BLOB (contenuto del file) alla revisione specificata.

Mercurial ha anche molti modi per nominare i changeset (descritti ad esempio nella pagina man di hg ):

  • Un intero semplice viene trattato come un numero di revisione. È necessario ricordare che i numeri di revisione sono locali per il repository dato ; in altri repository possono essere diversi.
  • Gli interi negativi vengono trattati come offset sequenziali dalla punta, con -1 che indica la punta, -2 che indica la revisione prima della punta e così via. Sono anche locali al repository.
  • Un identificatore di revisione univoco (stringa esadecimale di 40 cifre) o il suo prefisso univoco.
  • Un nome tag (nome simbolico associato a una data revisione) o un nome segnalibro (con estensione: nome simbolico associato a una determinata testina, locale al repository) o un "ramo denominato" (etichetta di commit; la revisione data da "ramo denominato" è suggerimento (commit senza figli) di tutti i commit con una determinata etichetta di commit, con il numero di revisione più grande se sono presenti più suggerimenti di questo tipo)
  • Il nome riservato "tip" è un tag speciale che identifica sempre la revisione più recente.
  • Il nome riservato "null" indica la revisione nulla.
  • Il nome riservato "." indica il genitore della directory di lavoro.

Differenze
Come puoi vedere confrontando gli elenchi sopra, Mercurial offre numeri di revisione, da locali a repository, mentre Git no. D'altra parte Mercurial offre offset relativi solo da 'tip' (ramo corrente), che sono locali al repository (almeno senza ParentrevspecExtension ), mentre Git consente di specificare qualsiasi commit che segue da qualsiasi suggerimento.

La revisione più recente si chiama HEAD in Git e "tip" in Mercurial; non esiste una revisione nulla in Git. Sia Mercurial che Git possono avere molte radici (possono avere più di un commit senza genitori; questo di solito è il risultato di unire progetti precedentemente separati).

Vedi anche: Molti diversi tipi di articolo sugli identificatori di revisione sul Blog di Elia (newren's).

Opinione personale: penso che i numeri di revisione siano sopravvalutati (almeno per lo sviluppo distribuito e / o la storia non lineare / ramificata). In primo luogo, per un sistema di controllo di versione distribuito devono essere locali o in repository o richiedono di trattare alcuni repository in modo speciale come autorità di numerazione centrale. In secondo luogo, i progetti più grandi, con una storia più lunga, possono avere un numero di revisioni in un intervallo di 5 cifre, quindi offrono solo un leggero vantaggio rispetto agli identificatori di revisione abbreviati a 6-7 caratteri e implicano un ordinamento rigoroso mentre le revisioni sono ordinate solo parzialmente (intendo qui che le revisioni n e n + 1 non devono necessariamente essere genitori e figlio).

Intervalli di revisione

In Git gli intervalli di revisione sono topologici . A..BSintassi comunemente vista , che per storia lineare significa intervallo di revisione che inizia da A (ma esclude A) e termina in B (cioè l'intervallo è aperto dal basso ), è una scorciatoia ("zucchero sintattico") per ^A B, che per i comandi di attraversamento della storia significa tutto commette raggiungibile da B, esclusi quelli raggiungibili da A. Ciò significa che il comportamento A..Bdell'intervallo è del tutto prevedibile (e abbastanza utile) anche se A non è antenato di B: A..Bsignifica quindi intervallo di revisioni dall'antenato comune di A e B (unisci base ) alla revisione B.

In Mercurial gli intervalli di revisione si basano sull'intervallo di numeri di revisione . L'intervallo viene specificato utilizzando la A:Bsintassi e, al contrario di Git, l'intervallo funge da intervallo chiuso . Anche l'intervallo B: A è l'intervallo A: B in ordine inverso, che non è il caso di Git (ma vedi la nota di A...Bsintassi di seguito). Ma tale semplicità ha un prezzo: l'intervallo di revisione A: B ha senso solo se A è antenato di B o viceversa, cioè con storia lineare; altrimenti (suppongo che) l'intervallo sia imprevedibile e il risultato sia locale al repository (perché i numeri di revisione sono locali al repository).

Ciò è stato risolto con Mercurial 1.6, che ha un nuovo intervallo di revisione topologica , in cui "A..B" (o "A :: B") è inteso come l'insieme di changeset che sono sia discendenti di X che antenati di Y. Questo è , Suppongo, equivalente a '--ancestry-path A..B' in Git.

Git ha anche una notazione A...Bper la differenza simmetrica delle revisioni; significa A B --not $(git merge-base A B), il che significa che tutti i commit sono raggiungibili da A o B, ma escludendo tutti i commit raggiungibili da entrambi (raggiungibili da antenati comuni).

rinomina

Mercurial utilizza il monitoraggio della ridenominazione per gestire la ridenominazione dei file. Ciò significa che le informazioni sul fatto che un file è stato rinominato vengono salvate al momento del commit; in Mercurial queste informazioni vengono salvate nella forma "migliorata diff" nei metadati di filelog (file revlog). La conseguenza di ciò è che devi usare hg rename/ hg mv... o devi ricordare di eseguire hg addremoveper eseguire il rilevamento della ridenominazione basato sulla somiglianza.

Git è unico tra i sistemi di controllo versione in quanto utilizza il rilevamento della ridenominazione per gestire le ridenominazioni dei file. Ciò significa che il fatto che il file sia stato rinominato viene rilevato al momento opportuno: quando si esegue un'unione o quando si mostra un diff (se richiesto / configurato). Ciò ha il vantaggio che l'algoritmo di rilevamento della ridenominazione può essere migliorato e non viene bloccato al momento del commit.

Sia Git che Mercurial richiedono l'uso --followdell'opzione per seguire le ridenominazioni quando mostrano la cronologia di un singolo file. Entrambi possono seguire le ridenominazioni quando mostrano la cronologia di un file in git blame/ hg annotate.

In Git il git blamecomando è in grado di seguire lo spostamento del codice, anche spostando (o copiando) il codice da un file all'altro, anche se lo spostamento del codice non fa parte di una rinomina di file salutare. Per quanto ne so, questa funzione è unica per Git (al momento della stesura, ottobre 2009).

Protocolli di rete

Sia Mercurial che Git supportano il recupero e il push nei repository sullo stesso filesystem, dove l'URL del repository è solo un percorso del filesystem verso il repository. Entrambi hanno anche il supporto per il recupero da file bundle .

Supporto mercuriale per il recupero e il push tramite SSH e tramite i protocolli HTTP. Per SSH è necessario un account shell accessibile sul computer di destinazione e una copia di hg installata / disponibile. Per l'accesso HTTP hg-serveè richiesto l'esecuzione dello script CGI o Mercurial e Mercurial deve essere installato sulla macchina server.

Git supporta due tipi di protocolli utilizzati per accedere al repository remoto:

  • I protocolli "intelligenti" , che includono l'accesso tramite SSH e tramite il protocollo personalizzato git: // (by git-daemon), richiedono che git sia installato sul server. Lo scambio in tali protocolli consiste nella negoziazione di client e server su quali oggetti hanno in comune, quindi la generazione e l'invio di un file pack. Modern Git include il supporto per il protocollo HTTP "intelligente".
  • I protocolli "stupidi" , che includono HTTP e FTP (solo per il recupero) e HTTPS (per l'invio tramite WebDAV), non richiedono l'installazione di git sul server, ma richiedono che il repository contenga informazioni aggiuntive generate da git update-server-info(di solito eseguite da un hook ). Lo scambio consiste nel far passare il client nella catena di commit e scaricare oggetti sciolti e pacchetti, se necessario. Il rovescio della medaglia è che si scarica più di quanto strettamente richiesto (ad esempio in caso d'angolo quando c'è un solo pacchetto di file verrebbe scaricato intero anche quando si ottengono solo poche revisioni) e che può richiedere molte connessioni per finire.

Estensione: gestibilità e estensioni (plugin)

Mercurial è implementato in Python , con alcuni codici core scritti in C per le prestazioni. Fornisce API per la scrittura di estensioni (plugin) come modo per aggiungere funzionalità extra. Alcune funzionalità, come "rami dei segnalibri" o revisioni della firma, sono fornite in estensioni distribuite con Mercurial e richiedono l'attivazione.

Git è implementato in script C , Perl e shell . Git fornisce molti comandi di basso livello ( idraulici ) adatti per l'uso negli script. Il solito modo di introdurre nuove funzionalità è di scriverlo come Perl o script di shell e quando l'interfaccia utente si stabilizza riscriverlo in C per prestazioni, portabilità e nel caso di script di shell evitando casi angolari (questa procedura è chiamata builtinification ).

Git si basa e si basa su formati [repository] e protocolli [di rete]. Invece dei legami linguistici ci sono reimplementazioni (parziali o complete) di Git in altre lingue (alcune di queste sono parzialmente reimplementazioni e in parte avvolgenti attorno ai comandi git): JGit (Java, usato da EGit, Eclipse Git Plugin), Grit (Ruby) , Dulwich (Python), git # (C #).


TL; DR


32
Ciò che potrebbe essere aggiunto è che hg si impegna molto per scoraggiare la riscrittura della storia (può essere fatto solo con estensioni: mq, histedit, rebase), mentre git lo fa immediatamente (e sembra che faccia parte della comunità lo incoraggia persino).
tonfa,

80
Penso che "riscrivere la storia" risulti inutilmente negativo. Ciò che incoraggio a git è che le persone considerino la storia che pubblicano. Altre persone hanno bisogno di consumare quella storia. Nessuno (nemmeno tu) è interessato a tutti i tuoi commit "spiacenti, ho dimenticato un file". A nessuno importa della serie di fusioni in entrata che hai attraversato mentre seguivi un ramo a monte mentre lavoravi su una nuova funzionalità. Questo tipo di cose rende la storia (e gli strumenti correlati) molto più difficili da comprendere e non fornisce alcun valore.
Dustin,

5
@Jakub: i rami con nome sono qualcosa che non esiste in Git. È semplicemente un campo nella descrizione di cset (e fa parte della storia, quindi è immutabile a meno che non modifichi hash, ecc.). Qualcosa come i rami git sono segnalibri ("teste nominate") ma al momento non sono trasferibili in remoto (non si importano i segnalibri remoti quando si tira). stevelosh.com/blog/entry/2009/8/30/… lo spiega molto bene.
tonfa,

28
"Originariamente Mercurial supportava solo un ramo per flusso di lavoro del repository e lo dimostra." Uh, no. Mercurial inizialmente non supportava i rami con nome , ma in un unico repository hai sempre potuto avere tanti rami anonimi quanti il ​​tuo cuore desidera. Contrastalo con git, il che rende la ramificazione anonima un enorme dolore. È praticamente necessario pensare a un nome per ogni piccolo ramo, se si vuole ottenere qualcosa fatto (ed evitare di dover la spazzatura lavoro raccolti).
Steve Losh,

17
@SteveLosh: sembra che avere molti rami anonimi in Mercurial sia una buona cosa, ma a me sembra orribile. Come si fa a distinguerli tutti? E tu pensi che nominare i rami in Git sia un'enorme difficoltà, ma se hai uno scopo per creare il ramo allora hai un nome già pronto. Se non hai uno scopo, non diramarti. Non riesco a vedere come Mercurial offra alcun vantaggio qui. Vedo solo dolore e confusione.
iconoclasta,

57

Penso che tu possa avere la sensazione di cosa siano simili o diversi quei sistemi urlando quei due video:

Linus Torvalds on Git ( http://www.youtube.com/watch?v=4XpnKHJAok8 )
Bryan O'Sullivan su Mercurial ( http://www.youtube.com/watch?v=JExtkqzEoHY )

Entrambi sono molto simili nel design ma molto diversi nelle implementazioni.

Uso Mercurial. Per quanto ho capito Git, una cosa importante è che Git tiene traccia dei contenuti dei file anziché dei file stessi. Linus dice che se sposti una funzione da un file all'altro, Git ti dirà la storia di quella singola funzione attraverso lo spostamento.

Dicono anche che git è più lento su HTTP ma ha il proprio protocollo e server di rete.

Git funziona meglio come client spesso SVN rispetto a Mercurial. Puoi tirare e spingere contro un server SVN. Questa funzionalità è ancora in fase di sviluppo in Mercurial

Sia Mercurial che Git hanno a disposizione soluzioni di hosting web molto belle (BitBucket e GitHub), ma Google Code supporta solo Mercurial. A proposito, hanno un confronto molto dettagliato di Mercurial e Git che hanno fatto per decidere quale supportare ( http://code.google.com/p/support/wiki/DVCSAnalysis ). Ha molte buone informazioni.


8
Consiglierei di leggere tutti i commenti su quella code page di Google. Le informazioni sembrano piuttosto distorte e non corrispondono alla mia esperienza. Mi piace hg, e l'ho usato ampiamente per circa un anno. Uso git quasi esclusivamente ora. Ci sono cose che devo realizzare che git rende facile e hg rende quasi impossibile (anche se ad alcuni piace chiamarlo per mezzo di "complicazione") Git di base è facile come hg di base.
Dustin,

11
Dustin, forse elenchi alcuni di quei casi "git easy, hg not much"?
Gregg Lind,

1
@knittl no non lo fa. Soprattutto perché sarebbe dispiaciuto per loro dispiegarlo poiché a git manca un protocollo http intelligente (la maggior parte dei front-end di Google sono basati su http).
tonfa,

2
@tonfa: il protocollo Smart HTTP per Git è attualmente in fase di sviluppo (come in: ci sono patch sulla mailing list di git e sono in 'pu' = ramo degli aggiornamenti proposti nel repository git.git).
Jakub Narębski,

4
A partire da ora Google Code supporta anche Git.
Andrej Kirejeŭ,

30

Qualche tempo fa ho scritto un post sul blog sui modelli di ramificazione di Mercurial e ho incluso confronti con il modello di ramificazione di Git. Forse lo troverai interessante: http://stevelosh.com/blog/entry/2009/8/30/a-guide-to-branching-in-mercurial/


@Steve Losh: volevo commentare questo post sul blog (su un ramo senza nome noto anche come HEAD distaccato, e su git-fetch che recupera tutti i rami, non uno), ma ho ricevuto un errore di 500 server.
Jakub Narębski,

1
@Jakub Narębski Scommetto che il problema è il carattere non ASCII a tuo nome. Sono abbastanza sicuro di aver riscontrato lo stesso problema su un altro sito e si è scoperto che l'associazione Python Askimet soffoca su Unicode. Darò un'occhiata.
Steve Losh,

@Steve Losh: Grazie per l'informazione, dopo "unidecoding" il mio nome sono stato in grado di postare un commento. Ottima descrizione della ramificazione in Mercurial (ma penso ancora che sia inferiore ;-))
Jakub Narębski

@SteveLosh Ti incoraggio a espandere questa risposta a una revisione più completa di mercurial. In questo momento, la risposta migliore è purtroppo in gran parte un annuncio per git perché il suo autore non ha usato ampiamente mercurial e non capisce come usarlo in modo efficace. Sarebbe bello che un'altra risposta fornisse il punto di vista mercuriale, per così dire.
Warren Dew,

25

Uso entrambi abbastanza regolarmente. La principale differenza funzionale sta nel modo in cui i nomi di Git e Mercurial si ramificano all'interno dei repository. Con Mercurial, i nomi delle filiali vengono clonati e associati ai loro changeset. Quando aggiungi modifiche a un nuovo ramo in Mercurial e invii a un altro repository, il nome del ramo viene inviato contemporaneamente. Quindi, i nomi delle filiali sono più o meno globali in Mercurial e devi usare l'estensione Segnalibro per avere nomi leggeri solo locali (se li vuoi; Mercurial, per impostazione predefinita, utilizza codeline leggere anonime, che nella sua terminologia sono chiamato "teste"). In Git, i nomi dei rami e la loro mappatura iniettiva ai rami remoti sono memorizzati localmente ed è necessario gestirli esplicitamente, il che significa sapere come farlo.

Come altri noteranno qui, ci sono molte e piccole differenze. La cosa con i rami è il grande differenziatore.


2
Vedi anche questo post per una buona spiegazione dei quattro tipi di filiali in Mercurial: stevelosh.com/blog/entry/2009/8/30/…
Martin Geisler,


11

Mercurial è quasi interamente scritto in pitone. Il core di Git è scritto in C (e dovrebbe essere più veloce di quello di Mercurial) e strumenti scritti in sh, perl, tcl e usa utility GNU standard. Quindi deve portare tutti questi programmi di utilità e interpreti con esso nel sistema che non li contiene (ad es. Windows).

Entrambi supportano il lavoro con SVN, anche se il supporto di AFAIK svn è rotto per git su Windows (forse sono solo sfortunato / zoppo, chi lo sa). Ci sono anche estensioni che consentono di interagire tra git e Mercurial.

Mercurial ha una buona integrazione con Visual Studio . L'ultima volta che ho controllato, il plugin per Git funzionava ma era estremamente lento.

I set di comandi di base sono molto simili (init, clone, add, status, commit, push, pull ecc.). Quindi, il flusso di lavoro di base sarà lo stesso. Inoltre, c'è un client simile a TortoiseSVN per entrambi.

Le estensioni per Mercurial possono essere scritte in python (nessuna sorpresa!) E per git possono essere scritte in qualsiasi forma eseguibile (eseguibile binario, shell script ecc.). Alcune estensioni sono pazzesche potenti, come git bisect.


9
Mercurial core è scritto anche in C FYI (ma probabilmente è un core più piccolo di git).
tonfa,

1
Uso git-svn su Windows senza alcun problema. Sta usando Cygwin (l'unico modo giusto per usare git su Windows se me lo chiedi). Non posso parlare per msysgit.
Dan Molding,

@Dan Molding: Sì, ho riscontrato problemi con msysgit. Forse dovrei provare con Cygwin Port (ho avuto una scarsa esperienza nell'uso di Cygwin prima, quindi l'ho evitato). Grazie per il consiglio!
elder_george,

Personalmente non mi piace l'intrusione di Cygwin nel registro per l'archiviazione dei dati dell'utente. È un PITA per farlo funzionare a chiave USB e mantenere una copia locale c: \ drive sincronizzata per quando voglio correre più veloce di quanto possa andare la mia chiave USB. : - /
Chris K,

1
Uso il plug-in Git per Visual Studio sopra menzionato e le prestazioni della versione corrente sono buone. Esegue il bombardamento degli strumenti da riga di comando per svolgere il lavoro, quindi non credo che perderà significativamente le prestazioni su grandi progetti.
Stuart Ellis,

11

Se hai bisogno di un buon supporto di Windows, potresti preferire Mercurial. TortoiseHg (plugin di Windows Explorer) riesce a offrire un'interfaccia grafica semplice da usare a uno strumento piuttosto complesso. Come stato qui, avrai anche un plug-in Visual Studio . Tuttavia, l'ultima volta che ho provato, l'interfaccia SVN non ha funzionato così bene su Windows.

Se non ti dispiace l'interfaccia della riga di comando, consiglierei Git. Non per motivi tecnici ma strategici. Il tasso di adozione di Git è molto più alto. Basta vedere quanti famosi progetti open source stanno passando da cvs / svn a Mercurial e quanti stanno passando a Git. Scopri quanti provider di hosting di codice / progetto puoi trovare con il supporto git rispetto all'hosting Mercurial.


C'è anche TortoiseGit, se non ti piace usare la riga di comando. (Ma richiede l'installazione di msysgit.)
Ben James,

2
La nostra azienda ha finito per scegliere git a causa del suo ottimo supporto su Windows: dai un'occhiata a Git Extensions . Sono di parte perché ora sono un collaboratore, ma non lo ero quando abbiamo iniziato a usarlo.
Jacob Stanley,

11

Dopo aver letto che Mercurial è più facile (cosa che credo ancora, dopo che tutta la comunità di Internet è dell'opinione), quando ho iniziato a lavorare con Git e Mercurial ho sentito che Git è relativamente più semplice per me adattarmi (ho iniziato con Mercurial con TortoiseHg) quando si lavora dalla riga di comando, principalmente perché i comandi git sono stati nominati in modo appropriato secondo me e sono meno numerosi. Mercurial ha nomi diversi per ciascun comando che svolge un lavoro distinto, mentre i comandi Git possono essere multiuso in base alla situazione (ad es.checkout). Mentre Git era più difficile allora, ora la differenza è appena sostanziale. YMMV .. Con un buon client GUI come TortoiseHg, in verità era molto più facile lavorare con Mercurial e non dovevo ricordare i comandi un po 'confusi. Non entrerò nel dettaglio di come variava ogni comando per la stessa azione, ma qui ci sono due elenchi completi: 1 dal sito di Mercurial e 2 ° da wiki .

╔═════════════════════════════╦════════════════════════════════════════════════════════════════════════════════════════════════╗
║           Git               ║                Mercurial                                                                       ║
╠═════════════════════════════╬════════════════════════════════════════════════════════════════════════════════════════════════╣
║ git pull                    ║ hg pull -u                                                                                     ║
║ git fetch                   ║ hg pull                                                                                        ║
║ git reset --hard            ║ hg up -C                                                                                       ║
║ git revert <commit>         ║ hg backout <cset>                                                                              ║
║ git add <new_file>          ║ hg add <new_file> (Only equivalent when <new_file> is not tracked.)                            ║
║ git add <file>              ║ Not necessary in Mercurial.                                                                    ║
║ git add -i                  ║ hg record                                                                                      ║
║ git commit -a               ║ hg commit                                                                                      ║
║ git commit --amend          ║ hg commit --amend                                                                              ║
║ git blame                   ║ hg blame or hg annotate                                                                        ║
║ git blame -C                ║ (closest equivalent): hg grep --all                                                            ║
║ git bisect                  ║ hg bisect                                                                                      ║
║ git rebase --interactive    ║ hg histedit <base cset> (Requires the HisteditExtension.)                                      ║
║ git stash                   ║ hg shelve (Requires the ShelveExtension or the AtticExtension.)                                ║
║ git merge                   ║ hg merge                                                                                       ║
║ git cherry-pick <commit>    ║ hg graft <cset>                                                                                ║
║ git rebase <upstream>       ║ hg rebase -d <cset> (Requires the RebaseExtension.)                                            ║
║ git format-patch <commits>  ║ hg email -r <csets> (Requires the PatchbombExtension.)                                         ║
║   and git send-mail         ║                                                                                                ║
║ git am <mbox>               ║ hg mimport -m <mbox> (Requires the MboxExtension and the MqExtension. Imports patches to mq.)  ║
║ git checkout HEAD           ║ hg update                                                                                      ║
║ git log -n                  ║ hg log --limit n                                                                               ║
║ git push                    ║ hg push                                                                                        ║
╚═════════════════════════════╩════════════════════════════════════════════════════════════════════════════════════════════════╝

Git salva internamente ogni versione dei file impegnati, mentre Hg salva solo i changeset che possono avere un footprint più piccolo. Git rende più semplice cambiare la storia rispetto a Hg, ma poi è ancora una funzione di odio o amore. Mi piace Hg per il primo e Git per il secondo.

Quello che mi manca in Hg è la funzionalità di sottomodulo di Git. Hg ha dei sottosposi ma non è esattamente il sottomodulo Git.

L'ecosistema attorno ai due può anche influenzare la propria scelta: Git deve essere più popolare (ma è banale), Git ha GitHub mentre Mercurial ha BitBucket , Mercurial ha TortoiseHg per il quale non ho visto un equivalente altrettanto buono per Git.

Ognuno ha i suoi vantaggi e svantaggi, con nessuno dei due non perderai.


8

Dai un'occhiata al post di Scott Chacon di qualche tempo fa.

Penso che git abbia la reputazione di essere "più complicato", sebbene nella mia esperienza non sia più complicato di quanto debba essere. IMO, il modello git è molto più semplice da capire (i tag contengono commit (e i puntatori a zero o più commit parent) contengono alberi che contengono BLOB e altri alberi ... fatto).

Non è solo la mia esperienza che Git non è più confuso di mercuriale. Consiglio di leggere nuovamente questo post di Scott Chacon sull'argomento.


1
Il modello mercuriale è in realtà quasi identico: il log delle modifiche punta a manifestare le revisioni dei file / BLOB ... fatto. Se stavi confrontando il formato su disco probabilmente non hai tenuto conto del file packs che è più difficile da spiegare rispetto al semplice formato revlog di hg.
tonfa,

Bene, quel modello semplificato ignora il tagging che è considerevolmente più clunkier nella pratica in hg (anche se sostengo che il tag git è un po 'confuso perché non crea un oggetto tag per impostazione predefinita). Il formato su disco era particolarmente costoso per entrambi i progetti che avevano una storia di molti nomi di file.
Dustin,

1
Non penso che il modello ignori il tagging: il tagging è banale in Mercurial - come sai, è solo un file che dà nomi agli hash SHA-1. Non ci sono congetture su come i tag scorrono nel sistema: si muovono insieme a spinte e tiri. E se c'è un conflitto tra tag, allora è anche banale risolverlo: lo risolvi come qualsiasi altro conflitto. Dopotutto, è solo una linea in un file di testo. Penso che la semplicità di questo modello sia una caratteristica molto bella.
Martin Geisler,

Dustin: Sì, gli utenti sono spesso confusi dal fatto che non puoi vedere il tag 1.0 .hgtagsquando hai verificato la revisione 1.0. Tuttavia, non è necessario guardare all'interno .hgtagse troverai che hg tagselenca ancora tutti i tag. Inoltre, questo comportamento è una semplice conseguenza dell'archiviazione dei tag in un file controllato in base alla versione: anche in questo caso il modello è facile da comprendere e molto prevedibile .
Martin Geisler,

1
Martin Geisler Direi che le regole per i tag in Mercurial, necessarie perché utilizza file controllati dalla versione per il trasporto, con layer su regole speciali per rendere i tag senza versione, è tutt'altro che facile da comprendere.
Jakub Narębski,

5

Ho usato Git per poco più di un anno nel mio lavoro attuale, e prima ancora, ho usato Mercurial per poco più di un anno nel mio lavoro precedente. Fornirò una valutazione dal punto di vista dell'utente.

Innanzitutto, entrambi sono sistemi di controllo della versione distribuiti. I sistemi di controllo di versione distribuiti richiedono un cambiamento di mentalità rispetto ai sistemi di controllo di versione tradizionali, ma in realtà funzionano molto meglio in molti modi una volta che li si capisce. Per questo motivo, considero sia Git che Mercurial molto superiori a Subversion, Perforce, ecc. La differenza tra i sistemi di controllo di versione distribuiti e i sistemi di controllo di versione tradizionali è molto più grande della differenza tra Git e Mercurial.

Tuttavia, ci sono anche differenze significative tra Git e Mercurial che rendono ciascuna più adatta al proprio sottoinsieme di casi d'uso.

Mercurial è più semplice da imparare. Sono arrivato al punto in cui raramente dovevo fare riferimento alla documentazione o alle note dopo alcune settimane di utilizzo di Mercurial; Devo ancora fare riferimento ai miei appunti regolarmente con Git, anche dopo averlo usato per un anno. Git è notevolmente più complicato.

Questo in parte perché Mercurial è semplicemente più pulito. Raramente devi diramare manualmente in Mercurial; Mercurial creerà automaticamente una filiale anonima per te se e quando ne avrai bisogno. La nomenclatura mercuriale è più intuitiva; non devi preoccuparti della differenza tra "fetch" e "pull" come fai con Git. Mercurial è un po 'meno difettoso. Esistono problemi di distinzione tra maiuscole e minuscole dei nomi di file che causavano problemi quando si spingevano progetti su piattaforme con Git e Mercurial; questo problema è stato risolto in Mercurial qualche tempo fa mentre non erano stati corretti in Git l'ultima volta che ho controllato. Puoi dire a Mercurial dei nomi dei file; con Git, se non rileva automaticamente la ridenominazione - una proposta molto positiva nella mia esperienza - la rinominazione non può essere tracciata affatto.

L'altra ragione della complicazione aggiuntiva di Git, tuttavia, è che gran parte di essa è necessaria per supportare funzionalità e potenza aggiuntive. Sì, è più complicato gestire le ramificazioni in Git - ma d'altra parte, una volta che hai i rami, non è troppo difficile fare cose con quei rami che sono praticamente impossibili in Mercurial. Ribaltare i rami è una di queste cose: puoi spostare il tuo ramo in modo che la sua base, invece di essere lo stato del tronco quando sei ramificato, sia ora lo stato del tronco; questo semplifica enormemente la cronologia delle versioni quando ci sono molte persone che lavorano sulla stessa base di codice, dal momento che è possibile far apparire sequenziali, anziché intrecciate, le spinte verso il trunk. Allo stesso modo, è molto più facile comprimere più commit sul tuo ramo in un unico commit,

In definitiva, penso che la scelta tra Mercurial e Git dovrebbe dipendere da quanto sono grandi i progetti di controllo della versione, misurati in termini di numero di persone che ci lavorano contemporaneamente. Se hai un gruppo di una dozzina o più che lavora su una singola applicazione web monolitica, ad esempio, i più potenti strumenti di gestione delle filiali di Git lo renderanno molto più adatto al tuo progetto. D'altra parte, se il tuo team sta sviluppando un sistema distribuito eterogeneo, con solo uno o due sviluppatori che lavorano contemporaneamente su un componente, l'utilizzo di un repository Mercurial per ciascuno dei progetti componenti consentirà allo sviluppo di procedere in modo più fluido con meno overhead di gestione del repository.

In conclusione: se hai una grande squadra che sviluppa una singola enorme applicazione, usa Git; se le singole applicazioni sono piccole, con qualsiasi scala proveniente dal numero anziché dalle dimensioni di tali applicazioni, utilizzare Mercurial.


4

Una differenza totalmente estranea agli stessi DVCS:

Git sembra essere molto popolare tra gli sviluppatori C. Git è il repository di fatto per il kernel Linux e questo potrebbe essere il motivo per cui è così popolare tra gli sviluppatori C. Ciò è particolarmente vero per coloro che hanno il lusso di lavorare solo nel mondo Linux / Unix.

Gli sviluppatori Java sembrano favorire Mercurial rispetto a Git. Ci sono forse due ragioni per questo: una è che un gran numero di progetti Java di grandi dimensioni sono ospitati su Mercurial, incluso lo stesso JDK. Un altro è che la struttura e la documentazione pulita di Mercurial fanno appello a persone provenienti dal campo di Java, mentre queste persone trovano Git incoerente nella denominazione dei comandi wrt e priva di documentazione. Non sto dicendo che in realtà è vero, sto dicendo che le persone si sono abituate a qualcosa dal loro solito habitat e quindi tendono a scegliere DVCS da quello.

Gli sviluppatori di Python preferiscono quasi esclusivamente Mercurial, immagino. In realtà non vi è alcuna ragione razionale per questo se non il fatto che Mercurial è basato su Python. (Uso anche Mercurial e non capisco davvero perché la gente faccia storie sul linguaggio di implementazione del DVCS. Non capisco una parola di Python e se non fosse per il fatto che è elencato da qualche parte che è basato su Python quindi non lo avrei saputo).

Non penso che tu possa dire che un DVCS si adatta a una lingua migliore di un'altra, quindi non dovresti scegliere tra quelle. Ma in realtà le persone scelgono (in parte) in base a quale DVCS vengono maggiormente esposte come parte della loro comunità.

(no, non ho statistiche di utilizzo per il backup delle mie affermazioni sopra .. è tutto basato sulla mia soggettività)

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.