it-swarm.com.de

Git und Mercurial - Vergleichen und Kontrastieren

Seit einiger Zeit benutze ich Subversion für meine persönlichen Projekte.

Immer mehr höre ich großartige Dinge über Git und Mercurial und DVCS im Allgemeinen.

Ich würde der ganzen DVCS-Sache gerne einen Strudel geben, aber ich bin mit beiden Optionen nicht allzu vertraut.

Was sind einige der Unterschiede zwischen Mercurial und Git?

Hinweis: Ich versuche nicht herauszufinden, welches das "beste" ist oder mit welchem ​​ich überhaupt beginnen sollte. Ich suche hauptsächlich nach Schlüsselbereichen, in denen sie ähnlich sind und in denen sie sich unterscheiden, weil ich interessiert bin, wie sie sich in Bezug auf Implementierung und Philosophie unterscheiden.

516
TM.

Disclaimer: Ich benutze Git, verfolge die Git-Entwicklung auf der Git-Mailingliste und trage sogar ein bisschen zu Git bei (hauptsächlich Gitweb). Ich kenne Mercurial aus der Dokumentation und einige aus der Diskussion auf #revctrl IRC channel on FreeNode.

Danke an alle Leute auf dem #Mercurial IRC Channel, die für diese Beschreibung Hilfe zu Mercurial bereitgestellt haben



Zusammenfassung

Hier wäre es schön, eine Syntax für die Tabelle zu haben, so etwas wie in PHPMarkdown/MultiMarkdown/Maruku-Erweiterung von Markdown

  • Repository-Struktur: Mercurial erlaubt keine Octopus-Zusammenführungen (mit mehr als zwei übergeordneten Objekten) und keine Kennzeichnung von nicht festgeschriebenen Objekten.
  • Tags: Mercurial verwendet versionierte .hgtags-Dateien mit speziellen Regeln für Repository-Tags und unterstützt auch lokale Tags in .hg/localtags. In Git-Tags befinden sich die Referenzen im refs/tags/-Namespace. Standardmäßig werden sie beim Abrufen automatisch befolgt und erfordern ein explizites Pushing.
  • Branches: In Mercurial basiert der grundlegende Workflow auf anonymen Köpfen ; Git verwendet einfache benannte Zweige und verfügt über spezielle Arten von Zweigen ( Remote-Tracking-Zweige ), die auf Zweige im Remote-Repository folgen.
  • Revisionsnamen und -bereiche: Mercurial liefert Revisionsnummern , lokal für das Repository, und basiert auf diesen relativen Revisionen (Zählung von der Spitze, dh dem aktuellen Zweig) und Revisionsbereichen local numbering; Git bietet eine Möglichkeit, sich auf die Revision relativ zum Branch-Tipp zu beziehen, und die Revisionsbereiche sind topologisch (basierend auf dem Revisionsdiagramm).
  • Mercurial verwendet Rename Tracking , während Git Rename Detection verwendet, um die Umbenennung von Dateien vorzunehmen
  • Network: Mercurial unterstützt die "intelligenten" SSH- und HTTP-Protokolle sowie das statische HTTP-Protokoll. Das moderne Git unterstützt die "intelligenten" SSH-, HTTP- und GIT-Protokolle sowie das "dumme" HTTP (S) -Protokoll. Beide unterstützen Bundles-Dateien für den Offline-Transport.
  • Mercurial verwendet - Erweiterungen (Plugins) und eine etablierte API. Git hat scriptability und etablierte Formate.

Es gibt ein paar Dinge, die Mercurial von Git unterscheiden, aber es gibt andere Dinge, die sie ähnlich machen. Beide Projekte leihen sich gegenseitig Ideen aus. Der Befehl hg bisect in Mercurial (ehemals bisect extension ) wurde beispielsweise von dem Befehl git bisect in Git inspiriert, während die Idee von git bundle von hg bundle inspiriert wurde.

Repository-Struktur, Speichern von Revisionen

In Git gibt es vier Arten von Objekten in der Objektdatenbank: blob Objekte, die den Inhalt einer Datei enthalten, hierarchische tree Objekte, in denen die Verzeichnisstruktur gespeichert ist, einschließlich der Dateinamen und der relevanten Teile der Datei Berechtigungen (ausführbare Berechtigung für Dateien, die ein symbolischer Link sind), commit Objekt, das Autoreninformationen enthält, Zeiger auf den Status des Repositorys bei Revision, dargestellt durch einen Commit (über ein Baumobjekt des obersten Verzeichnisses des Projekts) und Verweise auf null oder mehr übergeordnete Commits und tag Objekte, die auf andere Objekte verweisen und mit PGP/GPG signiert werden können.

Git verwendet zwei Möglichkeiten zum Speichern von Objekten: Loose Format, wobei jedes Objekt in einer separaten Datei gespeichert wird (diese Dateien werden einmal geschrieben und nie geändert), und Gepackt Format, in dem viele Objekte enthalten sind werden in einer einzigen Datei deltakomprimiert gespeichert. Die Atomarität von Operationen wird durch die Tatsache bereitgestellt, dass nach dem Schreiben eines Objekts ein Verweis auf ein neues Objekt geschrieben wird (atomar unter Verwendung des Tricks "Erstellen + Umbenennen").

Git-Repositorys müssen regelmäßig mit git gc gewartet werden (um Speicherplatz zu sparen und die Leistung zu verbessern), obwohl Git dies heutzutage automatisch tut. (Diese Methode bietet eine bessere Komprimierung von Repositorys.)

Mercurial speichert (soweit ich es verstehe) den Verlauf einer Datei in einem filelog (zusammen, glaube ich, mit zusätzlichen Metadaten wie dem Umbenennungs-Tracking und einigen Hilfsinformationen). Es verwendet die flache Struktur manifest zum Speichern der Verzeichnisstruktur und die Struktur changelog zum Speichern von Informationen zu Änderungssätzen (Revisionen), einschließlich der Festschreibungsnachricht und null, einem oder zwei übergeordneten Elementen.

Mercurial verwendet Transaktionsjournal , um die Einheitlichkeit der Operationen zu gewährleisten, und verwendet Abschneiden Dateien, um nach einer fehlgeschlagenen oder unterbrochenen Operation zu bereinigen. Revlogs können nur angehängt werden.

Wenn man die Repository-Struktur in Git im Vergleich zu Mercurial betrachtet, sieht man, dass Git eher einer Objektdatenbank (oder einem inhaltsadressierten Dateisystem) gleicht und Mercurial eher einer herkömmlichen relationalen Datenbank mit festen Feldern.

