Si je les comprends bien (et je suis loin d'être un expert dans chacun), ils ont fondamentalement chacun une philosophie différente. J'ai d'abord utilisé du mercure pendant 9 mois. Maintenant, j'ai utilisé git pour 6.
hg est un logiciel de contrôle de version. Son objectif principal est de suivre les versions d'un logiciel.
git est un système de fichiers basé sur le temps. Son objectif est d'ajouter une autre dimension à un système de fichiers. La plupart ont des fichiers et des dossiers, git ajoute du temps. Le fait qu'il fonctionne à merveille en tant que VCS est un sous-produit de sa conception.
Dans hg, il y a un historique de l'ensemble du projet qu'il essaie toujours de maintenir. Par défaut, je crois que hg souhaite que tous les changements soient apportés à tous les objets par tous les utilisateurs lorsqu'ils poussent et tirent.
Dans git, il n'y a qu'un pool d'objets et ces fichiers de suivi (branches / têtes) qui déterminent quel ensemble de ces objets représente l'arborescence de fichiers dans un état particulier. Lorsque vous poussez ou tirez, git envoie uniquement les objets nécessaires aux branches particulières que vous poussez ou tirez, ce qui est un petit sous-ensemble de tous les objets.
En ce qui concerne git, il n'y a pas de "1 projet". Vous pourriez avoir 50 projets tous dans le même dépôt et git s'en ficherait. Chacun pourrait être géré séparément dans le même référentiel et bien vivre.
Le concept de succursales de Hg est des succursales hors du projet principal ou des succursales, etc. Git n'a pas un tel concept. Une branche dans git n'est qu'un état de l'arbre, tout est une branche dans git. Quelle branche est officielle, actuelle ou la plus récente n'a aucun sens dans git.
Je ne sais pas si cela avait un sens. Si je pouvais dessiner des images hg pourrait ressembler à ceci où chaque commit est uno
o---o---o
/
o---o---o---o---o---o---o---o
\ /
o---o---o
Un arbre avec une seule racine et des branches qui s'en détachent. Bien que git puisse le faire et souvent les gens l'utilisent de cette façon qui n'est pas appliquée. Une image git, s'il y a une telle chose, pourrait facilement ressembler à ceci
o---o---o---o---o
o---o---o---o
\
o---o
o---o---o---o
En fait, à certains égards, cela n'a même pas de sens de montrer les branches dans git.
Une chose qui est très déroutante pour la discussion, git et mercurial ont tous les deux quelque chose appelé une "branche" mais ils ne sont pas à distance les mêmes choses. Une branche dans mercurial se produit lorsqu'il y a des conflits entre différents repos. Une branche en git est apparemment similaire à un clone en hg. Mais un clone, bien qu'il puisse donner un comportement similaire, n'est certainement pas le même. Considérez-moi les essayer en git vs hg en utilisant le repo de chrome qui est assez grand.
$ time git checkout -b some-new-branch
Switched to new branch 'some-new-branch'
real 0m1.759s
user 0m1.596s
sys 0m0.144s
Et maintenant en hg en utilisant 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
Ces deux sont des points chauds. C'est à dire, je les ai courus deux fois et c'est la deuxième manche. Le clone hg est en fait le même que git-new-workdir. Les deux font un répertoire de travail entièrement nouveau presque comme si vous aviez tapé cp -r project project-clone
. Ce n'est pas la même chose que de créer une nouvelle branche dans git. C'est beaucoup plus lourd. S'il existe un véritable équivalent de la ramification de git en hg, je ne sais pas ce que c'est.
Je comprends qu'à un certain niveau, hg et git pourraient être capables de faire des choses similaires. Si c'est le cas, il y a encore une énorme différence dans le flux de travail vers lequel ils vous mènent. Dans git, le workflow typique consiste à créer une branche pour chaque fonctionnalité.
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
Cela vient de créer 3 branches, chacune basée sur une branche appelée master. (Je suis sûr qu'il y a un moyen dans git de faire ces 1 ligne chacune au lieu de 2)
Maintenant, pour travailler sur celui que je fais
git checkout fix-game-save-bug
et commencer à travailler. Engagez des choses, etc. Passer d'une branche à l'autre, même dans un projet aussi grand que Chrome, est presque instantané. En fait, je ne sais pas comment faire ça en hg. Cela ne fait partie d'aucun tutoriel que j'ai lu.
Une autre grande différence. L'étape de Git.
Git a cette idée d'une scène. Vous pouvez le considérer comme un dossier caché. Lorsque vous vous engagez, vous ne validez que ce qui est sur la scène, pas les changements dans votre arborescence de travail. Cela peut sembler étrange. Si vous souhaitez valider toutes les modifications dans votre arborescence de travail, vous feriez ce git commit -a
qui ajoute tous les fichiers modifiés à la scène, puis les valide.
Quel est l'intérêt de la scène alors? Vous pouvez facilement séparer vos commits. Imaginez que vous avez modifié joypad.cpp et gamesave.cpp et que vous souhaitez les valider séparément
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 a même des commandes pour décider quelles lignes particulières du même fichier vous souhaitez copier sur la scène afin que vous puissiez également diviser ces validations séparément. Pourquoi voudriez-vous faire ça? Parce que les commits séparés, les autres ne peuvent extraire que ceux qu'ils veulent ou s'il y a eu un problème, ils peuvent annuler uniquement le commit qui avait le problème.