// -*- mode: doc; mode: flyspell; coding: utf-8; fill-column: 79; -*- == Clonons gaiement == Avec les anciens systèmes de gestion de versions, l'opération standard pour obtenir des fichiers est le checkout. Vous obtenez un ensemble de fichiers correspondant à un état particulier précédemment enregistré. Avec Git et d'autres systèmes distribués de gestion de versions, le clonage est l'opération standard. Pour obtenir des fichiers, on crée un 'clone' du dépôt entier. En d'autres termes, il s'agit de faire un http://fr.wikipedia.org/wiki/Site_miroir[miroir] du serveur central. Tout ce qui peut se faire sur le dépôt central peut être fait sur le vôtre. === Synchronisation entre machines === Je peux imaginer faire des archives *tar* ou utiliser *rsync* pour des sauvegardes ou une synchronisation simple. Mais parfois j'édite sur mon portable, d'autres fois sur mon fixe, et les deux peuvent ne pas avoir communiqué entre temps. Initialisez un dépôt Git et faites un *commit* de vos fichiers depuis une machine. Ensuite sur l'autre : $ git clone autre.ordinateur:/chemin/vers/les/fichiers pour créer une deuxième copie de ces fichiers et du dépôt Git. À partir de ce moment, $ git commit -a $ git pull autre.ordinateur:/chemin/vers/les/fichiers HEAD ira chercher l'état des fichiers sur l'autre ordinateur pour mettre à jour celui sur lequel vous travaillez. Si récemment vous avez fait des modifications d'un même fichier en conflit entre elles, Git vous le signalera et vous devrez répéter à nouveau le commit après avoir résolu ces conflits. === Gestion classique des sources === Initialisez le dépôt Git de vos fichiers : $ git init $ git add . $ git commit -m "Commit initial" Sur le serveur central, initialisez un 'dépôt nu' (*bare* dans la terminologie Git) dans un dossier quelconque : $ mkdir proj.git $ cd proj.git $ git init --bare $ # variante en une ligne : GIT_DIR=proj.git git init Si besoin, démarrez le démon (service) : $ git daemon --detach # peut être tourne-t-il déjà Pour les services d'hébergement en ligne, suivez les instructions fournies pour mettre en place le dépôt Git initialement vide. En général il s'agit de remplir un formulaire sur une page web. 'Poussez' votre projet vers le serveur central en utilisant : $ git push git://serveur.central/chemin/du/proj.git HEAD Pour obtenir les sources, un développeur saisit : $ git clone git://serveur.central/chemin/du/proj.git Après avoir fait des modifications, le développeur les enregistre en local : $ git commit -a Pour se mettre à jour par rapport à la dernière version : $ git pull Tout conflit lors de la fusion doit être résolu puis validé : $ git commit -a Pour envoyer les modifications locales vers le dépôt central : $ git push Si le serveur principal a de nouvelles modifications dues à d'autres développeurs, l'envoi échoue et le développeur doit se mettre à jour de la dernière version, résoudre les éventuels conflits de fusion, puis essayer à nouveau. === Dépôts nus === Un dépôt nu (*bare repository*) est nommé ainsi car il n'a pas de dossier de travail : il ne contient que des fichiers qui sont normalement cachés dans le sous dossier `.git`. En d'autres termes, il ne conserve que l'historique d'un projet et ne contient jamais le rendu d'une version donnée. Un dépôt nu joue un rôle similaire à celui du serveur principal dans un système de gestion de versions centralisé : le réceptacle de vos projets. Les développeurs clonent vos projets à partir de celui-ci et y poussent les dernières modifications officielles. En général il est placé sur un serveur qui ne fait quasiment que ce travail de distribution de l'information. Le développement s'opère sur les clones de sorte que le dépôt principal peut se passer d'un dossier de travail. Beaucoup des commandes de Git échouent sur un dépôt nu tant que la variable d'environnement `GIT_DIR` n'est pas renseignée avec le chemin vers le dépôt ou que l'option `--bare` n'est pas utilisée. === Envoi vs rapatriement (push vs pull) === Pourquoi a-t-on introduit la commande `push` (_pousser_ ou _envoyer_) au lieu de se contenter de la commande `pull` (_tirer_ ou _rapatrier_) plus familière ? Premièrement, la commande `pull` échoue sur un dépôt nu : il faut y utiliser la commande `fetch` dont nous parlerons plus tard. Mais même si nous conservions un dépôt standard sur le serveur central, y rapatrier les modifications serait peu pratique. Nous devrions d'abord nous connecter au serveur et donner en argument à la commande `pull` l'adresse de la machine depuis laquelle nous souhaitons rapatrier des modifications. Des pare-feux peuvent éventuellement nous embêter, et comment faire si nous n'avons pas d'accès `shell` au serveur ? Quoi qu'il en soit, ce cas mis à part, nous décourageons l'envoi ( en comparaison du rapatriement ) parce que cela peut entraîner des confusions lorsque la destination possède un dossier de travail. En résumé, pendant votre phase d'apprentissage de Git, n'utilisez l'envoi ( push ) que lorsque la destination est un dépôt nu ; sinon rapatriez ( pull ). === Forker un projet === Vous en avez marre de la manière dont est géré un projet ? Vous pensez pouvoir faire mieux ? Dans ce cas, sur votre serveur : $ git clone git://serveur.principal/chemin/vers/les/fichiers Ensuite, informez tout le monde du fork de ce projet sur votre serveur. Par la suite, vous pouvez fusionner les modifications venant du projet originel grâce à : $ git pull === Système ultime de sauvegarde === Vous voulez des archives redondantes et géographiquement distribuées, permettant de faire face à un désastre ? Si votre projet a beaucoup de développeurs, ne faites rien ! Chaque clone de votre code est de fait une sauvegarde. Non seulement de l'état actuel, mais de l'historique complet. Grâce aux empreintes cryptographiques, si le clone de quelqu'un est corrompu, il sera repéré dès qu'il tentera de communiquer avec d'autres. Si votre projet n'est pas si populaire, trouvez autant de serveurs que possible afin d'héberger vos clones. Le vrai paranoïaque devrait toujours noter la dernière empreinte SHA1 de 20 octets du HEAD dans un endroit sûr. Ce doit être sûr, pas privé. Par exemple, la publier dans un quotidien marcherait bien, parce qu'il est difficile de réaliser une attaque modifiant l'ensemble des exemplaires d'un journal. === Le multi-tâche à la vitesse de la lumière === Imaginons que vous souhaitiez travailler sur plusieurs fonctionnalités en parallèle. Dans ce cas validez (`commit`) votre projet et lancez : $ git clone . /un/nouveau/dossier Grâce aux http://fr.wikipedia.org/wiki/Lien_mat%C3%A9riel[liens matériels], les clones locaux sont créés plus rapidement et occupent moins de place que de simples copies. Vous pouvez maintenant travailler simultanément sur deux fonctionnalités indépendantes. Par exemple vous pouvez modifier l'un des clones pendant que l'autre est en cours de compilation. À tout moment vous pouvez valider (`commit`) vos modifications puis rapatrier (`pull`) les modifications depuis l'autre clone. $ git pull /mon/autre/clone HEAD === Guérilla de la gestion de versions === Alors que vous travaillez sur un projet qui utilise un autre système de gestion de versions, Git vous manque ? Dans ce cas, initialisez un dépôt Git dans votre dossier de travail. $ git init $ git add . $ git commit -m "Commit initial" puis clonez-le : $ git clone . /un/nouveau/dossier Allez ensuite dans le nouveau dossier et travaillez plutôt là, utilisant Git comme vous le voulez. De temps à autre, quand vous voulez vous synchroniser avec les autres, rendez-vous dans le dossier de départ, synchronisez-le en utilisant l'autre système de gestion de version, puis saisissez : $ git add . $ git commit -m "Synchro avec les autres" Ensuite allez dans le nouveau dossier et lancez : $ git commit -a -m "Description de mes modifications" $ git pull La procédure pour partager vos modifications avec les autres dépend de l'autre système de gestion de versions. Le nouveau dossier contient les fichiers avec vos modifications. Lancez toute commande de l'autre système de gestion de versions nécessaire pour les envoyer au dépôt central. Subversion, qui est peut être le meilleur système de gestion de versions centralisé est utilisé par d'innombrables projets. La commande *git svn* automatise la procédure ci-dessus pour les dépôts Subversion, et peut aussi être utilisée pour exporter un projet Git vers un dépôt Subversion. === Mercurial === Mercurial est un système de gestion de versions similaire qui peut travailler quasiment sans heurt avec Git. Avec le plugin `hg-git` un utilisateur de Mercurial peut, sans rien perdre, envoyer (push) vers ou rapatrier (pull) depuis un dossier Git. Téléchargez le plugin `hg-git` avec Git : $ git clone git://github.com/schacon/hg-git.git ou Mercurial: $ hg clone http://bitbucket.org/durin42/hg-git/ Malheureusement, il ne semble pas y avoir de plugin analogue pour Git. Pour cette raison, il semble préférable d'utiliser Git plutôt que Mercurial pour le dépôt principal. Avec un dépôt Mercurial, il faut généralement un volontaire qui maintienne un dépôt Git en parallèle alors que, grâce au plugin `hg-git`, un dépôt Git fait l'affaire même pour les utilisateurs de Mercurial. Bien que ce plugin puisse convertir un dépôt Mercurial en un dépôt Git en le poussant dans un dépôt vide, cette tâche est plus simple avec le script `hg-fast-export-git`, disponible via : $ git clone git://repo.or.cz/fast-export.git Pour faire une conversion, dans un nouveau dossier : $ git init $ hg-fast-export.sh -r /depot/hg ceci après avoir ajouté le script à votre `$PATH`. === Bazaar === Nous allons rapidement évoquer Bazaar parce que c'est le système de gestion de versions distribué libre le plus populaire après Git et Mercurial. Bazaar à l'avantage d'avoir plus de recul, étant donné qu'il est relativement jeune ; ses concepteurs ont pu tirer les leçons du passé et éviter des petits écueils historiques. De plus ses développeurs ont le souci de la portabilité et de l'interopérabilité avec les autres systèmes de gestion de versions. Un plugin `bzr-git` permet aux utilisateurs de Bazaar de travailler avec les dépôts Git dans une certaine mesure, et permet de le faire de manière incrémentale, tandis que `bzr-fast-export` est fait pour les conversions uniques. === Pourquoi j'utilise Git === Au départ j'ai choisi Git parce que j'ai entendu qu'il gérait l'inimaginablement ingérable source du noyaux Linux. Je n'ai jamais ressenti le besoin d'en changer. Git m'a rendu de fiers services et je ne me suis toujours pas heurté à ses limites. Comme j'utilise surtout Linux, les éventuels problèmes sur d'autres plateformes n'entrent pas en ligne de compte. De plus je préfère les programmes C et les scripts bash aux exécutables comme les scripts Pythons : il y a moins de dépendances et je suis accro aux temps d'exécution rapides. J'ai réfléchi à la manière d'améliorer Git, allant jusqu'à écrire mes propres outils de type Git, mais uniquement à des fins de recherche. Même si j'avais terminé ce projet j'aurais tout de même continué avec Git vu que les avantages sont trop peu significatifs pour justifier l'utilisation d'un système farfelu. Bien sur, vos besoins et envies diffèrent sûrement et vous pouvez très bien vous trouver mieux avec un autre système. Néanmoins vous ne pouvez pas faire une grosse erreur en choisissant Git. // LocalWords: visual-line checkout Git doc Clonons clonage synchros tar rsync // LocalWords: git HEAD init add bare mkdir proj.git cd DIR daemon detach web // LocalWords: tourne-t-il push repository clonent fetch pare-feux shell Forker // LocalWords: fork cryptographiques SHA multi-tâche clonez-le synchronisez-le // LocalWords: Synchro svn Mercurial plugin hg-git Téléchargez hg-fast-export.sh // LocalWords: hg-fast-export-git PATH Bazaar portabilité l'interopérabilité // LocalWords: bzr-git incrémentale bzr-fast-export l'inimaginablement ingérable // LocalWords: Linux plateformes bash accro