Unterschiede:
In Git bilden die tree Objekte eine hierarchische Struktur; in Mercurial manifest Datei ist flat Struktur. In Git blob object store eine Version eines Inhalts einer Datei; in Mercurial filelog stores gesamte Historie einer einzelnen Datei (wenn wir hier keine Komplikationen bei Umbenennungen berücksichtigen). Dies bedeutet, dass es verschiedene Bereiche von Operationen gibt, in denen Git schneller ist als Mercurial, alle anderen Dinge als gleich angesehen werden (wie Zusammenführen oder Anzeigen des Verlaufs eines Projekts), und Bereiche, in denen Mercurial schneller ist als Git (wie Anwenden von Patches oder Anzeigen) Geschichte einer einzelnen Datei). Dieses Problem ist für den Endbenutzer möglicherweise nicht wichtig.

Aufgrund der festen Datensatzstruktur von Mercurials changelog -Struktur können Commits in Mercurial nur bis zu zwei Eltern ; Commits in Git können mehr als zwei Eltern haben (sog. "Octopus Merge"). Während Sie (theoretisch) Octopus Merge durch eine Reihe von übergeordneten Merges ersetzen können, kann dies bei der Konvertierung zwischen Mercurial- und Git-Repositorys zu Komplikationen führen.

Soweit ich weiß, hat Mercurial keine Entsprechung zu annotierten Tags (Tag-Objekten) von Git. Ein Sonderfall für mit Anmerkungen versehene Tags ist signierte Tags (mit PGP/GPG-Signatur); äquivalent in Mercurial kann mit GpgExtension erstellt werden, welche Erweiterung zusammen mit Mercurial verteilt wird. Sie können in Mercurial nicht tag non-commit object wie in Git, aber das ist meiner Meinung nach nicht sehr wichtig (einige Git-Repositorys verwenden tagged blob, um öffentliche PGP-Schlüssel zu verteilen zu verwenden, um signierte Tags zu verifizieren).

Referenzen: Branchen und Tags

In Git befinden sich Referenzen (Zweige, Remote-Tracking-Zweige und Tags) außerhalb der DAG von Commits (wie sie sollten). Referenzen im refs/heads/-Namespace ( local branches ) verweisen auf Commits und werden normalerweise durch "git commit" aktualisiert. sie zeigen auf die Spitze eines Astes, deshalb dieser Name. Verweise im refs/remotes/<remotename>/-Namespace ( remote-tracking branches ) müssen festgeschrieben werden, folgen den Verzweigungen im Remote-Repository <remotename> und werden durch "git fetch" oder ein gleichwertiges Update aktualisiert. Verweise im refs/tags/-Namespace ( tags ) verweisen normalerweise auf Commits (Lightweight-Tags) oder Tag-Objekte (kommentierte und signierte Tags) und sind nicht dazu gedacht, sich zu ändern.

Stichworte

In Mercurial können Sie der Revision einen dauerhaften Namen geben, indem Sie tag ; Tags werden ähnlich wie Ignoriermuster gespeichert. Dies bedeutet, dass global sichtbare Tags in der revisionsgesteuerten Datei .hgtags in Ihrem Repository gespeichert werden. Dies hat zwei Konsequenzen: Erstens muss Mercurial spezielle Regeln für diese Datei anwenden, um die aktuelle Liste aller Tags abzurufen und diese Datei zu aktualisieren (z. B. liest es die zuletzt festgeschriebene Revision der Datei, die derzeit nicht ausgecheckt ist). Zweitens müssen Sie Änderungen an dieser Datei vornehmen, damit neue Tags für andere Benutzer/andere Repositorys sichtbar sind (soweit ich das verstehe).

Mercurial unterstützt auch lokale Tags , die in hg/localtags gespeichert sind und für andere nicht sichtbar sind (und natürlich nicht übertragbar sind)

In Git-Tags sind feste (konstante) benannte Verweise auf andere Objekte (normalerweise Tag-Objekte, die wiederum auf Commits verweisen), die im Namespace refs/tags/ gespeichert sind. Standardmäßig ruft git beim Abrufen oder Verschieben eines Revisionssatzes automatisch Tags ab oder verschiebt sie, die auf Revisionen verweisen, die abgerufen oder verschoben werden. Trotzdem können Sie steuern bis zu einem gewissen Grad welche Tags abgerufen oder verschoben werden.

Git behandelt Lightweight-Tags (die direkt auf Commits verweisen) und Annotated-Tags (die auf Tag-Objekte verweisen, die Tag-Nachrichten enthalten, die optional PGP-Signaturen enthalten, die wiederum auf Commits verweisen) leicht unterschiedlich, z. B. werden standardmäßig nur Annotated-Tags bei der Beschreibung berücksichtigt schreibt mit "git describe" fest.

Git hat kein striktes Äquivalent zu lokalen Tags in Mercurial. Dennoch empfehlen die Best Practices von git, ein separates öffentliches Bare-Repository einzurichten, in das Sie Push-fähige Änderungen übertragen und von dem andere klonen und abrufen. Dies bedeutet, dass Tags (und Zweige), die Sie nicht pushen, für Ihr Repository privat sind. Andererseits können Sie auch einen anderen Namespace als heads, remotes oder tags verwenden, z. B. local-tags für lokale Tags.

Persönliche Meinung: Meiner Meinung nach sollten Tags außerhalb des Revisionsgraphen liegen, da sie außerhalb des Graphen liegen (sie sind Zeiger auf das Revisionsgraphen). Tags sollten nicht versioniert, aber übertragbar sein. Die Entscheidung von Mercurial, einen ähnlichen Mechanismus wie den zum Ignorieren von Dateien zu verwenden, bedeutet, dass entweder .hgtags speziell behandelt werden muss (Datei-In-Tree ist übertragbar, aber normal versioniert) oder Tags vorhanden sind, die nur lokal sind (.hg/localtags ist nicht lokal). versioniert, aber nicht übertragbar).

Geäst

In Git ist local branch (branch tip oder branch head) ein benannter Verweis auf ein Commit, in dem neue Commits erstellt werden können. Verzweigung kann auch aktive Entwicklungslinie bedeuten, d. H. Alle von der Verzweigungsspitze aus erreichbaren Festschreibungen. Lokale Zweige befinden sich im refs/heads/-Namespace, z. Der vollqualifizierte Name des 'master'-Zweigs ist' refs/heads/master '.

