Archives de la catégorie Astuces et Outils
Git + Subversion : arrêtez d’ignorer ce que vous devriez ignorer (?!)
Posté par Christophe dans Astuces et Outils le 09/16/2010
Parfois on se retrouve à faire du Git, en local, sur un dépôt distant Subversion. Ça arrive en fait dans deux situations :
- On est en train de passer un dépôt de Subversion vers Git, en vue d’abandonner le premier au profit du second (yay !).
- On est obligé de bosser sur un dépôt Subversion, mais on refuse de laisser tomber le confort quotidien de Git en local.
Git propose une passerelle au moyen de la commande git svn et de ses sous-commandes. Moyennant quelques précautions d’usage, on peut ainsi travailler avec Git en local et synchroniser vers (et depuis) le dépôt Subversion distant. C’est un sujet assez vaste et j’y reviendrai plus en détail dans un prochain billet.
Toutefois, ceux qui rencontrent déjà ces situations ont sans doute remarqué un phénomène irritant : Git ne prend pas en compte la propriété svn:ignore. En fait, il ne prend en compte que svn:executable (ce qui est déjà pas mal, vu comme elle est grave utile…).
La propriété svn:ignore est similaire au fichier .gitignore : elle permet de lister des motifs de fichiers qui ne doivent pas être versionnés. Il est donc dommage qu’on n’en bénéficie pas automatiquement sur Git, risquant ainsi de versionner par erreur des fichiers qui devraient être ignorés.
Voilà pourquoi j’ai développé un petit outil qui va automatiquement synchroniser vos svn:ignore vers vos .gitignore, à tout moment, pour votre master (c’est-à-dire votre trunk distant), sans écraser d’éventuelles infos déjà présentes dans vos .gitignore… C’est le premier d’une série probable de petits scripts du même genre, destinés à faciliter l’utilisation de Git au quotidien.
Comme mon récent outil git-basecamp, il est disponible en open-source, et documenté, sur GitHub. Je vous invite donc à jeter un œil à mon dépôt git-helpers. Notez qu’il existe aussi une quantité de dépôts nommés « git-tools » sur Github, mais aucun de ceux que j’ai regardés n’avait cette fonctionnalité (et la plupart des aides qu’ils fournissent m’ont semblé un peu basiques…).
Enjoy !
Comprendre et maîtriser les clés SSH
Posté par Christophe dans Astuces et Outils, Didacticiels le 09/13/2010
Git base toute sa gestion d’authentification sur le mécanisme des clés SSH. Ce système est d’ailleurs immensément utile de façon générale sous Linux, Unix et OSX, dès qu’il s’agit de s’authentifier sur une machine tierce. Afin d’avoir un maximum de confort lorsqu’on accède à un dépôt nécessitant une identification (lecture de dépôts privés ou écriture dans le cas général), il est donc important de bien maîtriser les clés SSH.
Ce billet tente de vous donner toutes les clés (ahem) pour comprendre et manipuler aisément vos identités SSH.
Après un topo rapide sur le principe des clés asymétriques, nous verrons rapidement quels algorithmes sont à favoriser, quelles tailles de clé sont acceptables, et les meilleures pratiques de protection de vos clés (tant en termes de passphrase que de gestion des droits d’accès à vos fichiers de clés).
Ces fondamentaux étant assimilés, nous pourrons vérifier si vous avez déjà des clés, comment en créer de nouvelles, et comment vous en servir efficacement et confortablement pour vos accès à des dépôts Git.
Principe des clés asymétriques
Quand vous travaillez avec des clés asymétriques, par principe, vous avez deux clés (on parle de paire de clés) : une clé publique, que vous pouvez diffuser librement, voire mettre à disposition sur un serveur de clés ; et une clé privée, qui constitue véritablement votre « identité », et ne doit jamais être diffusée : elle reste simplement présente dans votre dépôt de clés personnel.
Comme toujours en cryptographie, on peut faire deux choses avec une clé : chiffrer un contenu (l’encrypter) ou le signer (calculer une valeur unique, reposant sur le contenu concerné et sur votre clé privée, pour obtenir une valeur de signature, comme un cachet spécifique). Seule la clé « d’en face » (la publique si vous avez utilisé la privée, et inversement) permet de déchiffrer ou de vérifier la signature. Notez au passage que signer un contenu permet non seulement d’attester que vous êtes bien l’envoyeur (ou l’auteur, etc.), mais aussi que le contenu n’a pas été modifié après signature.
Une paire de clé permet donc de vous représenter vis-à-vis d’un système tiers, en lui fournissant à l’avance votre clé publique, pour ensuite communiquer avec lui à l’aide de votre clé privée ; puisque seules les clés d’une même paire peuvent se comprendre, le système distant est à même non seulement de vérifier que vous êtes bien celui (ou celle) que vous prétendez être, mais aussi que ce qu’il reçoit est bien ce que vous envoyé. Pas mal !
Si le sujet vous intéresse, vous trouverez une tonne d’infos sur Wikipedia. Mais si j’étais vous, je finirais cet article d’abord histoire de ne pas partir sur une tangente…
RSA vs. DSA
Il existe de nombreux algorithmes de chiffrement basés sur des clés asymétriques, mais les deux dominants, et de loin, son RSA et DSA, d’après les initiales de leurs auteurs respectifs. RSA est historiquement le premier, et DSA a été développé plus récemment, comme une alternative alors qu’RSA était encore breveté.
De nombreux didacticiels, articles et documentations exploitent RSA, mais vous pouvez choisir librement RSA ou DSA pour vos clés, du moment que vous utilisez une taille suffisante (voir ci-après).
Taille de clé
Une clé a une taille, exprimée en nombre de bits. Par exemple, les clés exploitées par les certificats de chiffrement des sites web utilisant la protection SSL (vous savez, ces URLs qui démarrent en https://, par exemple votre gestion de compte bancaire en ligne) sont généralement limitées, pour des raisons légales d’origine honteuse, à 256 bits. En revanche, vos propres clés ne font pas (ou plus, suivant le pays où vous vivez) l’objet d’une telle limitation.
À ce jour, une taille de 2Ko, c’est-à-dire 2048 bits (oui, 8 fois plus qu’un certificat bancaire !) est considérée raisonnablement sécurisée pour RSA, en tout cas pour un particulier. En gros, même si la toute-puissante NSA avait envie de casser votre chiffrage pour jeter un œil à ces données, il leur faudrait quelques heures pour y parvenir. Et pour qu’ils daignent vous allouer quelques heures de leur système, vous devez en gros être un très, très gros poisson.
Donc on est tranquilles.
Notez qu’en revanche une clé DSA fait obligatoirement 1024 bits (1Ko). C’est comme ça.
Passphrase
Vous avez certainement l’habitude voir le terme password, c’est-à-dire mot de passe. Et vous avez sûrement déjà rencontré des tas de systèmes, services et outils qui vous demandent de saisir un mot de passe, en lui imposant une taille minimum (ce qui est bien) et maximum (ce qui est parfaitement stupide et contre-productif). À cause de ce maximum, justement, ces systèmes insistent pour que vous mélangiez à loisir majuscules, minuscules, chiffres et symboles, et n’utilisiez pas de termes trop évidents (dates de naissances, prénoms, noms de vos animaux, mots basiques, segments de touches du clavier, etc.).
Du coup, tout le monde se retrouve forcé d’utiliser des mots de passe genre &dF@8^Xy+, qui sont tellement tordus qu’on s’empresse de les noter sur un papier, massacrant instantanément l’utilité du mot de passe en le rendant facile à découvrir en cas de besoin (surtout quand ledit papier est un Post-It™ collé sous le clavier, voire sur l’écran) (ne rigolez pas, je l’ai déjà vu) (plusieurs fois) (en fait, si ça se trouve, vous l’avez déjà fait) (gredin(e) que vous êtes).
Par contraste, une passphrase (pas d’équivalent français satisfaisant à ma connaissance, aussi essayez de le prononcer correctement, genre passfrayz) est une petite phrase, ou tout au moins un morceau de phrase, donc plusieurs mots. Et je dis bien mots, parce qu’en l’occurrence, utiliser de vrais mots et noms ne pose plus guère de problème, dès lors qu’on en a au moins 3 ou 4, surtout s’ils n’ont aucun rapport.
« Mais on m’a toujours dit que des vrais mots Saymal™ ! », me hurlez-vous avec consternation, le sourcil vengeur.
Oui, sauf dans des jolies passphrases. Pourquoi donc ? Parce que le niveau de complexité augmente de façon plus qu’exponentielle au fil des caractères, en particulier quand on commence à découper en mots. En cryptographie, on considère qu’un mot de passe, ou une passphrase, peuvent appartenir à plusieurs niveaux de sécurité, qui correspondent à la difficulté qu’on rencontre pour les casser. La recherche sur le sujet abonde est se met à jour chaque année, notamment au sein de conférences spécialisées comme la célèbre DEFCON.
Je suis assez fan de cet excellent article de Thomas Baekdal, qui illustre bien le sujet. Imaginons une passphrase qu’il faudrait des centaines d’années, voire des millénaires, dans l’état actuel de la technologie la plus avancée, pour casser par un moyen technologique. On qualifie une telle passphrase de « sécurisée à vie » (secure for life). Eh bien, pour obtenir une telle passphrase, il suffit de combiner au moins 3 mots, pas nécessairement sans rapport, pour un total d’au moins une dizaine de caractères. Voici quelques exemples de telles passphrases :
- this is fun (sérieux ! Il faudrait au moins 25 siècles…)
- j’aime les noix de cajou (le système solaire aura déjà imposé d’ici qu’on casse ça…)
- des filles à la vanille
- san pellegrino enterre badoit
- i love to boogie
- tu fais du vb dommage eliane
- entre git et svn j’ai choisi
- plutot crever qu’installer vista
- …
Vous avez immédiatement perçu l’avantage monstrueux d’une bonne passphrase, lecteurs fûtés que vous êtes : non seulement c’est sécurisé à vie, mais en plus c’est carrément plus facile à mémoriser !
Bon, vous allez me rétorquer que c’est vachement plus long à taper, et là je vous répondrais que oui, mais qu’il existe des tas d’outils de type agents SSH, trousseaux de clés et systèmes de mémorisation de mot de passe (dans votre navigateur par exemple), qui sont de manière générale une bonne idée (surtout si vous leur mettez un mot de passe maître, à taper une seule fois par session, qui les déverrouille explicitement). Puisque nous parlons ici spécifiquement de clés SSH, nous aborderons plus loin comment éviter la saisie systématique de sa passphrase.
Parce que ne vous avisez surtout pas de « résoudre » le pseudo-problème de la longueur du texte en utilisant une passphrase vide. Ce serait complètement stupide, parce que ça reviendrait à ne pas du tout protéger votre clé ! Donc assurez-vous d’utiliser une bonne passphrase bien solide, et préférez les agents SSH (que ne vous verrons plus bas, je le répète) pour vous éviter des saisies multiples.
Vérifier ce qu’on a comme clé
Bon, il est l’heure de vérifier si vous avez déjà une paire de clés du bon type (DSA)…
Sur tous les systèmes Linux et Unix, vos clés SSH sont normalement stockées dans un dossier .ssh à la racine de votre profil. Ouvrez donc un terminal et tapez la commande suivante :
ls -lAF ~/.ssh
Si vous avez un message d’erreur (genre « je ne connais pas ce dossier ») ou un listing ne contenant que des fichiers style authorized_keys, config ou known_hosts, vous n’avez pas encore de clé exploitable. Ce que vous cherchez, ce sont des fichiers qui, classiquement, s’appellent id_dsa (la clé privée) et id_dsa.pub (la clé publique). Ce sont de bêtes fichiers texte, avec un peu d’enrobage autour de votre clé représentée dans un format appelé Base64. Par exemple, sur mon portable, le listing donne ça :
$ ls -lAF ~/.ssh total 48 -rw------- 1 tdd tdd 90 déc 11 2009 config -rw------- 1 tdd tdd 736 aoû 23 2007 id_dsa -rw------- 1 tdd tdd 609 aoû 23 2007 id_dsa.pub -rw------- 1 tdd tdd 736 jul 17 09:17 id_dsa_git -rw-r--r-- 1 tdd tdd 609 jul 17 09:17 id_dsa_git.pub -rw------- 1 tdd tdd 668 avr 6 22:53 id_dsa_sips -rw-r--r-- 1 tdd tdd 23696 jul 24 11:07 known_hosts
Comme vous pouvez le constater, ma clé fondamentale date un peu (23 août 2007), et j’ai une deuxième paire dédiée pour Git (id_dsa_git), ce qui n’a rien d’obligatoire, ainsi qu’une troisième, dont je n’ai ici que la clé privée, et qui me sert encore à autre chose.
Vous n’avez pas de clé DSA, ou vous en avez une dont vous ignorez la passphrase pour quelque raison que ce soit ? Ou peut-être en voulez-vous une dédiée pour Git ? Pas de souci, on va en créer une nouvelle !
Créer une clé
L’outil de prédilection pour créer des clés (et un peu tout ce qui touche à la crypto) est le système OpenSSL. C’est un ensemble de bibliothèques et outils en ligne de commande, présent sur tous les Linux et Unix (entre autres), qui constitue le standard de facto. Dommage qu’il soit si mal documenté… Ici, on peut passer par une surcouche spécialisée dans les clés SSH, au travers de l’outil en ligne de commande ssh-keygen.
Pour créer une paire de clés DSA, on procède comme suit. Je suppose ici que vous allez changer le nom par défaut vers id_dsa_ga (pour Git Attitude), mais si vous laissez le nom par défaut, il suffit de taper Entrée à la question correspondante. Évidemment, utilisez votre propre chemin.
$ ssh-keygen -t dsa Generating public/private dsa key pair. Enter file in which to save the key (/Users/tdd/.ssh/id_dsa): /Users/tdd/.ssh/id_dsa_ga Enter passphrase (empty for no passphrase): Enter same passphrase again: Your identification has been saved in /Users/tdd/.ssh/id_dsa_ga. Your public key has been saved in /Users/tdd/.ssh/id_dsa_ga.pub. The key fingerprint is: 65:31:7e:ee:49:3a:66:cd:92:7b:02:2b:bf:b3:1a:79 tdd@CodeMagic.local The key’s randomart image is: +--[ DSA 1024]----+ | o | | . o | | + . | | o o | | S o | | .. B . | | o EoB = | | .ooo.+. | | .+++.o | +-----------------+
Suivant votre version de ssh-keygen, vous n’aurez pas forcément le randomart à la fin (et en vrai, on s’en fout), et la ligne qui suit « The key fingerprint is: » sera totalement spécifique à votre propre exécution de la commande. Chaque paire de clé a une empreinte unique.
Et de fait, regardez un peu vos clés toutes neuves (vous aurez naturellement des valeurs différentes de celles présentées ici, celle de la privée étant d’ailleurs tronquée par mes soins :)
$ cat ~/.ssh/id_dsa_ga -----BEGIN DSA PRIVATE KEY----- Proc-Type: 4,ENCRYPTED DEK-Info: DES-EDE3-CBC,6ED59B013D8A361F pB5eHHpvXxoz6i1jFzlKANv9W6SeHw664PV/1A90acR/Mw/ERQvTQKo3TaLaFhkb … NwhQFyxZZty2hn6xrv5UIAGTpjk+P2+waRmSno1Vg1x0epCp45kvFRv9AiXsOpt4 RgzPC5+a6kjPf8EtyozGoQ== -----END DSA PRIVATE KEY----- $ cat ~/.ssh/id_dsa_ga.pub ssh-dss AAAAB3NzaC1kc3MAAACBAJhbQcZK8lFMvpw7trbFj51Sqjd9nKBu2xkw/kvUAQlPQPaIRLOiq92fxp+jzp97xDqpwFnvU++ptUiB1nQQ8oq8l5t5QuHwfMMnSDMXhWf2235i4Lw2DtRTbxs0UQJ1l+QxO/AjlV/POcFpq6Z0PKMosi8TslqqPaqAbQtiEX2DAAAAFQDaK1EZY12itrt0lomTAOT0QATilwAAAIAK9C0YTR0T82r7TFheo/+vU6dS9KCypEjR7rEVf7MxCJLd9MQNkVTJe7XCFnYeT9oz7h8NbYHGyDQr7EZGIchtiju6EPFWuQWEAJAHq7z9s9ygoVqyWSQo0y/6riihJk5bo+Etj//OdwndlfKg0c6UGBFg8T2i6nKsbmMMEAI+XAAAAIA+bPjEeoZhwLuCp3Bv0+B4mWgGqnb2IhRSVDQNYeHIofhiSY7prVB+O1iQhrN/EJlygkaFWNaVlPmxrXa+8i+ZGWeVlAaKJdSAsDawNjOaHTi6/Cfqm7NTrLIIeOcjjxwrPLPZ3v0tP8MFjhYFdgjooYjTDzqQmpCGVSA4hXtqhg== tdd@CodeMagic.local
Notez que les clés publiques sont généralement formatées sur une seule ligne ; dans une liste de clés (par exemple le fichier ~/.ssh/authorized_keys, qui liste les clés publiques dont les titulaires peuvent accéder à votre compte via SSH), on a donc en général une clé par ligne. La fin de la clé publique est son commentaire, qui vaut par défaut « identifiant@machine », mais peut être changé.
Dernière info sur la manipulation des fichiers de clé : on peut changer la passphrase d’une clé SSH avec la ligne de commande suivante :
$ ssh-keygen -p -f ~/.ssh/le_fichier_de_cle
La commande vous demandera votre ancienne passphrase, puis la nouvelle avec une double saisie (initiale puis de confirmation). Pratique si vous aviez saisi une passphrase un peu pourrie, par exemple. En revanche, si votre clé est compromise (vous avez des raisons de penser qu’un tiers s’est approprié votre clé privée), ne changez pas la passphrase (ça ne servira à rien) : changez de clé !
Agents SSH
Un agent SSH est un outil intégré à votre système d’exploitation qui vous permet de ne saisir la passphrase d’une clé qu’une seule fois (pendant la durée de vie de l’agent, généralement limitée à votre session, entre connexion et déconnexion).
OS X intègre cette fonction dans son outil plus général de Trousseau d’Accès (Keyring) depuis Leopard (10.5). Avant cela (par exemple Tiger, la 10.4), il fallait ruser comme décrit dans cet article. La première utilisation d’une clé entraîne l’affichage d’une demande de passphrase, et la possibilité de stocker celle-ci dans le trousseau d’accès pour éviter des saisies supplémentaires durant la session.
Ubuntu et ses variantes intègrent cette fonction aux principaux gestionnaires de fenêtre (Gnome, KDE, etc.). Le workflow est similaire à celui d’OS X : la première utilisation entraîne une demande de passphrase avec persistence dans l’agent.
Pour les autres distributions Linux et gestionnaires de fenêtre, je ne sais pas trop si un agent est déjà disponible ou pas. Vous pouvez le vérifier en ouvrant un terminal puis en tapant :
$ set | grep SSH_AUTH_SOCK
Si vous ne voyez rien s’afficher, vous n’avez pas d’agent actif ; si vous voyez quelque chose (probablement du genre /var/run/….sock), alors vous en avez un.
Si vous n’avez pas d’agent actif, vous pouvez en lancer un manuellement à l’aide de la bien-nommée commande ssh-agent. Celle-ci crée un processus résident (un daemon) et affiche la série de commandes à balancer dans l’environnement (ou dans chaque terminal) pour qu’il soit au courant que l’agent existe, et donc qu’il essaie de s’en servir. Ces commandes consistent généralement juste à définir les variables d’environnement SSH_AUTH_SOCK et SSH_AGENT_PID. Du coup quand on lance un agent à la main dans le shell courant, on récupère généralement son affichage pour l’exécuter aussi sec, comme ceci :
$ eval `ssh-agent` Agent pid 23038
Évidemment, vous verrez un autre numéro de processus (pid), mais le principe est le même.
À partir de là, à vous de tester le comportement lors de la première utilisation d’une clé SSH : si vous voyez une interception globale vous demandant de saisir la passphrase et proposant de la stocker dans l’agent, tout baigne. Si ce n’est pas le cas, vous allez devoir ajouter la passphrase à l’agent manuellement, en utilisant la commande ssh-add. Dans ce cas, soit vous avez une seule clé, et vous n’avez pas besoin de la préciser, soit vous en avez plusieurs et il faut indiquer laquelle :
$ ssh-add ~/.ssh/id_dsa_ga Enter passphrase for /Users/tdd/.ssh/id_dsa_ga: Identity added: /Users/tdd/.ssh/id_dsa_ga (/Users/tdd/.ssh/id_dsa_ga)
Après ça, la passphrase est automatiquement exploitée pendant toute la durée de vie de l’agent.
Ce type de manip’ est notamment utile quand on se connecte sur un serveur de production où on va faire une série de git pull, git submodule update, etc. et où on veut éviter de taper sa passphrase une tonne de fois. On commence par configurer l’agent, ajouter sa clé, et hop ! On est prêt à rouler.
Enfin, pour ce qui est de Windows, avec msysGit spécifiquement, vous trouverez quelques instructions pour lancer automatiquement ssh-agent sur cette documentation chez GitHub.
Publier sa clé publique ?
Les clés asymétriques ne sont pas seulement utiles pour SSH et les systèmes se greffant par-dessus. Elles sont aussi, par exemple, le moyen privilégié pour (dé)crypter ou signer numériquement (ou les deux) les e-mails. Je rêve du jour où tout le monde saura utiliser correctement le medium e-mail : pas de pièces jointes énormes ou débiles, pas de liste d’e-mails destinataires visible par tout le monde, pas de HTML pourri rempli de Comic Sans MS… et l’habitude de signer les e-mails importants. Ce dernier point, notamment, ouvrira le chemin des e-mails comme moyen valide de communication à valeur légale, par exemple avec votre banquier, votre notaire, votre avocat, etc.
Si le sujet vous intéresse, jetez par exemple un œil au client de messagerie Thunderbird et à son extension Enigmail, basée sur l’outil libre GnuPG (naturellement, il existe d’autres possibilités techniques autour d’Apple Mail, de GMail et j’en passe).
Dans un tel contexte, il est important de pouvoir facilement récupérer la clé publique de quelqu’un, soit parce qu’on veut lui envoyer un contenu confidentiel (on va donc le chiffrer avec la clé publique du destinataire, dont seule la clé privée pourra déchiffrer), soit parce qu’on a reçu un e-mail signé numériquement de cette personne (grâce à sa clé privée), et qu’on veut vérifier que ça vient bien d’elle, et que le contenu n’a pas été altéré (ce qu’on peut faire uniquement à l’aide de sa clé publique).
Bien entendu, la personne en question peut nous avoir, au préalable, transmis sa clé publique. Encore faut-il pouvoir faire confiance au mécanisme qui a fait cette transmission (il existe des moyens, dont l’empreinte de la clé, mais ce n’est pas le sujet de cet article). Un autre moyen plus général est, pour la personne, de publier sa clé publique aux yeux de tous. Pour cela, il existe des serveurs de clés. La plupart sont gratuits, et les plus connus sont répertoriés par les principaux systèmes exploitant des clés. En voici quelques-uns :
Et Git dans tout ça ?
La plupart des hébergements de dépôt Git reposent sur des clés SSH publiques pour identifier les personnes ayant un accès aux dépôts. Lorsque vous accédez à un dépôt authentifié, que ce soit en protocole git://… ou git@…, le système SSH sous-jacent va passer en revue vos clés privées au regard des clés publiques qu’il connaît, et s’il trouve une correspondance, vous demander la passphrase (à moins qu’un agent ne la lui fournisse tout seul) puis engager la suite des opérations.
Dans le cadre des ateliers Git Attitude, lorsque nous étudions l’interaction avec des dépôts distants, j’ai besoin de disposer de clés publiques dont vous avez l’homologue privée, afin de configurer vos accès au serveur Gitosis que nous utilisons. Vous recevez dans vos convocations une demande pour me fournir cette clé à l’avance, avec un lien vers cet article si vous vous sentez déboussolés
J’espère que cet article vous a été utile, et vous a permis de mieux comprendre les clés SSH et leurs meilleures pratiques d’utilisation. Si vous avez des questions, commentaires ou corrections, les commentaires sont là pour ça !
Git, Basecamp, et un peu de magie
Posté par Christophe dans Astuces et Outils le 09/08/2010
Je viens de sortir un petit outil open-source qui facilite énormément le suivi de temps sur Basecamp relatif à vos travaux sur Git.
Quoi ?! Vous n’utilisez pas Basecamp ! Mais c’est pas bien, ça ! Allez donc voir comme c’est top.
L’idée est d’analyser vos messages de commit à la recherche d’un petit tag spécifique sur la fin, qui va permettre à un script post-commit de déterminer le temps de travail, l’éventuelle tâche spécifique associée, et de loguer le temps qui va bien. C’est super pratique et je m’en sers déjà sur plusieurs projets, toute la journée.
Ça se passe ici, et y’a une doc détaillée. Enjoy !
Installer un Git récent
Posté par Christophe dans Astuces et Outils, Didacticiels le 08/05/2010
Vous aimez déjà Git, ou vous souhaitez le découvrir ? Vous allez participer à un Atelier Git Attitude ? Il vous faut alors installer une version récente sur votre poste de travail, et sans doute aussi sur vos machines de déploiement, de staging, etc. Cet article essaie de vous donner toutes les clés pour faire cela aussi rapidement et facilement que possible.
Récent… c’est-à-dire ?
À l’heure où j’écris ceci, la dernière version stable de Git est la 1.7.2.1. La plupart des systèmes pré-packagés sont encore sur la précédente, la 1.7.1.1 (qui est très récente aussi), mais ça va vite se mettre à jour…
Concrètement, les différences avec des versions plus anciennes (jusqu’à 1.5.0, qui a introduit les derniers changements en date de structure du dépôt) sont quelque peu mineures et focalisées sur des détails d’options et de raffinement dans les décorations des logs, l’exécution d’outils externes (on pense notamment aux outils de diff), quelques fonctionnalités de confort, etc.
En termes de compatibilité sur le dépôt et d’opérations courantes, tout Git au moins 1.5.0 saura manipuler un dépôt plus récent, par exemple (ce qui peut avoir son importance si, par exemple, vous déployez sur un hébergement mutualisé dont les versions seraient un peu rances).
Je vous recommande d’avoir au moins une 1.6.6, mais compiler le code source sur votre plate-forme reste la meilleure façon d’avoir une version à jour, optimisée pour votre situation et dotée de tout le dernier confort proposé, notamment pour les usages avancés.
Un mot sur la doc
Git est un outil extrêmement puissant et riche, avec ses quelque 75 commandes de haut niveau (dites « porcelain ») et près de 60 commandes de bas niveau, à usage surtout interne (dites « plumbing »). Même les commandes principales, utiles pratiquement au quotidien, qui sont à peu près 20, recèlent une puissance insoupçonnée ; à ce titre, leur documentation est un atout précieux.
En effet, je trouve que les auteurs et mainteneurs de Git ont fait un boulot exceptionnel sur la documentation des commandes, à laquelle on peut accéder soit en tapant git help COMMANDE soit, lorsqu’on a la commande man, avec un man git-COMMANDE (les deux sont équivalents mais je préfère personnellement la première syntaxe).
Cependant, les méthodes d’installation par source ou par paquets ne l’installeront pas toujours par défaut : il vous appartient d’installer les bons paquets auxiliaires (typiquement git-doc) ou d’appeler les bonnes commandes de compilation et d’installation. Nous y reviendrons.
Installer Git sur OSX
Sur OSX, je ne saurais trop vous recommander de passer par l’installeur binaire hébergé sur Google Code, le projet git-osx-installer. Il est calé (là tout de suite) sur la 1.7.2 et installe les docs au passage, donc aucune raison de se priver ! Tout est installé dans /usr/local/git par défaut.
C’est de loin l’option la plus simple : compiler à partir des sources sur OSX exige une kyrielle de pré-requis qui peuvent être pénibles à obtenir, qu’on passe par Macports, Fink, Homebrew ou d’autres voies…
Installer Git sur Linux
Approche 1 : utiliser des paquets
Il existe généralement plusieurs paquets se répartissant les fonctionnalités et documentations de Git, paquets aux noms raisonnablement explicites, typiquement git comme « paquet chapeau » (paquet virtuel entraînant l’installation des autres), git-core (la quasi-totalité des commandes), git-doc, git-gui, gitk et gitweb (interfaces graphiques et frontal web de navigation de dépôt), git-svn et git-cvs (passerelles avec d’autres SCM)…
Sur Ubuntu et ses dérivés, les paquets sont assez récents (1.7.0 sur Lucid Lynx à l’heure où j’écris ceci) ; il est toutefois possible d’avoir des versions très à jour en passant par un PPA (Personal Package Archive, dépôt Ubuntu officieux maintenu par une entité quelconque, un particulier par exemple), le plus connu dans le cas qui nous occupe étant celui d’Andrey Voronov, qui propose des paquets tout frais (donc 1.7.2) pour Ubuntu 8.04 (Hardy Heron) et 10.04 (Lucid Lynx). Si vous avez une 9.x, vous pouvez tester ces dépôts quand même, utiliser le paquet fourni (Git 1.6.0 en 9.04, Git 1.6.3 en 9.10) ou compiler la source.
Debian dispose de paquets raisonnablement récents, avec la 1.7.1 (si vous êtes en stable/lenny, vous aurez cependant besoin des dépôts « backports »).
Pour les distributions basées RPM, telles que Red Hat, SuSE et Mandriva, le site officiel de Git maintient des paquets RPM très à jour. Gentoo a un paquet dev-vcs/git en unstable, et comme c’est Gentoo, on est basés sur sources donc assez récent (1.7.2 semble-t-il). ArchLinux est, comme souvent, très à jour avec un paquet git en 1.7.2.1 qui n’a que peu de dépendances.
Enfin, sachez qu’on peut avoir un Git récent sur Solaris en passant par Sun Freeware.
Approche 2 : compiler le code source
Commencez par récupérer l’archive du code source complet (préfixe git-) au format de votre choix. Par exemple pour la 1.7.2.1, l’une des deux suivantes :
- http://www.kernel.org/pub/software/scm/git/git-1.7.2.1.tar.bz2
- http://www.kernel.org/pub/software/scm/git/git-1.7.2.1.tar.gz
D’une distribution à l’autre, les dépendances ne seront pas toujours les mêmes. Bon, vous allez faire une compil’, il vous faut donc naturellement build-essential, le paquet universel des distributions Linux pour pouvoir compiler des trucs. Je sais aussi qu’il vous faut généralement au moins Curl, Perl et Expat, mais si vous voulez les docs (et vous les voulez, faites-moi confiance…) vous aurez sans doute aussi besoin des paquets pour TCL/TK, xmlto et AsciiDoc. Sur une Debian/Ubuntu, ça donne une installation de paquets qui va durer un petit moment :
$ apt-get install -q -y build-essential libcurl4-openssl-dev curl perl expat tk asciidoc docbook2x xmlto
Allez donc prendre un café… Quand ce sera fini, c’est en revanche enfantin. Décompressez votre archive quelque part (par exemple dans /tmp/sources), allez dans le répertoire ainsi créé, puis :
$ ./configure … $ make all man … $ sudo make install install-man …
La clé ici est de bien penser à préciser les cibles man à la compilation (par défaut on n’a que all) et install-man ensuite. Si vous aimez utiliser l’outil de consultations de docs info, vous pouvez ajouter les cibles info et install-info, respectivement.
Une petite vérif’ ?
$ git --version git version 1.7.2.1
Bravo !
Installer Git sur Windows
Bon, déjà, soyons clair : ça sera largement moins bien que sur Linux ou OSX. Vous n’aurez pas les docs (pas de façon intégrée en tout cas), l’accès en ligne de commande (donc à toutes les commandes) n’est pas 100% automatique, et j’en passe. Mais bon.
Règle numéro 1 : tu ne te baseras par sur Cygwin. Car tu n’as pas une heure à perdre par commande, et la sous-couche Cygwin est horriblement lente en générale, et pour Git en particulier. Ouste !
Cela nous laisse les optionss suivantes :
- msysgit (également appelé « Git for Windows »). Cet outil propose un installeur exécutable hébergé sur Google Code, qui est assez bien maintenu (il est actuellement en 1.7.1). Il propose une interface graphique pour les opérations usuelles.
- SmartGit. C’est un enrobage Java, donc multi-plateformes en fait, autour de Git. On le trouve chez Syntevo, qui nous a déjà filé SmartSVN. Ça fournit une interface graphique pour les non-experts, notamment les non-développeurs, mais on n’y trouve, fatalement, aucune commande avancée. Pratique par exemple si vous voulez que vos graphistes / designers versionnent leurs fichiers au même titre que les développeurs. La version actuelle est la 1.5.4, je ne sais pas à quel Git ça correspond mais elle est sortie à peu près au moment de Git 1.7.1.1…
Complétion et prompt
Git fournit, dans son archive de code source (sa tarball), un script de complétion Bash tout simplement génial.
Il permet de compléter les commandes en profondeur (commandes, sous-commandes, arguments appropriés, y compris pour les aliases configurés dans Git), et fournit de surcroît la fonction de personnalisation avancée du prompt que j’avais déjà présentée dans Le prompt Bash qui change la vie avec Git (inutile donc de le garder dans votre fichier d’initialisation, ça ferait doublon pour rien).
D’ailleurs sa version ne cesse de s’améliorer (on a désormais une variable qui indique dans le prompt si on est en avance ou en retard par rapport à l’upstream, par exemple, et l’initialisation—qui a lieu la première fois d’une session qu’on arrive dans un dépôt—est de plus en plus rapide).
Que du bonheur ! Si vous ne voulez pas vous galérer à récupérer l’archive, la décompresser et piocher le bon fichier, faites donc juste la commande qui suit :
curl https://github.com/git/git/raw/master/contrib/completion/git-completion.bash -o ~/.git-completion
Ensuite, dans votre .bashrc (Linux) ou .profile (OSX), retirez si besoin vos fonctions de prompt existantes, et terminez en chargeant le script de complétion Git et en personnalisant votre prompt (ici avec plein de jolies couleurs) :
source ~/.git-completion export GIT_PS1_SHOWDIRTYSTATE=1 GIT_PS1_SHOWSTASHSTATE=1 GIT_PS1_SHOWUNTRACKEDFILES=1 export PS1='\[\033[35m\u@\h:\033[36m\W\[\033[0m\033[33m$(__git_ps1 " (%s)")\033[0m\$ '
Démonstration :
tdd@CodeMagic:~$ cd /tmp tdd@CodeMagic:tmp$ git clone git://github.com/tdd/sprockets-rails.git tdd@CodeMagic:tmp$ cd sprockets-rails tdd@CodeMagic:sprockets-rails (master)$ echo 'toto' > toto tdd@CodeMagic:sprockets-rails (master %)$ git add toto tdd@CodeMagic:sprockets-rails (master +)$ echo 'tutu' >> toto tdd@CodeMagic:sprockets-rails (master *+)$ git stash tdd@CodeMagic:sprockets-rails (master $)$ git stash pop tdd@CodeMagic:sprockets-rails (master *)$ git reset --hard HEAD tdd@CodeMagic:sprockets-rails (master)$ git <TAB><TAB> add commit instaweb revert am config lg rm annotate describe log send-email apply diff merge shortlog archive difftool mergetool show bisect fetch mv show-branch blame filter-branch name-rev st branch format-patch notes stage bundle fp pull stash checkout fsck push status cherry gc rebase submodule cherry-pick get-tar-commit-id relink svn ci grep remote tag citool gui repack whatchanged clean help replace clone imap-send request-pull co init reset tdd@CodeMagic:sprockets-rails (master)$ git merge <TAB><TAB> HEAD master origin/HEAD origin/master tdd@CodeMagic:sprockets-rails (master)$ git merge origin/master --<TAB><TAB> --commit --ff-only --no-commit --no-log --no-stat --stat --ff --log --no-ff --no-squash --squash --strategy …
Whoooohooooo !
Conclusion
Comme vous pouvez le voir, installer un Git récent n’a rien de sorcier, et disposer d’un Git complet, avec documentation intégrée, et doté d’une complétion et d’un prompt idoines, change tout simplement la vie… Alors bonne gestion de versions !
Héberger un serveur Git avec Gitosis (Linux / OSX)
Posté par Christophe dans Astuces et Outils, Didacticiels le 07/18/2010
Il y a plusieurs raisons pour vouloir disposer d’un hébergement Git. Les trois principales sont :
- disposer d’un backup distant de son travail,
- mettre son travail à la disposition d’autrui,
- collaborer avec d’autres sur un projet.
Hébergement public ou privé ?
Lorsque le projet est libre, ou qu’en tout cas son contenu est public, le plus simple consiste à exploiter un bon service d’hébergement Git qui serait gratuit pour les dépôts publics. Dans ce domaine, l’acteur désormais incontournable (et particulièrement bien foutu) est le célèbre GitHub.
En revanche, pour les dépôts privés, soit on reste sur GitHub, mais dès lors, c’est payant (pas cher ceci dit : à partir de $9/mois, ce qui permet de bénéficier de l’infrastructure massive du service, notamment en termes de fiabilité de stockage). Soit on crée son propre hébergement Git, ce qui a notamment l’intérêt éventuel de le rendre interne à sa société (et donc, potentiellement, très rapide d’accès sur un réseau local performant).
Ce billet vise à explorer en détail l’option technique favorite pour héberger son propre serveur Git : Gitosis.
Quand on connaît la procédure, récupérer, installer et configurer Git, qu’on soit sur OSX ou Linux, est l’affaire de 10 à 15 minutes. En lisant ce billet et les explications, ce sera naturellement un peu plus long. Mais ça reste rapide et facile !
Le prompt Bash qui change la vie avec Git
Posté par Christophe dans Astuces et Outils le 07/14/2010
Lors de l’atelier de samedi je vous ai promis un prompt Bash qui déboîte quand on fait du Git.
Celui-ci repose sur une série de fonctions Bash dont la plus « high-level » est appelée à chaque prompt. Elle permet de voir immédiatement :
- Dans quelle branche on est
- Si on a des modifs en working tree
- Si on a des modifs en stage
- Si on a des fichiers untracked
- Si on a du stash
Toutes choses fort utiles au moment de faire son commit, histoire de ne rien oublier…
Voici le code source avec quelques commentaires. Vous pouvez aussi aller piocher le Gist directement.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 | # Scavenged from Git 1.6.5.x contrib/completion/git_completion.bash # __git_ps1 accepts 0 or 1 arguments (i.e., format string) # returns text to add to bash PS1 prompt (includes branch name) __gitdir () { if [ -z "${1-}" ]; then if [ -n "${__git_dir-}" ]; then echo "$__git_dir" elif [ -d .git ]; then echo .git else git rev-parse --git-dir 2>/dev/null fi elif [ -d "$1/.git" ]; then echo "$1/.git" else echo "$1" fi } __git_ps1 () { local g="$(__gitdir)" if [ -n "$g" ]; then local r local b if [ -f "$g/rebase-merge/interactive" ]; then r="|REBASE-i" b="$(cat "$g/rebase-merge/head-name")" elif [ -d "$g/rebase-merge" ]; then r="|REBASE-m" b="$(cat "$g/rebase-merge/head-name")" else if [ -d "$g/rebase-apply" ]; then if [ -f "$g/rebase-apply/rebasing" ]; then r="|REBASE" elif [ -f "$g/rebase-apply/applying" ]; then r="|AM" else r="|AM/REBASE" fi elif [ -f "$g/MERGE_HEAD" ]; then r="|MERGING" elif [ -f "$g/BISECT_LOG" ]; then r="|BISECTING" fi b="$(git symbolic-ref HEAD 2>/dev/null)" || { b="$( case "${GIT_PS1_DESCRIBE_STYLE-}" in (contains) git describe --contains HEAD ;; (branch) git describe --contains --all HEAD ;; (describe) git describe HEAD ;; (* | default) git describe --exact-match HEAD ;; esac 2>/dev/null)" || b="$(cut -c1-7 "$g/HEAD" 2>/dev/null)..." || b="unknown" b="($b)" } fi local w local i local s local u local c if [ "true" = "$(git rev-parse --is-inside-git-dir 2>/dev/null)" ]; then if [ "true" = "$(git rev-parse --is-bare-repository 2>/dev/null)" ]; then c="BARE:" else b="GIT_DIR!" fi elif [ "true" = "$(git rev-parse --is-inside-work-tree 2>/dev/null)" ]; then if [ -n "${GIT_PS1_SHOWDIRTYSTATE-}" ]; then if [ "$(git config --bool bash.showDirtyState)" != "false" ]; then git diff --no-ext-diff --ignore-submodules \ --quiet --exit-code || w="*" if git rev-parse --quiet --verify HEAD >/dev/null; then git diff-index --cached --quiet \ --ignore-submodules HEAD -- || i="+" else i="#" fi fi fi if [ -n "${GIT_PS1_SHOWSTASHSTATE-}" ]; then git rev-parse --verify refs/stash >/dev/null 2>&1 && s="$" fi if [ -n "${GIT_PS1_SHOWUNTRACKEDFILES-}" ]; then if [ -n "$(git ls-files --others --exclude-standard)" ]; then u="%" fi fi fi if [ -n "${1-}" ]; then printf "$1" "$c${b##refs/heads/}$w$i$s$u$r" else printf " (%s)" "$c${b##refs/heads/}$w$i$s$u$r" fi fi } export GIT_PS1_SHOWDIRTYSTATE=1 GIT_PS1_SHOWUNTRACKEDFILES=1 GIT_PS1_SHOWSTASHSTATE=1 # Basique… # export PS1='\u@\h:\W$(__git_ps1) \$ ' # Avec plein de couleurs… export PS1='\[\033[0;37m\]\u@\h:\[\033[0;33m\]\W\[\033[0m\]\[\033[1;32m\]$(__git_ps1)\[\033[0m\] \$ ' |
Notez les variables qui configurent ce qui est affiché :
- GIT_PS1_SHOWDIRTYSTATE fait remonter les modifs en working tree (symbole *) et en stage (symbole +)
- GIT_PS1_SHOWUNTRACKED_FILES fait remonter les fichiers non présents dans l’index (non pris en compte jusqu’à ajout explicite) (symbole %)
- GIT_PS1_SHOWSTASHSTATE indique qu’on a des trucs dans le stash (symbole $)
Ça ralentit un tout petit peu le premier prompt de votre session dans un dépôt non trivial, le temps pour les commandes Git internes de construire les caches d’accès à l’index et à l’historique… Ensuite c’est instantané.
Je ne pourrais pas vivre sans !
Enjoy!