Wenn ich sie richtig verstehe (und ich bin weit davon entfernt, ein Experte zu sein), hat jeder von ihnen eine grundsätzlich andere Philosophie. Ich habe Mercurial zunächst 9 Monate lang verwendet. Jetzt habe ich Git für 6 verwendet.
hg ist eine Software zur Versionskontrolle. Ihr Hauptziel ist es, die Versionen einer Software zu verfolgen.
git ist ein zeitbasiertes Dateisystem. Sein Ziel ist es, einem Dateisystem eine weitere Dimension hinzuzufügen. Die meisten haben Dateien und Ordner, Git fügt Zeit hinzu. Dass es als VCS hervorragend funktioniert, ist ein Nebenprodukt seines Designs.
In hg gibt es eine Geschichte des gesamten Projekts, die es immer zu pflegen versucht. Ich glaube, hg will standardmäßig alle Änderungen an allen Objekten von allen Benutzern beim Push- und Pull-Verfahren.
In Git gibt es nur einen Pool von Objekten und diese Verfolgungsdateien (Zweige/Köpfe), die bestimmen, welche Menge dieser Objekte den Baum der Dateien in einem bestimmten Zustand repräsentiert. Beim Schieben oder Ziehen sendet Git nur die Objekte, die für die jeweiligen Zweige benötigt werden, die Sie schieben oder ziehen, was eine kleine Teilmenge aller Objekte ist.
Was Git betrifft, so gibt es kein "1 Projekt". Sie könnten 50 Projekte im selben Repository haben, und Git würde sich nicht darum kümmern. Jedes Projekt könnte separat in der gleichen Projektliste verwaltet werden und gut leben.
Hg's Konzept der Zweige ist Zweige aus dem Hauptprojekt oder Zweige aus Zweigen usw. Git hat kein solches Konzept. Ein Zweig in Git ist nur ein Zustand des Baums, alles ist ein Zweig in Git. Welcher Zweig offiziell, aktuell oder der neueste ist, hat in Git keine Bedeutung.
Ich weiß nicht, ob das einen Sinn ergibt. Wenn ich Bilder zeichnen könnte, würde hg vielleicht so aussehen, wobei jede Übertragung ein o
o---o---o
/
o---o---o---o---o---o---o---o
\ /
o---o---o
Ein Baum mit einer einzigen Wurzel und davon ausgehenden Zweigen. Git kann das zwar, und viele Leute benutzen es auch so, aber es ist nicht erzwungen. Ein Git-Bild, wenn es so etwas gibt, könnte leicht wie folgt aussehen
o---o---o---o---o
o---o---o---o
\
o---o
o---o---o---o
In mancher Hinsicht macht es nicht einmal Sinn, Zweige in Git anzuzeigen.
Eine Sache, die für die Diskussion sehr verwirrend ist, Git und Mercurial haben beide etwas, das "Branch" genannt wird, aber sie sind nicht im Entferntesten das Gleiche. Ein Zweig in Mercurial entsteht, wenn es Konflikte zwischen verschiedenen Repos gibt. Ein Branch in Git ist scheinbar ähnlich wie ein Clone in Hg. Aber ein Klon, auch wenn er ein ähnliches Verhalten zeigt, ist definitiv nicht dasselbe. Betrachten Sie mich, wie ich das in Git und Hg anhand des Chromium-Repos ausprobiere, das ziemlich groß ist.
$ time git checkout -b some-new-branch
Switched to new branch 'some-new-branch'
real 0m1.759s
user 0m1.596s
sys 0m0.144s
Und jetzt in hg mit clone
$ time hg clone project/ some-clone/
updating to branch default
29387 files updated, 0 files merged, 0 files removed, 0 files unresolved.
real 0m58.196s
user 0m19.901s
sys 0m8.957
Das sind beides heiße Eisen. D.h. ich habe sie zweimal ausgeführt und dies ist der zweite Durchlauf. hg clone ist eigentlich das gleiche wie git-new-workdir. Beide erstellen ein völlig neues Arbeitsverzeichnis, als ob Sie Folgendes eingegeben hätten cp -r project project-clone
. Das ist nicht dasselbe wie das Anlegen eines neuen Zweigs in Git. Es ist viel schwerer. Wenn es ein echtes Äquivalent zu git's branching in hg gibt, weiß ich nicht, was es ist.
Ich verstehe auf einer gewissen Ebene hg und git könnte in der Lage sein, ähnliche Dinge zu tun. Wenn ja, dann gibt es immer noch einen großen Unterschied im Arbeitsablauf, zu dem sie Sie führen. In Git besteht der typische Arbeitsablauf darin, für jede Funktion einen Zweig zu erstellen.
git checkout master
git checkout -b add-2nd-joypad-support
git checkout master
git checkout -b fix-game-save-bug
git checkout master
git checkout -b add-a-star-support
Dadurch wurden 3 Zweige erstellt, die jeweils auf einem Zweig namens master basieren. (Ich bin mir sicher, dass es in Git eine Möglichkeit gibt, die Zweige auf 1 Zeile statt auf 2 zu reduzieren)
Jetzt arbeite ich an einer, die ich gerade mache
git checkout fix-game-save-bug
und mit der Arbeit beginnen. Dinge festschreiben, usw. Das Wechseln zwischen Zweigen ist selbst bei einem so großen Projekt wie Chrome fast augenblicklich möglich. Ich weiß eigentlich nicht, wie man das in hg macht. Es ist nicht Teil eines Tutorials, das ich gelesen habe.
Ein weiterer großer Unterschied. Git's Bühne.
Git hat diese Vorstellung von einer Bühne. Man kann es sich wie einen versteckten Ordner vorstellen. Wenn Sie eine Übertragung durchführen, übertragen Sie nur das, was sich auf der Stage befindet, nicht die Änderungen in Ihrem Arbeitsbaum. Das mag seltsam klingen. Wenn Sie alle Änderungen in Ihrem Arbeitsbaum übertragen wollen, würden Sie Folgendes tun git commit -a
der alle geänderten Dateien zur Stage hinzufügt und sie dann festschreibt.
Was ist dann der Sinn der Bühne? Sie können Ihre Übertragungen einfach trennen. Stellen Sie sich vor, Sie haben joypad.cpp und gamesave.cpp bearbeitet und möchten sie getrennt übertragen
git add joypad.cpp // copies to stage
git commit -m "added 2nd joypad support"
git add gamesave.cpp // copies to stage
git commit -m "fixed game save bug"
Git verfügt sogar über Befehle, mit denen Sie entscheiden können, welche Zeilen in derselben Datei Sie auf die Bühne kopieren möchten, so dass Sie diese Übertragungen auch separat aufteilen können. Warum sollten Sie das tun? Weil andere nur die Commits ziehen können, die sie wollen, oder wenn es ein Problem gab, können sie nur den Commit rückgängig machen, der das Problem hatte.