Die aktuelle Verzweigung in Git (dh die ausgecheckte Verzweigung und die Verzweigung, in die die neue Festschreibung gehen soll) ist die Verzweigung, auf die durch die Referenz HEAD Man kann HEAD) verweisen = direkt auf ein Commit zeigen, anstatt eine symbolische Referenz zu sein; diese Situation, in einem anonymen unbenannten Zweig zu sein, heißt detached HEAD ("Git-Zweig" zeigt, dass Sie es sind auf '(kein Zweig)').

In Mercurial gibt es anonyme Zweige (Zweigköpfe) und man kann Lesezeichen verwenden (über Lesezeichenerweiterung ). Solche bookmark branches sind rein lokal, und diese Namen waren (bis Version 1.6) mit Mercurial nicht übertragbar. Sie können rsync oder scp verwenden, um die Datei .hg/bookmarks in ein Remote-Repository zu kopieren. Sie können auch hg id -r <bookmark> <url> verwenden, um die Versions-ID eines aktuellen Lesezeichentipps abzurufen.

Seit 1.6 können Lesezeichen verschoben/gezogen werden. Die Seite BookmarksExtension enthält einen Abschnitt zu Arbeiten mit Remote-Repositorys . Es gibt einen Unterschied darin, dass in Mercurial die Lesezeichennamen global sind, während die Definition von 'remote' in Git auch Zuordnung von Zweignamen von den Namen im Remote-Repository zu den Namen von local beschreibt Remote-Tracking-Filialen; Zum Beispiel bedeutet refs/heads/*:refs/remotes/Origin/* Mapping, dass man den Status des 'Master'-Zweigs (' refs/heads/master ') im Remote-Repository im' Origin/master'-Remote-Tracking-Zweig ('refs/remotes/Origin/master') finden kann. .

Mercurial hat auch sogenannte named branches , wobei der Branchenname embedded in einem Commit (in einem Changeset) ist. Ein solcher Name ist global (wird beim Abrufen übertragen). Diese Filialnamen werden permanent als Teil der Metadaten des Änderungssatzes aufgezeichnet. Mit modernem Mercurial können Sie "named branch" schließen und die Aufzeichnung des Filialnamens beenden. Bei diesem Mechanismus werden die Astspitzen im laufenden Betrieb berechnet.

Mercurials "named branches" sollten meiner Meinung nach commit labels heißen, weil es das ist, was sie sind. Es gibt Situationen, in denen "named branch" mehrere Tipps haben kann (mehrere untergeordnete Festschreibungen) und auch aus mehreren nicht zusammenhängenden Teilen des Revisionsdiagramms bestehen kann.

Es gibt kein Äquivalent dieser Mercurial "eingebetteten Zweige" in Git; Darüber hinaus ist Gits Philosophie, dass man zwar sagen kann, dass ein Zweig ein Commit enthält, dies aber nicht bedeutet, dass ein Commit zu einem Zweig gehört.

Beachten Sie, dass in der Mercurial-Dokumentation weiterhin die Verwendung separater Klone (separate Repositorys) zumindest für langlebige Zweige (einzelner Zweig pro Repository-Workflow) vorgeschlagen wird, auch bekannt als Verzweigen durch Klonen .

Zweige beim Schieben

Mercurial drückt standardmäßig alle Köpfe . Wenn Sie einen einzelnen Zweig pushen möchten ( single head ), müssen Sie die aktuelle Revision des Zweigs angeben, den Sie pushen möchten. Sie können den Verzweigungstipp anhand der Versionsnummer (lokal für das Repository), der Versionskennung, des Lesezeichennamens (lokal für das Repository, wird nicht übertragen) oder des Namens der eingebetteten Verzweigung (benannte Verzweigung) angeben.

Wenn Sie eine Reihe von Revisionen pushen, die Commits enthalten, die im Mercurial-Sprachgebrauch als "benannter Zweig" gekennzeichnet sind, haben Sie diesen "benannten Zweig" im Repository, in das Sie pushen. Dies bedeutet, dass die Namen solcher eingebetteten Zweige ("benannte Zweige") global sind (in Bezug auf Klone eines bestimmten Repositorys/Projekts).

Standardmäßig (abhängig von der Konfigurationsvariablen Push.default) "git Push" oder "git Push <"fernbedienung> "Git würde übereinstimmende Zweige pushen, dh nur die lokalen Zweige, deren Entsprechung bereits im Remote-Repository vorhanden ist, in das Sie pushen. Sie können die Option --all verwenden, um git-Push (" git Drücken Sie --all "), um all branches zu drücken. Sie können" git Push <"verwendenfernbedienung> <ast> "um einen gegebener einzelner Zweig zu pushen, und Sie können" git Push <verwendenfernbedienung> HEAD "auf Push current branch .

In allen oben genannten Fällen wird davon ausgegangen, dass Git nicht konfiguriert ist, der über remote.<remotename>.Push-Konfigurationsvariablen zu Push verzweigt.

Zweige beim Holen

Hinweis: hier verwende ich die Git-Terminologie, wobei "fetch" das Herunterladen von Änderungen aus dem Remote-Repository bedeutet ohne Integration dieser Änderungen in die lokale Arbeit. Dies ist, was "git fetch" und "hg pull" tun.

Wenn ich es richtig verstehe, holt Mercurial standardmäßig alle Köpfe aus dem Remote-Repository, aber Sie können den abzurufenden Zweig über "hg pull --rev <rev> <url>" oder "hg pull <url>#<rev>" angeben, um ) zu erhalten + einzelner Zweig . Sie können <rev> mit der Revisions-ID, dem Namen der benannten Verzweigung (in das Changelog eingebettete Verzweigung) oder dem Namen des Lesezeichens angeben. Der Name des Lesezeichens wird jedoch (zumindest derzeit) nicht übertragen. Alle "named branches" -Revisionen, die Sie erhalten, werden übertragen. "hg pull" speichert die Spitzen der Zweige, die es als anonyme, unbenannte Köpfe abruft.

In Git standardmäßig (für 'Origin' Remote, das mit "git clone" erstellt wurde, und für Remotes, die mit "git remote add" erstellt wurden) erhält "git fetch" (oder "git fetch <remote>") all branches aus dem Remote-Repository (aus dem refs/heads/-Namespace) und speichert sie im refs/remotes/-Namespace. Dies bedeutet zum Beispiel, dass der Zweig mit dem Namen 'master' (vollständiger Name: 'refs/heads/master') in 'Origin' als 'Origin/master' gespeichert (gespeichert) wird Zweig mit Fernverfolgung ( vollständiger Name: 'refs/remotes/Origin/master').

Sie können single branch in Git abrufen, indem Sie git fetch <remote> <branch> verwenden - Git würde die angeforderten Zweige in FETCH_HEAD speichern, was Mercurial unbenannten Köpfen ähnelt.

Dies sind nur Beispiele für Standardfälle mit leistungsstarker refspec Git-Syntax: Mit refspecs können Sie angeben und/oder konfigurieren, welche Zweige abgerufen und wo sie gespeichert werden sollen. Beispiel: Der Standardfall "Alle Zweige abrufen" wird durch "+ refs/heads/*: refs/remotes/Origin/*" als Platzhalter angegeben, und "Einzelnen Zweig abrufen" ist eine Abkürzung für "refs/heads/<branch>:". . Refspecs werden verwendet, um Namen von Zweigen (Refs) im Remote-Repository lokalen Refs-Namen zuzuordnen. Sie müssen jedoch nicht viel über refspecs wissen, um effektiv mit Git arbeiten zu können (hauptsächlich dank des Befehls "git remote").

Persönliche Meinung: Ich persönlich denke, dass "Named Branches" (mit in Changeset-Metadaten eingebetteten Branchennamen) in Mercurial mit seinem globalen Namespace ein fehlgeleitetes Design sind, insbesondere für ein verteiltes Versionskontrollsystem. Nehmen wir zum Beispiel den Fall, dass sowohl Alice als auch Bob in ihren Repositorys einen Zweig namens 'for-joe' "named branch" haben, Zweige, die nichts gemeinsam haben. In Joes Repository würden diese beiden Zweige jedoch als ein einziger Zweig misshandelt. Sie haben sich also eine Konvention ausgedacht, die vor Namenskonflikten schützt. Dies ist kein Problem mit Git, wo in Joes Repository 'for-joe' Zweig von Alice 'alice/for-joe' wäre und von Bob 'bob/for-joe'. Siehe auch Trennen des Filialnamens von der Filialidentität Problem im Mercurial-Wiki.

Mercurials "Bookmark Branches" fehlen derzeit die Kernverteilungsmechanismen.

Unterschiede:
Dieser Bereich ist einer der Hauptunterschiede zwischen Mercurial und Git, wie James Woodyatt und Steve Losh in ihren Antworten sagten. Standardmäßig verwendet Mercurial anonyme Lightweight-Codelines, die in ihrer Terminologie als "Köpfe" bezeichnet werden. Git verwendet einfache benannte Zweige mit injektiver Zuordnung, um Namen von Zweigen im Remote-Repository den Namen von Remote-Tracking-Zweigen zuzuordnen. Git "zwingt" Sie, Zweige zu benennen (nun, mit Ausnahme eines einzelnen unbenannten Zweigs, Situation, die als abgetrennter HEAD bezeichnet wird), aber ich denke, dies funktioniert besser mit verzweigungsintensiven Workflows wie dem Zweig-Workflow, dh mehreren Zweigen in einem einzelnen Repository-Paradigma.

Revisionen benennen

In Git gibt es viele Möglichkeiten, Revisionen zu benennen (beschrieben z. B. in git rev-parse manpage):

  • Der vollständige SHA1-Objektname (40-Byte-Hexadezimalzeichenfolge) oder eine Teilzeichenfolge davon, die im Repository eindeutig ist
  • Ein symbolischer Referenzname, z.B. 'master' (bezogen auf 'master' branch) oder 'v1.5.0' (bezogen auf tag) oder 'Origin/next' (bezogen auf remote-tracking branch)
  • Ein Suffix ^ to revision-Parameter bedeutet das erste übergeordnete Element eines Festschreibungsobjekts, ^n bedeutet das n-te übergeordnete Element einer Zusammenführungsfestschreibung. Ein Suffix ~n to revision parameter steht für den n-ten Vorgänger eines Commits in der geraden ersten übergeordneten Zeile. Diese Suffixe können kombiniert werden, um einen Revisionsspezifizierer zu bilden, der einem Pfad von einer symbolischen Referenz folgt, z. 'pu ~ 3 ^ 2 ~ 3'
  • Ausgabe von "git describe", dh einem nächstgelegenen Tag, optional gefolgt von einem Bindestrich und einer Anzahl von Commits, gefolgt von einem Bindestrich, einem "g" und einem abgekürzten Objektnamen, zum Beispiel "v1.6.5.1-75-". g5bf8097 '.

Es gibt auch Revisionsspezifizierer, bei denen es sich um ein Reflog handelt, das hier nicht erwähnt wird. In Git hat jedes Objekt, sei es ein Commit, ein Tag, ein Baum oder ein Blob, seine SHA-1-Kennung. Es gibt eine spezielle Syntax wie z. 'next: Documentation' oder 'next: README', um auf Baum (Verzeichnis) oder Blob (Dateiinhalt) in der angegebenen Revision zu verweisen.

Mercurial hat auch viele Möglichkeiten, Changesets zu benennen (beschrieben z. B. in hg manpage):

  • Eine einfache Ganzzahl wird als Revisionsnummer behandelt. Man muss bedenken, dass die Revisionsnummern lokal für das angegebene Repository sind ; In anderen Repositorys können sie unterschiedlich sein.
  • Negative Ganzzahlen werden als sequenzielle Offsets von der Spitze behandelt, wobei -1 die Spitze bezeichnet, -2 die Revision vor der Spitze bezeichnet und so weiter. Sie sind auch local zum Repository.
  • Eine eindeutige Revisionskennung (40-stellige hexadezimale Zeichenfolge) oder deren eindeutiges Präfix.
  • Ein Tag-Name (symbolischer Name, der mit einer bestimmten Revision verknüpft ist) oder ein Lesezeichenname (mit der Erweiterung: symbolischer Name, der mit einem bestimmten Kopf verknüpft ist, lokal für das Repository) oder ein "benannter Zweig" (Commit-Label; Revision, die mit "benannter Zweig" verknüpft ist) ist tip (childless commit) aller Commits mit angegebenem Commit-Label, mit der größten Revisionsnummer, wenn es mehr als einen solchen Tip gibt)
  • Der reservierte Name "tip" ist ein spezielles Tag, das immer die letzte Revision kennzeichnet.
  • Der reservierte Name "null" gibt die Null-Revision an.
  • Der reservierte Name "." Gibt das übergeordnete Arbeitsverzeichnis an.

Differences
Wie Sie im Vergleich der obigen Listen sehen können, bietet Mercurial Revisionsnummern an, die lokal im Repository gespeichert sind, während Git dies nicht tut. Andererseits bietet Mercurial relative Offsets nur von 'tip' (aktueller Zweig) an, die für das Repository lokal sind (zumindest ohne ParentrevspecExtension ), während Git das Festschreiben von Commits, die von jedem Tipp folgen, zulässt.

Die letzte Revision heißt HEAD in Git und "tip" in Mercurial; es gibt keine Null-Revision in Git. Sowohl Mercurial als auch Git können viele Root-Commits haben (können mehr als ein übergeordnetes Commit haben) Dies ist in der Regel das Ergebnis früher getrennter Projekte.

Siehe auch: Viele verschiedene Arten von Revisionsspezifizierern Artikel in Elijahs Blog (Newren's).

Persönliche Meinung: Ich denke, dass Revisionsnummern überbewertet sind (zumindest für verteilte Entwicklung und/oder nichtlineare/verzweigte Geschichte). Erstens müssen sie für ein verteiltes Versionskontrollsystem entweder lokal für das Repository sein oder ein bestimmtes Repository in besonderer Weise als zentrale Nummerierungsbehörde behandeln. Zweitens können größere Projekte mit längerer Historie eine Revisionszahl im 5 - stelligen Bereich aufweisen, sodass sie nur einen geringen Vorteil gegenüber den auf 6-7 Zeichen verkürzten Revisionskennungen bieten und eine strikte Reihenfolge implizieren, während Revisionen nur teilweise geordnet sind (ich meine hier das) Revisionen n und n + 1 müssen nicht Eltern und Kind sein).

Revisionsbereiche

In Git-Revisionsbereichen sind topologisch . Die häufig verwendete A..B-Syntax, die für die lineare Historie bedeutet, dass der Revisionsbereich bei A beginnt (aber A ausschließt) und bei B endet (dh der Bereich ist von unten offen ), ist eine Kurzform ("syntaktischer Zucker") für ^A B. Dies bedeutet, dass das Verhalten von A..B auch dann vollständig vorhersehbar (und sehr nützlich) ist, wenn A kein Vorfahr von B ist: A..B bedeutet dann Revisionsbereich vom gemeinsamen Vorfahren von A und B (Basis zusammenführen) bis zur Revision B.

In Mercurial basieren die Revisionsbereiche auf dem Bereich von Revisionsnummern . Der Bereich wird mit der Syntax A:B angegeben und im Gegensatz zum Git-Bereich als geschlossenes Intervall . Der Bereich B: A ist auch der Bereich A: B in umgekehrter Reihenfolge, was bei Git nicht der Fall ist (siehe jedoch den folgenden Hinweis zur Syntax von A...B). Eine solche Einfachheit ist jedoch mit einem Preis verbunden: Der Revisionsbereich A: B ist nur dann sinnvoll, wenn A ein Vorfahr von B ist oder umgekehrt, d. H. Mit linearer Historie; Andernfalls (ich denke das) ist der Bereich unvorhersehbar und das Ergebnis ist lokal für das Repository (da Revisionsnummern lokal für das Repository sind).

Dies wurde mit Mercurial 1.6 behoben, das den neuen topologischen Revisionsbereich hat, wobei 'A..B' (oder 'A :: B') als die Menge der Änderungssätze verstanden wird, die sind beide Nachkommen von X und Vorfahren von Y. Dies ist, denke ich, äquivalent zu '--ancestry-path A..B' in Git.

Git hat auch die Notation A...B für symmetrische Revisionsunterschiede; es bedeutet A B --not $(git merge-base A B), was bedeutet, dass alle Commits von A oder B erreichbar sind, aber nicht alle Commits, die von beiden erreichbar sind (erreichbar von gemeinsamen Vorfahren).

Benennt um

Mercurial verwendet Rename Tracking , um die Umbenennung von Dateien durchzuführen. Dies bedeutet, dass die Informationen darüber, dass eine Datei umbenannt wurde, zum Zeitpunkt des Festschreibens gespeichert werden. In Mercurial werden diese Informationen in der Form "Enhanced Diff" in den Metadaten Filelog (File Revlog) gespeichert. Dies hat zur Folge, dass Sie hg rename/hg mv... verwenden müssen oder hg addremove ausführen müssen, um eine auf Ähnlichkeiten basierende Umbenennungserkennung durchzuführen.

Git ist einzigartig unter Versionskontrollsystemen, da es Rename Detection verwendet, um die Umbenennung von Dateien durchzuführen. Dies bedeutet, dass die Tatsache, dass die Datei umbenannt wurde, zu dem Zeitpunkt erkannt wird, an dem sie benötigt wird: beim Zusammenführen oder beim Anzeigen eines Vergleichs (falls angefordert/konfiguriert). Dies hat den Vorteil, dass der Umbenennungserkennungsalgorithmus verbessert werden kann und zum Zeitpunkt des Festschreibens nicht eingefroren wird.

Sowohl Git als auch Mercurial erfordern die Verwendung der Option --follow, um den Umbenennungen zu folgen, wenn der Verlauf einer einzelnen Datei angezeigt wird. Beide können umbenannt werden, wenn der zeilenweise Verlauf einer Datei in git blame/hg annotate angezeigt wird.

In Git kann der Befehl git blame der Codebewegung folgen und auch Code von einer Datei in die andere verschieben (oder kopieren), selbst wenn die Codebewegung nicht Teil einer vollständigen Dateiumbenennung ist. Soweit ich weiß, gibt es diese Funktion nur bei Git (zum Zeitpunkt des Schreibens, Oktober 2009).

Netzwerkprotokolle

Sowohl Mercurial als auch Git unterstützen das Abrufen von und das Pushen zu Repositorys im selben Dateisystem, wobei die Repository-URL nur ein Dateisystempfad zum Repository ist. Beide unterstützen auch das Abrufen von Bundle-Dateien .

Mercurial unterstützt das Abrufen und Pushen über SSH und über HTTP-Protokolle. Für SSH benötigt man ein zugängliches Shell-Konto auf dem Zielcomputer und eine Kopie von hg installiert/verfügbar. Für den HTTP-Zugriff ist das Ausführen des Skripts hg-serve oder Mercurial CGI erforderlich, und Mercurial muss auf dem Server installiert sein.

Git unterstützt zwei Arten von Protokollen für den Zugriff auf das Remote-Repository:

  • "intelligente" Protokolle , die den Zugriff über SSH und über ein benutzerdefiniertes git: // -Protokoll (von git-daemon) umfassen, erfordern, dass git auf dem Server installiert ist. Der Austausch in diesen Protokollen besteht darin, dass Client und Server darüber verhandeln, welche Objekte sie gemeinsam haben, und dann eine Paketdatei generieren und senden. Modern Git unterstützt das "intelligente" HTTP-Protokoll.
  • "blöde" Protokolle , die HTTP und FTP (nur zum Abrufen) und HTTPS (zum Pushen über WebDAV) enthalten, erfordern keine Installation von Git auf dem Server, erfordern jedoch, dass das Repository zusätzliche Informationen enthält, die von generiert werden git update-server-info (wird normalerweise von einem Hook ausgeführt). Der Austausch besteht darin, dass der Client die Commit-Kette durchläuft und bei Bedarf lose Objekte und Paketdateien herunterlädt. Der Nachteil ist, dass das Herunterladen mehr als unbedingt erforderlich ist (z. B. in Eckfällen, in denen nur eine einzige Paketdatei vorhanden ist, wird die Datei auch dann vollständig heruntergeladen, wenn nur wenige Revisionen abgerufen werden), und dass möglicherweise viele Verbindungen erforderlich sind, um fertig zu werden.

Erweitern: Skriptfähigkeit vs. Erweiterungen (Plugins)

Mercurial ist in Python implementiert, wobei einige Kerncodes aus Performancegründen in C geschrieben sind. Es bietet eine API zum Schreiben von - Erweiterungen (Plugins), um zusätzliche Funktionen hinzuzufügen. Einige Funktionen, z. B. "Lesezeichenzweige" oder Überarbeitungen beim Signieren, sind in den mit Mercurial gelieferten Erweiterungen enthalten und müssen aktiviert werden.

Git ist in [~ # ~] c [~ # ~] , Perl und Shell-Skripten implementiert . Git bietet viele Befehle auf niedriger Ebene ( plumbing ), die zur Verwendung in Skripten geeignet sind. Die übliche Art, neue Funktionen einzuführen, besteht darin, sie als Perl- oder Shell-Skript zu schreiben. Wenn sich die Benutzeroberfläche stabilisiert, schreiben Sie sie aus Performance- und Portabilitätsgründen in C neu. Im Fall von Shell-Skripten werden Eckfälle vermieden (diese Prozedur heißt builtinification) ).

Git basiert auf [Repository] -Formaten und [Netzwerk] -Protokollen. Anstelle von Sprachbindungen gibt es (teilweise oder vollständig) Neuimplementierungen von Git in anderen Sprachen (einige davon sind teilweise Neuimplementierungen und schließen Git-Befehle teilweise um): JGit (Java, von EGit verwendet, Eclipse Git Plugin ), Grit (Ruby), Dulwich (Python), Git # (C #).


TL; DR

446
Jakub Narębski

Ich denke, Sie können ein Gefühl dafür bekommen, in welchen Systemen diese beiden Videos ähnlich oder unterschiedlich sind:

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

Beide sind im Design sehr ähnlich, aber in den Implementierungen sehr unterschiedlich.

Ich benutze Mercurial. Soweit ich Git verstehe, unterscheidet sich git hauptsächlich dadurch, dass es den Inhalt von Dateien anstelle von Dateien selbst verfolgt. Wenn Sie eine Funktion von einer Datei in eine andere verschieben, sagt Linus, dass Git Ihnen den Verlauf dieser einzelnen Funktion während des Verschiebens mitteilt.

Sie sagen auch, dass Git über HTTP langsamer ist, aber ein eigenes Netzwerkprotokoll und einen eigenen Server hat.

Git funktioniert besser als ein SVN-Thick-Client als Mercurial. Sie können gegen einen SVN-Server ziehen und drücken. Diese Funktionalität befindet sich in Mercurial noch in der Entwicklung

Sowohl Mercurial als auch Git haben sehr gute Webhosting-Lösungen zur Verfügung (BitBucket und GitHub), aber Google Code unterstützt nur Mercurial. Übrigens haben sie einen sehr detaillierten Vergleich von Mercurial und Git, die sie gemacht haben, um zu entscheiden, welches unterstützt werden soll ( http://code.google.com/p/support/wiki/DVCSAnalysis ). Es hat viele gute Infos.

56
artemb

Ich habe vor einiger Zeit einen Blogeintrag über Mercurials Verzweigungsmodelle geschrieben und Vergleiche mit dem Verzweigungsmodell von git aufgenommen. Vielleicht findest du es interessant: http://stevelosh.com/blog/entry/2009/8/30/a-guide-to-branching-in-Mercurial/

30
Steve Losh

Ich benutze beide ziemlich regelmäßig. Der wesentliche funktionale Unterschied besteht in der Art und Weise, in der Git- und Mercurial-Namen in Repositorys verzweigt sind. Bei Mercurial werden Zweignamen geklont und zusammen mit ihren Changesets abgerufen. Wenn Sie Änderungen an einem neuen Zweig in Mercurial hinzufügen und in ein anderes Repository verschieben, wird der Zweigname gleichzeitig verschoben. Daher sind Zweigstellennamen in Mercurial mehr oder weniger global, und Sie müssen die Bookmark-Erweiterung verwenden, um nur lokale Lightweight-Namen zu verwenden (wenn Sie möchten). Mercurial verwendet standardmäßig anonyme Lightweight-Codelines, die in der Terminologie verwendet werden genannt "Köpfe"). In Git werden Zweignamen und ihre injektive Zuordnung zu Remote-Zweigen lokal gespeichert, und Sie müssen sie explizit verwalten, was bedeutet, dass Sie wissen, wie das geht. Hier hat Git den Ruf, dass es schwieriger zu erlernen und anzuwenden ist als Mercurial.

Wie andere hier bemerken werden, gibt es viele, viele kleine Unterschiede. Die Sache mit den Zweigen ist das große Unterscheidungsmerkmal.

25
james woodyatt

Schauen Sie sich Git vs. Mercurial: Please Relax den Blog-Beitrag von Patrick Thomson an, in dem er schreibt:
Git ist MacGyver , Mercurial ist James Bond

Beachten Sie, dass dieser Blog-Beitrag vom 7. August 2008 stammt und beide SCM-Funktionen seitdem erheblich verbessert wurden.

19
Jakub Narębski

Mercurial ist fast vollständig in Python geschrieben. Der Kern von Git ist in C geschrieben (und sollte schneller sein als der von Mercurial), und die Tools sind in sh, Perl, tcl geschrieben und verwenden standardmäßige GNU utils. Daher muss er alle diese Utils und Interpreter mitbringen es zu einem System, das sie nicht enthält (zB Windows).

Beide Unterstützungen funktionieren mit SVN, obwohl die AFAIK-SVN-Unterstützung für Git unter Windows nicht funktioniert (möglicherweise bin ich nur unglücklich/lahm, wer weiß). Es gibt auch Erweiterungen, mit denen Git und Mercurial zusammenarbeiten können.

Mercurial hat Nice Visual Studio-Integration . Als ich das letzte Mal nachgesehen habe, Plugin für Git hat funktioniert, war aber extrem langsam.

Die grundlegenden Befehlssätze sind sehr ähnlich (init, clone, add, status, commit, push, pull usw.). Der grundlegende Arbeitsablauf ist also derselbe. Es gibt auch einen TortoiseSVN-ähnlichen Client für beide.

Erweiterungen für Mercurial können in python (keine Überraschung!) Und für Git in jeder ausführbaren Form (ausführbare Binärdatei, Shell-Skript usw.) geschrieben werden. Einige Erweiterungen sind verrückt mächtig, wie git bisect.

11
elder_george

Wenn Sie gute Windows-Unterstützung benötigen, bevorzugen Sie möglicherweise Mercurial. TortoiseHg (Windows Explorer Plugin) bietet eine einfach zu bedienende grafische Oberfläche für ein ziemlich komplexes Tool. Als Status haben Sie hier auch ein Visual Studio-Plugin . Als ich es das letzte Mal versuchte, funktionierte die SVN-Oberfläche unter Windows nicht so gut.

Wenn Ihnen die Befehlszeilenschnittstelle nichts ausmacht, würde ich Git empfehlen. Nicht aus technischen Gründen, sondern aus strategischen Gründen. Die Adoptionsrate von Git ist viel höher. Sehen Sie sich nur an, wie viele berühmte Open Source-Projekte von CVS/SVN auf Mercurial und wie viele auf Git umsteigen. Sehen Sie, wie viele Code-/Projekt-Hosting-Anbieter Sie mit Git-Unterstützung im Vergleich zu Mercurial-Hosting finden.

11
Eric Darchis

Nachdem ich alles durchgelesen hatte, dass Mercurial einfacher ist (was ich immer noch glaube, obwohl die Internet-Community der Meinung ist), hatte ich das Gefühl, dass es für mich relativ einfacher ist, mich an Git anzupassen (ich habe angefangen) mit Mercurial mit TortoiseHg) bei der Arbeit von der Kommandozeile aus hauptsächlich, weil die git-Kommandos nach mir passend benannt wurden und weniger zahlreich sind. Mercurial hat verschiedene Benennung für jeden Befehl, der einen bestimmten Job ausführt, während Git-Befehle je nach Situation vielseitig verwendbar sind (z. B. checkout). Während Git damals schwieriger war, ist der Unterschied heute kaum noch erheblich. YMMV .. Mit einem guten GUI-Client wie TortoiseHg war es viel einfacher, mit Mercurial zu arbeiten, und ich musste mich nicht an die etwas verwirrenden Befehle erinnern. Ich gehe nicht im Detail darauf ein, wie jeder Befehl für dieselbe Aktion variiert hat, aber hier sind zwei umfassende Listen: 1 von Mercurials eigener Seite und 2. von Wikis .

╔═════════════════════════════╦════════════════════════════════════════════════════════════════════════════════════════════════╗
║           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 speichert eine Aufzeichnung jeder Version von festgeschriebenen Dateien intern, während Hg nur die Änderungssätze speichert, die einen geringeren Platzbedarf haben können. Git macht es einfacher, den Verlauf im Vergleich zu Hg zu ändern, aber es ist wiederum eine Hass-oder-Liebe-es-Funktion. Ich mag Hg für erstere und Git für letztere.

Was ich in Hg vermisse, ist das Submodul-Feature von Git. Hg hat Subrepos, aber das ist nicht genau das Git-Submodul.

Das Ökosystem um die beiden herum kann auch die Wahl beeinflussen: Git muss populärer sein (aber das ist trivial), Git hat GitHub , während Mercurial BitBucket hat, Mercurial TortoiseHg, für das ich Ich habe noch kein Äquivalent für Git gesehen.

Jedes hat seine Vor- und Nachteile, mit beiden wirst du nicht verlieren.

11
nawfal

Schauen Sie sich Scott Chacons Beitrag von einer Weile zurück.

Ich denke, Git hat den Ruf, "komplizierter" zu sein, obwohl es meiner Erfahrung nach nicht komplizierter ist, als es sein muss. IMO, das Git-Modell ist einfacher zu verstehen (Tags enthalten Commits (und Zeiger auf null oder mehr übergeordnete Commits) enthalten Bäume enthalten Blobs und andere Bäume. .. getan).

Es ist nicht nur meine Erfahrung, dass Git nicht verwirrender ist als Mercurial. Ich würde empfehlen, noch einmal diesen Blog-Beitrag von Scott Chacon zu lesen.

8
Dustin

Ich habe Git für etwas mehr als ein Jahr in meinem jetzigen Job verwendet und zuvor Mercurial für etwas mehr als ein Jahr in meinem vorherigen Job. Ich werde eine Bewertung aus Sicht eines Benutzers liefern.

Erstens sind beide verteilte Versionskontrollsysteme. Verteilte Versionskontrollsysteme erfordern eine Änderung der Denkweise gegenüber herkömmlichen Versionskontrollsystemen, funktionieren jedoch in vielerlei Hinsicht viel besser, wenn man sie erst einmal verstanden hat. Aus diesem Grund halte ich Git und Mercurial für viel besser als Subversion, Perforce usw. Der Unterschied zwischen verteilten Versionskontrollsystemen und herkömmlichen Versionskontrollsystemen ist viel größer als der Unterschied zwischen Git und Mercurial.

Es gibt jedoch auch signifikante Unterschiede zwischen Git und Mercurial, die jede für ihre eigene Untergruppe von Anwendungsfällen besser geeignet machen.

Mercurial ist einfacher zu lernen. Ich kam zu dem Punkt, an dem ich nach ein paar Wochen mit Mercurial selten auf Unterlagen oder Notizen zurückgreifen musste. Ich muss immer noch regelmäßig auf meine Notizen mit Git verweisen, auch nachdem ich sie ein Jahr lang benutzt habe. Git ist wesentlich komplizierter.

Dies liegt zum Teil daran, dass Mercurial einfach sauberer ist. In Mercurial müssen Sie selten manuell verzweigen. Mercurial erstellt automatisch einen anonymen Zweig für Sie, wenn und wann Sie ihn benötigen. Mercurial Nomenklatur ist intuitiver; Sie müssen sich nicht um den Unterschied zwischen "fetch" und "pull" kümmern, wie Sie es mit Git tun. Mercurial ist ein bisschen weniger fehlerhaft. Es gibt Probleme mit der Groß- und Kleinschreibung von Dateinamen, die Probleme verursachten, wenn Projekte mit Git und Mercurial plattformübergreifend übertragen wurden. Dies wurde vor einiger Zeit in Mercurial behoben, während sie bei meinem letzten Check nicht in Git behoben wurden. Sie können Mercurial mitteilen, dass Dateien umbenannt wurden. Wenn bei Git die Umbenennung nicht automatisch erkannt wird - meiner Erfahrung nach ein großer Erfolg oder Misserfolg - kann die Umbenennung überhaupt nicht nachverfolgt werden.

Der andere Grund für die zusätzliche Komplikation von Git ist jedoch, dass viel davon benötigt wird, um zusätzliche Funktionen und Leistung zu unterstützen. Ja, es ist komplizierter, mit Verzweigungen in Git umzugehen - aber auf der anderen Seite ist es nicht allzu schwierig, Dinge mit solchen Verzweigungen zu tun, die in Mercurial so gut wie unmöglich sind. Das erneute Abbauen von Zweigen ist eines dieser Dinge: Sie können Ihren Zweig so verschieben, dass seine Basis jetzt der Zustand des Stamms ist, anstatt der Zustand des Stamms, in dem Sie sich verzweigt haben. Dies vereinfacht den Versionsverlauf erheblich, wenn viele Personen an der gleichen Codebasis arbeiten, da jeder Push-to-Trunk sequenziell und nicht ineinander verschlungen erscheinen kann. In ähnlicher Weise ist es viel einfacher, mehrere Festschreibungen in Ihrem Zweig zu einer einzigen Festschreibung zusammenzufassen, was wiederum dazu beitragen kann, den Versionskontrollverlauf sauber zu halten: Im Idealfall wird die gesamte Arbeit an einer Funktion als eine einzige Festschreibung in trunk angezeigt, wobei alle untergeordneten Festschreibungen ersetzt werden Commits und Unterzweige, die der Entwickler möglicherweise während der Entwicklung des Features vorgenommen hat.

Letztendlich sollte die Wahl zwischen Mercurial und Git davon abhängen, wie groß Ihre Versionskontrollprojekte sind, gemessen an der Anzahl der Personen, die gleichzeitig daran arbeiten. Wenn Sie beispielsweise eine Gruppe von einem Dutzend oder mehr an einer einzelnen monolithischen Webanwendung arbeiten, können Sie sie mit den leistungsfähigeren Tools für die Zweigstellenverwaltung besser für Ihr Projekt einsetzen. Wenn Ihr Team hingegen ein heterogen verteiltes System entwickelt, bei dem nur ein oder zwei Entwickler gleichzeitig an einer Komponente arbeiten, kann die Entwicklung mithilfe eines Mercurial-Repositorys für jedes der Komponentenprojekte reibungsloser und mit weniger Aufwand erfolgen Verwaltungsaufwand für das Repository.

Fazit: Wenn Sie ein großes Team haben, das eine einzige große Anwendung entwickelt, verwenden Sie Git. Verwenden Sie Mercurial, wenn Ihre einzelnen Anwendungen klein sind und sich die Skalierung nicht nach der Größe, sondern nach der Anzahl der Anwendungen richtet.

5
Warren Dew

Ein Unterschied, der absolut nichts mit den DVCS selbst zu tun hat:

Git scheint bei C-Entwicklern sehr beliebt zu sein. Git ist das De-facto-Repository für den Linux-Kernel und möglicherweise der Grund, warum es bei C-Entwicklern so beliebt ist. Dies gilt insbesondere für diejenigen, die den Luxus haben, nur in der Linux/Unix-Welt zu arbeiten.

Java-Entwickler scheinen Mercurial Git vorzuziehen. Dafür gibt es möglicherweise zwei Gründe: Einer ist, dass eine Reihe von sehr großen Java auf Mercurial gehostet werden, einschließlich des JDK selbst. Ein anderer ist, dass die Struktur und die saubere Dokumentation von Mercurial die Menschen anspricht Ich komme aus dem Java) Lager, obwohl solche Leute Git inkonsistent finden, wenn sie Befehle benennen und in der Dokumentation fehlen. Ich sage nicht, dass das tatsächlich wahr ist, ich sage, die Leute haben sich an etwas von ihrem gewöhnt gewöhnlicher Lebensraum und dann neigen sie dazu, DVCS daraus zu wählen.

Ich würde annehmen, dass Python-Entwickler fast ausschließlich Mercurial bevorzugen. Es gibt eigentlich keinen vernünftigen Grund dafür außer der Tatsache, dass Mercurial auf Python basiert. (Ich benutze auch Mercurial und verstehe wirklich nicht, warum die Leute Probleme mit der Implementierungssprache des DVCS haben. Ich verstehe kein Wort von Python und wenn es nicht so wäre die Tatsache, dass es irgendwo aufgeführt ist, dass es auf Python, dann hätte ich nicht gewusst) basiert.

Ich glaube nicht, dass man sagen kann, dass ein DVCS besser zu einer Sprache passt als eine andere, deshalb sollte man sich nicht dafür entscheiden. In Wirklichkeit entscheiden sich die Menschen (teilweise) danach, welchem ​​DVCS sie als Teil ihrer Gemeinschaft am meisten ausgesetzt sind.

(Nein, ich habe keine Nutzungsstatistik, um meine obigen Behauptungen zu sichern. Alles basiert auf meiner eigenen Subjektivität.)

4
peterh