Avis de non-responsabilité: j'utilise Git, je suis le développement de Git sur la liste de diffusion git, et je contribue même un peu à Git (gitweb principalement). Je connais Mercurial à partir de la documentation et certains de la discussion sur le canal IRC #revctrl sur FreeNode.
Merci à toutes les personnes sur le canal IRC #mercurial qui ont fourni de l'aide sur Mercurial pour cette rédaction
Sommaire
Ici, ce serait bien d'avoir une syntaxe pour la table, quelque chose comme dans PHPMarkdown / MultiMarkdown / Maruku extension de Markdown
- Structure du référentiel: Mercurial ne permet pas les fusions de poulpe (avec plus de deux parents), ni le marquage d'objets non validés.
- Balises: Mercurial utilise un
.hgtags
fichier versionné avec des règles spéciales pour les balises par référentiel et prend également en charge les balises locales dans .hg/localtags
; dans les balises Git sont des références résidant dans l' refs/tags/
espace de noms, et par défaut sont suivies automatiquement lors de la récupération et nécessitent une poussée explicite.
- Branches: Dans Mercurial, le flux de travail de base est basé sur des têtes anonymes ; Git utilise des branches nommées légères et possède des types spéciaux de branches ( branches de suivi à distance) qui suivent les branches dans le référentiel distant.
- Noms et plages de révision : Mercurial fournit des numéros de révision , du local au référentiel, et base les révisions relatives (comptage à partir de la pointe, c'est-à-dire la branche actuelle) et les plages de révision sur cette numérotation locale ; Git fournit un moyen de faire référence à la révision par rapport à la pointe de la branche, et les plages de révision sont topologiques (basées sur le graphique des révisions)
- Mercurial utilise le suivi des renommées , tandis que Git utilise la détection des renommées pour gérer les renommages de fichiers
- Réseau: Mercurial prend en charge les protocoles SSH et HTTP «intelligents» et le protocole HTTP statique; Git moderne prend en charge les protocoles "intelligents" SSH, HTTP et GIT et le protocole "stupide" HTTP (S). Les deux prennent en charge les fichiers de bundles pour le transport hors ligne.
- Mercurial utilise des extensions (plugins) et une API établie; Git a une scriptabilité et des formats établis.
Il y a quelques choses qui diffèrent Mercurial de Git, mais il y a d'autres choses qui les rendent similaires. Les deux projets s'empruntent des idées. Par exemple, la hg bisect
commande dans Mercurial (anciennement extension bissecte ) a été inspirée par la git bisect
commande dans Git, tandis que l'idée de a git bundle
été inspirée par hg bundle
.
Structure du référentiel, stockage des révisions
Dans Git, il existe quatre types d'objets dans sa base de données d'objets: les objets blob qui contiennent le contenu d'un fichier, les objets arborescents hiérarchiques qui stockent la structure du répertoire, y compris les noms de fichier et les parties pertinentes des autorisations de fichier (autorisation exécutable pour les fichiers, étant un lien symbolique) , un objet commit qui contient des informations sur la paternité, un pointeur vers un instantané de l'état du référentiel à la révision représenté par un commit (via un objet arborescent du répertoire supérieur du projet) et des références à zéro ou plusieurs commit parents, et des objets tag qui référencent d'autres objets et peuvent être signé à l'aide de PGP / GPG.
Git utilise deux façons de stocker des objets: un format lâche , où chaque objet est stocké dans un fichier séparé (ces fichiers sont écrits une fois et jamais modifiés), et un format compressé où de nombreux objets sont stockés delta-compressés dans un seul fichier. L'atomicité des opérations est fournie par le fait que la référence à un nouvel objet est écrite (atomiquement, en utilisant l'astuce create + rename) après avoir écrit un objet.
Les référentiels Git nécessitent une maintenance périodique en utilisant git gc
(pour réduire l'espace disque et améliorer les performances), bien que Git le fasse automatiquement de nos jours. (Cette méthode offre une meilleure compression des référentiels.)
Mercurial (pour autant que je le comprends) stocke l'historique d'un fichier dans un journal de fichiers (ensemble, je pense, avec des métadonnées supplémentaires comme le suivi des renommées et des informations d'assistance); il utilise une structure plate appelée manifeste pour stocker la structure du répertoire et une structure appelée changelog qui stocke des informations sur les changements (révisions), y compris le message de validation et zéro, un ou deux parents.
Mercurial utilise le journal des transactions pour fournir l'atomicité des opérations et s'appuie sur la troncature des fichiers pour le nettoyage après une opération échouée ou interrompue. Les revlogs sont en ajout uniquement.
En regardant la structure du référentiel dans Git par rapport à Mercurial, on peut voir que Git est plus comme une base de données d'objets (ou un système de fichiers adressé par contenu), et Mercurial plus comme une base de données relationnelle traditionnelle à champ fixe.
Différences:
dans Git, les objets arborescents forment une structure hiérarchique ; dans le fichier manifeste Mercurial est une structure plate . Dans Git, l' objet blob stocke une version du contenu d'un fichier; dans Mercurial filelog stocke l' historique complet d'un seul fichier (si nous ne prenons pas en compte ici les complications de renommage). Cela signifie qu'il existe différentes zones d'opérations où Git serait plus rapide que Mercurial, toutes autres choses considérées égales (comme les fusions ou l'affichage de l'historique d'un projet), et des zones où Mercurial serait plus rapide que Git (comme l'application de correctifs ou l'affichage historique d'un seul fichier).Ce problème peut ne pas être important pour l'utilisateur final.
En raison de la structure à enregistrement fixe de la structure du journal des modifications de Mercurial, les validations dans Mercurial ne peuvent avoir que deux parents ; commits dans Git peut avoir plus de deux parents (ce que l'on appelle la «fusion de poulpe»). Bien que vous puissiez (en théorie) remplacer la fusion de poulpe par une série de fusions à deux parents, cela pourrait entraîner des complications lors de la conversion entre les référentiels Mercurial et Git.
Pour autant que je sache, Mercurial n'a pas d'équivalent de balises annotées (objets de balises) de Git. Un cas particulier des balises annotées sont les balises signées (avec signature PGP / GPG); l'équivalent dans Mercurial peut être fait en utilisant GpgExtension , laquelle extension est distribuée avec Mercurial. Vous ne pouvez pas baliser un objet non validé dans Mercurial comme vous le pouvez dans Git, mais ce n'est pas très important, je pense (certains référentiels git utilisent un blob balisé pour distribuer la clé PGP publique à utiliser pour vérifier les balises signées).
Références: branches et balises
Dans Git, les références (branches, branches de suivi à distance et balises) résident en dehors du DAG des validations (comme elles le devraient). Les références dans l' refs/heads/
espace de noms ( branches locales ) pointent vers des validations et sont généralement mises à jour par "git commit"; ils pointent vers la pointe (tête) de la branche, c'est pourquoi un tel nom. Les références dans l' refs/remotes/<remotename>/
espace de noms ( branches de suivi à distance ) pointent vers la validation, suivent les branches dans le référentiel distant <remotename>
et sont mises à jour par "git fetch" ou équivalent. Les références dans l' refs/tags/
espace de noms ( balises ) pointent généralement vers des validations (balises légères) ou des objets de balise (balises annotées et signées), et ne sont pas censées changer.
Mots clés
Dans Mercurial, vous pouvez donner un nom persistant à la révision à l'aide d'une balise ; les balises sont stockées de manière similaire aux modèles d'ignorance. Cela signifie que les balises visibles globalement sont stockées dans un .hgtags
fichier contrôlé par révision dans votre référentiel. Cela a deux conséquences: premièrement, Mercurial doit utiliser des règles spéciales pour ce fichier pour obtenir la liste actuelle de toutes les balises et mettre à jour ce fichier (par exemple, il lit la dernière révision validée du fichier, pas la version actuellement extraite); deuxièmement, vous devez valider les modifications de ce fichier pour que la nouvelle balise soit visible par les autres utilisateurs / autres référentiels (pour autant que je le comprenne).
Mercurial prend également en charge les balises locales , stockées dans hg/localtags
, qui ne sont pas visibles par les autres (et bien sûr ne sont pas transférables)
Dans Git, les balises sont des références nommées fixes (constantes) à d'autres objets (généralement des objets de balise, qui à leur tour pointent vers des validations) stockés dans l' refs/tags/
espace de noms. Par défaut, lors de la récupération ou de la poussée d'un ensemble de révision, git récupère ou pousse automatiquement les balises qui indiquent que les révisions sont récupérées ou poussées. Néanmoins, vous pouvez contrôler dans une certaine mesure les balises récupérées ou poussées.
Git traite les balises légères (pointant directement sur les validations) et les balises annotées (pointant sur les objets de balise, qui contiennent un message de balise qui inclut éventuellement la signature PGP, qui à son tour pointe pour valider) légèrement différemment, par exemple, par défaut, il ne prend en compte que les balises annotées lors de la description valide en utilisant "git describe".
Git n'a pas d'équivalent strict des balises locales dans Mercurial. Néanmoins, les meilleures pratiques de git recommandent de configurer un référentiel nu public séparé, dans lequel vous transférez les modifications prêtes, et à partir duquel d'autres clones et récupèrent. Cela signifie que les balises (et les branches) que vous ne poussez pas sont privées dans votre référentiel. D'autre part, vous pouvez également utiliser un espace de noms autre que heads
, remotes
ou tags
, par exemple, local-tags
pour les balises locales.
Opinion personnelle: À mon avis, les balises doivent résider en dehors du graphique de révision, car elles lui sont externes (ce sont des pointeurs dans le graphique des révisions). Les balises doivent être sans version, mais transférables. Le choix de Mercurial d'utiliser un mécanisme similaire à celui pour ignorer les fichiers, signifie qu'il doit soit traiter .hgtags
spécialement (le fichier dans l'arborescence est transférable, mais ordinaire il est versionné), ou avoir des balises qui sont uniquement locales ( .hg/localtags
n'est pas versionnée, mais non transférable).
Branches
Dans Git, la branche locale (pointe de branche ou tête de branche) est une référence nommée à un commit, où l'on peut développer de nouveaux commits. La branche peut également signifier une ligne de développement active, c'est-à-dire que toutes les validations sont accessibles depuis l'extrémité de la branche. Les branches locales résident dans l' refs/heads/
espace de noms, par exemple, le nom complet de la branche «maître» est «réfs / têtes / maître».
La branche actuelle dans Git (signifiant branche extraite et branche où ira le nouveau commit) est la branche référencée par la référence HEAD. On peut avoir HEAD pointant directement vers un commit, plutôt que d'être une référence symbolique; cette situation d'être sur une branche anonyme sans nom est appelée HEAD détaché ("la branche git" montre que vous êtes sur '(pas de branche)').
Dans Mercurial, il y a des branches anonymes (têtes de branche), et on peut utiliser des signets (via l' extension de signet ). Ces branches de signets sont purement locales et ces noms (jusqu'à la version 1.6) n'étaient pas transférables avec Mercurial. Vous pouvez utiliser rsync ou scp pour copier le .hg/bookmarks
fichier dans un référentiel distant. Vous pouvez également utiliser hg id -r <bookmark> <url>
pour obtenir l'ID de révision d'une astuce actuelle d'un signet.
Depuis 1.6 les signets peuvent être poussés / tirés. La page BookmarksExtension contient une section sur l'utilisation des référentiels distants . Il y a une différence dans le fait que dans Mercurial, les noms de signets sont globaux , tandis que la définition de «distant» dans Git décrit également le mappage des noms de branche à partir des noms du référentiel distant vers les noms des branches locales de suivi à distance; par exemple, le refs/heads/*:refs/remotes/origin/*
mappage signifie que l'on peut trouver l'état de la branche 'maître' ('refs / heads / master') dans le référentiel distant dans la branche de suivi à distance 'origin / master' ('refs / remotes / origin / master').
Mercurial a également ce qu'on appelle des branches nommées , où le nom de la branche est intégré dans un commit (dans un changeset). Ce nom est global (transféré à l'extraction). Ces noms de branche sont enregistrés en permanence dans le cadre des métadonnées de l'ensemble de modifications \ u2019. Avec Mercurial moderne, vous pouvez fermer la "branche nommée" et arrêter l'enregistrement du nom de la branche. Dans ce mécanisme, les pointes de branches sont calculées à la volée.
Les "branches nommées" de Mercurial devraient à mon avis être plutôt appelées labels de commit , car c'est ce qu'elles sont. Il existe des situations où la "branche nommée" peut avoir plusieurs astuces (plusieurs validations sans enfant) et peut également consister en plusieurs parties disjointes du graphique des révisions.
Il n'y a pas d'équivalent de ces "branches intégrées" Mercurial dans Git; de plus, la philosophie de Git est que si l'on peut dire que la branche inclut une validation, cela ne signifie pas qu'une validation appartient à une branche.
Notez que la documentation de Mercurial propose toujours d'utiliser des clones séparés (référentiels séparés) au moins pour les branches à longue durée de vie (branche unique par flux de travail de référentiel), alias branchement par clonage .
Branches en poussant
Mercurial par défaut pousse toutes les têtes . Si vous voulez pousser une seule branche ( tête unique ), vous devez spécifier la révision de pointe de la branche que vous voulez pousser. Vous pouvez spécifier la pointe de branche par son numéro de révision (local vers le référentiel), par l'identifiant de révision, par le nom du signet (local vers le référentiel, non transféré) ou par le nom de la branche incorporée (branche nommée).
Si je comprends bien, si vous poussez une série de révisions qui contiennent des commits marqués comme étant sur une "branche nommée" dans le langage Mercurial, vous aurez cette "branche nommée" dans le référentiel vers lequel vous poussez. Cela signifie que les noms de ces branches incorporées ("branches nommées") sont globaux (en ce qui concerne les clones du référentiel / projet donné).
Par défaut (sous réserve de la push.default
variable de configuration) "git push" ou "git push < remote >" Git pousserait les branches correspondantes , c'est-à-dire uniquement les branches locales qui ont leur équivalent déjà présent dans le référentiel distant dans lequel vous poussez. Vous pouvez utiliser l' --all
option git-push ("git push --all") pour pousser toutes les branches , vous pouvez utiliser "git push < remote > < branch >" pour pousser une seule branche donnée , et vous pouvez utiliser "git push < remote > HEAD "pour pousser la branche courante .
Tout ce qui précède suppose que Git n'est pas configuré sur les branches à pousser via remote.<remotename>.push
les variables de configuration.
Branches à aller chercher
Remarque: ici, j'utilise la terminologie Git où "récupérer" signifie télécharger les modifications à partir du référentiel distant sans intégrer ces modifications au travail local. C'est ce que font " git fetch
" et " hg pull
".
Si je comprends bien, par défaut, Mercurial récupère toutes les têtes du référentiel distant, mais vous pouvez spécifier la branche à récupérer via " hg pull --rev <rev> <url>
" ou " hg pull <url>#<rev>
" pour obtenir une seule branche . Vous pouvez spécifier <rev> à l'aide de l'identifiant de révision, du nom de la "branche nommée" (branche intégrée dans le journal des modifications) ou du nom du signet. Cependant, le nom du signet (au moins actuellement) n'est pas transféré. Toutes les révisions de "branches nommées" que vous obtenez appartiennent à être transférées. "hg pull" stocke les bouts de branches récupérées comme des têtes anonymes et sans nom.
Dans Git par défaut (pour la télécommande 'origin' créée par "git clone" et pour les télécommandes créées en utilisant "git remote add") " git fetch
" (ou " git fetch <remote>
") obtient toutes les branches du référentiel distant (de l' refs/heads/
espace de noms) et les stocke dans refs/remotes/
espace de noms. Cela signifie par exemple que la branche nommée 'master' (nom complet: 'refs / heads / master') dans la 'origin' distante serait stockée (enregistrée) en tant que branche de suivi à distance 'origin / master' (nom complet: 'refs / télécommandes / origine / maître ').
Vous pouvez récupérer une seule branche dans Git en utilisant git fetch <remote> <branch>
- Git stockerait les branches demandées dans FETCH_HEAD, ce qui est quelque chose de similaire aux têtes sans nom Mercurial.
Ce ne sont que des exemples de cas par défaut de puissante syntaxe refspec Git: avec les refspecs, vous pouvez spécifier et / ou configurer les branches que vous souhaitez récupérer et où les stocker. Par exemple, le cas par défaut "récupérer toutes les branches" est représenté par '+ refs / heads / *: refs / remotes / origin / *' wildcard refspec, et "fetch single branch" est un raccourci pour 'refs / heads / <branch>:' . Les refspecs sont utilisées pour mapper les noms des branches (refs) dans le référentiel distant aux noms des refs locaux. Mais vous n'avez pas besoin d'en savoir (beaucoup) sur les refspecs pour pouvoir travailler efficacement avec Git (grâce principalement à la commande "git remote").
Opinion personnelle: Personnellement, je pense que les "branches nommées" (avec des noms de branche intégrés dans les métadonnées des changements) dans Mercurial sont une conception erronée avec son espace de noms global, en particulier pour un système de contrôle de version distribué . Par exemple, prenons le cas où Alice et Bob ont tous deux "branche nommée" nommée "for-joe" dans leurs référentiels, branches qui n'ont rien en commun. Dans le référentiel de Joe, cependant, ces deux branches seraient traitées comme une seule branche. Vous avez donc en quelque sorte trouvé une convention protégeant contre les conflits de noms de branche. Ce n'est pas un problème avec Git, où dans le référentiel de Joe, la branche 'for-joe' d'Alice serait 'alice / for-joe', et de Bob ce serait 'bob / for-joe'.
Les «succursales de signets» de Mercurial manquent actuellement de mécanisme de distribution interne.
Différences:
Cette zone est l'une des principales différences entre Mercurial et Git, comme James Woodyatt et Steve Losh l'ont dit dans leurs réponses. Mercurial, par défaut, utilise des codelines légères anonymes, qui dans leur terminologie sont appelées "têtes". Git utilise des branches nommées légères, avec un mappage injectif pour mapper les noms des branches du référentiel distant aux noms des branches de suivi à distance. Git vous "force" à nommer des branches (enfin, à l'exception d'une seule branche sans nom, situation appelée HEAD détaché), mais je pense que cela fonctionne mieux avec des flux de travail lourds comme une branche de sujet, ce qui signifie plusieurs branches dans un paradigme de référentiel unique.
Révisions de dénomination
Dans Git, il existe de nombreuses façons de nommer les révisions (décrites par exemple dans la page de manuel git rev-parse ):
- Le nom d'objet SHA1 complet (chaîne hexadécimale de 40 octets), ou une sous-chaîne de celui-ci qui est unique dans le référentiel
- Un nom de référence symbolique, par exemple 'master' (se référant à la branche 'master'), ou 'v1.5.0' (se référant à la balise), ou 'origin / next' (se référant à la branche de suivi à distance)
- Un suffixe
^
pour réviser le paramètre signifie le premier parent d'un objet commit, ^n
signifie le nième parent d'un commit de fusion. Un suffixe ~n
pour le paramètre de révision signifie le n-ième ancêtre d'une validation dans la première ligne directe. Ces suffixes peuvent être combinés pour former un spécificateur de révision suivant le chemin à partir d'une référence symbolique, par exemple «pu ~ 3 ^ 2 ~ 3»
- Sortie de "git describe", c'est-à-dire une balise la plus proche, éventuellement suivie d'un tiret et d'un certain nombre de validations, suivie d'un tiret, d'un 'g' et d'un nom d'objet abrégé, par exemple 'v1.6.5.1-75- g5bf8097 ».
Il existe également des spécificateurs de révision impliquant le reflog, non mentionnés ici. Dans Git, chaque objet, que ce soit commit, tag, tree ou blob a son identifiant SHA-1; il existe une syntaxe spéciale comme par exemple 'next: Documentation' ou 'next: README' pour faire référence à l'arborescence (répertoire) ou au blob (contenu du fichier) à la révision spécifiée.
Mercurial a également de nombreuses façons de nommer les changements (décrits par exemple dans la page de manuel hg ):
- Un entier simple est traité comme un numéro de révision. Il faut se rappeler que les numéros de révision sont locaux pour un référentiel donné ; dans d'autres référentiels, ils peuvent être différents.
- Les entiers négatifs sont traités comme des décalages séquentiels par rapport à la pointe, -1 indiquant la pointe, -2 indiquant la révision avant la pointe, etc. Ils sont également locaux dans le référentiel.
- Un identifiant de révision unique (chaîne hexadécimale à 40 chiffres) ou son préfixe unique.
- Un nom de balise (nom symbolique associé à une révision donnée), ou un nom de signet (avec l'extension: nom symbolique associé à une tête donnée, local au référentiel), ou une "branche nommée" (étiquette de validation; révision donnée par "branche nommée" est astuce (validation sans enfant) de toutes les validations avec une étiquette de validation donnée, avec le plus grand numéro de révision s'il y en a plusieurs)
- Le nom réservé "tip" est une balise spéciale qui identifie toujours la révision la plus récente.
- Le nom réservé "null" indique la révision nulle.
- Le nom réservé "." indique le parent du répertoire de travail.
Différences
Comme vous pouvez le voir en comparant les listes ci-dessus, Mercurial propose des numéros de révision, locaux au référentiel, contrairement à Git. D'autre part, Mercurial propose des décalages relatifs uniquement à partir de `` tip '' (branche actuelle), qui sont locaux au référentiel (au moins sans ParentrevspecExtension ), tandis que Git permet de spécifier n'importe quel commit à la suite de n'importe quelle astuce.
La révision la plus récente est nommée HEAD dans Git et "tip" dans Mercurial; il n'y a pas de révision nulle dans Git. Mercurial et Git peuvent avoir plusieurs racines (peuvent avoir plus d'un commit sans parent; cela est généralement le résultat de la fusion de projets auparavant séparés).
Voir aussi: Beaucoup de différents types d' articles de spécification de révision sur le blog d'Elijah (newren).
Opinion personnelle: Je pense que les numéros de révision sont surévalués (au moins pour le développement distribué et / ou l'histoire non linéaire / branchée). Premièrement, pour un système de contrôle de version distribué, ils doivent être soit locaux au référentiel, soit exiger de traiter certains référentiels de manière spéciale comme une autorité de numérotation centrale. Deuxièmement, les projets plus importants, avec un historique plus long, peuvent avoir un nombre de révisions dans une plage de 5 chiffres, de sorte qu'ils n'offrent qu'un léger avantage par rapport aux identificateurs de révision raccourcis à 6-7 caractères, et impliquent un ordre strict tandis que les révisions ne sont que partiellement ordonnées (je veux dire ici que les révisions n et n + 1 n'ont pas besoin d'être parent et enfant).
Gammes de révision
Dans Git, les plages de révision sont topologiques . La A..B
syntaxe courante , qui pour l'historique linéaire signifie une plage de révision commençant à A (mais excluant A) et se terminant à B (c'est-à-dire que la plage est ouverte par le bas ), est un raccourci ("sucre syntaxique") pour ^A B
lequel, pour les commandes de parcours de l'historique, toutes les commits accessibles depuis B, à l'exclusion de ceux accessibles depuis A. Cela signifie que le comportement de la A..B
plage est entièrement prévisible (et très utile) même si A n'est pas l'ancêtre de B: A..B
signifie alors la plage de révisions de l'ancêtre commun de A et B (fusionner la base ) à la révision B.
Dans Mercurial, les plages de révision sont basées sur la plage de numéros de révision . La plage est spécifiée à l'aide de la A:B
syntaxe et contrairement à Git, la plage agit comme un intervalle fermé . La plage B: A est également la plage A: B dans l'ordre inverse, ce qui n'est pas le cas dans Git (mais voir la note ci-dessous sur la A...B
syntaxe). Mais cette simplicité a un prix: la gamme de révision A: B n'a de sens que si A est l'ancêtre de B ou vice versa, c'est-à-dire avec une histoire linéaire; sinon (je suppose que) la plage est imprévisible et le résultat est local au référentiel (car les numéros de révision sont locaux au référentiel).
Ceci est corrigé avec Mercurial 1.6, qui a une nouvelle plage de révision topologique , où 'A..B' (ou 'A :: B') est compris comme l'ensemble de changements qui sont à la fois des descendants de X et des ancêtres de Y. C'est , Je suppose, équivalent à '--ancestry-path A..B' dans Git.
Git a également une notation A...B
pour la différence symétrique des révisions; cela signifie A B --not $(git merge-base A B)
, ce qui signifie que toutes les validations sont accessibles depuis A ou B, mais en excluant toutes les validations accessibles depuis les deux (accessibles depuis les ancêtres communs).
Renomme
Mercurial utilise le suivi des renommées pour gérer les renommages de fichiers. Cela signifie que les informations sur le fait qu'un fichier a été renommé sont enregistrées au moment de la validation; dans Mercurial, ces informations sont enregistrées sous la forme "diff amélioré" dans les métadonnées de fichier journal (fichier revlog). La conséquence de cela est que vous devez utiliser hg rename
/ hg mv
... ou vous devez vous rappeler de courir hg addremove
pour effectuer une détection de renommage basée sur la similitude.
Git est unique parmi les systèmes de contrôle de version en ce qu'il utilise la détection de renommage pour gérer les renommages de fichiers. Cela signifie que le fait que le fichier a été renommé est détecté au moment où il est nécessaire: lors d'une fusion ou lors de l'affichage d'un diff (si demandé / configuré). Cela a l'avantage que l'algorithme de détection de renommage peut être amélioré et n'est pas figé au moment de la validation.
Git et Mercurial nécessitent d'utiliser l' --follow
option pour suivre les renommages lors de l'affichage de l'historique d'un seul fichier. Les deux peuvent suivre des renommages lors de l'affichage de l'historique par ligne d'un fichier dans git blame
/ hg annotate
.
Dans Git, la git blame
commande est capable de suivre le mouvement du code, en déplaçant (ou en copiant) également le code d'un fichier à l'autre, même si le mouvement du code ne fait pas partie d'un renommage de fichier sain. Pour autant que je sache, cette fonctionnalité est unique à Git (au moment de la rédaction, octobre 2009).
Protocoles réseau
Mercurial et Git ont tous deux la prise en charge de l'extraction et de la transmission vers des référentiels sur le même système de fichiers, où l'URL du référentiel n'est qu'un chemin d'accès du système de fichiers au référentiel. Les deux prennent également en charge la récupération à partir de fichiers groupés .
Prise en charge de Mercurial récupérant et poussant via SSH et via les protocoles HTTP. Pour SSH, il faut un compte shell accessible sur la machine de destination et une copie de hg installé / disponible. Pour l'accès HTTP, le hg-serve
script Mercurial CGI en cours d'exécution est requis et Mercurial doit être installé sur la machine serveur.
Git prend en charge deux types de protocoles utilisés pour accéder au référentiel distant:
- Les protocoles "intelligents" , qui incluent l'accès via SSH et via le protocole git: // personnalisé (par
git-daemon
), nécessitent l'installation de git sur le serveur. L'échange dans ces protocoles consiste à négocier client et serveur sur les objets qu'ils ont en commun, puis à générer et à envoyer un packfile. Modern Git inclut la prise en charge du protocole HTTP "intelligent".
- Les protocoles "stupides" , qui incluent HTTP et FTP (uniquement pour la récupération) et HTTPS (pour la transmission via WebDAV), ne nécessitent pas l'installation de git sur le serveur, mais ils nécessitent que le référentiel contienne des informations supplémentaires générées par
git update-server-info
(généralement exécutées à partir d'un hook ). L'échange consiste en un client parcourant la chaîne de validation et en téléchargeant les objets et les fichiers pack en vrac selon les besoins. L'inconvénient est qu'il télécharge plus que ce qui est strictement requis (par exemple, dans le cas où il n'y a qu'un seul packfile, il serait téléchargé en entier même en ne récupérant que quelques révisions), et qu'il peut nécessiter de nombreuses connexions pour terminer.
Extension: scriptabilité vs extensions (plugins)
Mercurial est implémenté en Python , avec du code de base écrit en C pour les performances. Il fournit une API pour écrire des extensions (plugins) comme moyen d'ajouter des fonctionnalités supplémentaires. Certaines fonctionnalités, comme les «branches de signets» ou les révisions de signature, sont fournies dans les extensions distribuées avec Mercurial et nécessitent d'être activées.
Git est implémenté dans les scripts C , Perl et shell . Git fournit de nombreuses commandes de bas niveau ( plomberie ) utilisables dans les scripts. La manière habituelle d'introduire une nouvelle fonctionnalité est de l'écrire en Perl ou en script shell, et lorsque l'interface utilisateur se stabilise, réécrivez-la en C pour les performances, la portabilité, et dans le cas d'un script shell en évitant les cas d'angle (cette procédure est appelée intégration ).
Git s'appuie et est construit autour des formats [référentiel] et des protocoles [réseau]. Au lieu des liaisons de langage, il y a des réimplémentations (partielles ou complètes) de Git dans d'autres langages (certaines d'entre elles sont partiellement des réimplémentations et enveloppent partiellement les commandes git): JGit (Java, utilisé par EGit, Eclipse Git Plugin), Grit (Ruby) , Dulwich (Python), git # (C #).
TL; DR