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
.hgtags
file 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 bisect
comando in Mercurial (precedentemente estensione bisect ) è stato ispirato dal git bisect
comando in Git, mentre l'idea di è git bundle
stata 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 .hgtags
file 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
, remotes
o tags
, ad esempio, local-tags
per 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 .hgtags
speciale (il file nella struttura ad albero è trasferibile, ma ordinario è con versione), oppure ha tag solo locali ( .hg/localtags
non 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/bookmarks
file 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.default
variabile 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' --all
opzione 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, ^n
significa n-esimo genitore di un commit unione. Un suffisso ~n
per 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..B
Sintassi 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..B
dell'intervallo è del tutto prevedibile (e abbastanza utile) anche se A non è antenato di B: A..B
significa 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:B
sintassi 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...B
sintassi 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...B
per 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 addremove
per 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 --follow
dell'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 blame
comando è 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