Blog myBlog = BlogFactory.getWordPressBlog();
Article tagué Git
Sauvegarde automatique de l’historique d’un document
27/09/11
Il est des semaines où on doit troquer son IDE préféré pour des outils bizarres tels que OpenOffice LibreOffice, Microsoft Office, voire pire… Microsoft Project. Or avec ces outils, on a vite fait de perdre plusieurs heures de travail avec une fausse manipulation. Afin de palier à ce problème, j’ai mis à contribution un de mes outils préférés : git. Il n’y a pas de raison que les documents ne soient pas versionnés, au même titre que du code. D’autant plus que le coût de mise en place d’une telle sauvegarde est très faible :
1 2 3 | git init git add mondocument git commit -m 'Première sauvegarde de mon document' |
Diff entre deux versions
En commitant régulièrement son document, on en constitue un historique. Et avec les branches, on peut même le décliner en plusieurs versions. Je n’ai par contre pas réussi à créer de « feature branch » documentaire, la fusion automatique de documents binaires avec git se passant bizarrement assez mal.
L’autre problème avec des documents binaires, c’est qu’ils passent assez mal dans le « diff », ce qui fait perdre à la gestion de configuration une partie de son intérêt. Mais pour ce problème là, il existe une solution. Il suffit d’avoir un outil permettant d’afficher un document un mode texte. Dans le cas du format OpenDocument, on peut par exemple utiliser odt2txt.
Il faut ajouter dans .gitconfig le bloc suivant, pour déclarer le convertisseur associé au format odf :
1 2 | [diff "odf"] textconv=odt2txt |
Enfin, dans le répertoire du dépôt du projet, il faut associé ce convertisseur avec les extensions des fichiers OpenOffice. Ca se passe dans le fichier info/attributes :
1 2 3 | *.odt diff=odf *.ott diff=odf # idem pour les formats ods, ots, odp et otp |
Cette modification effectuée, on récupère la possibilité de calculer le différentiel entre deux commits, et toutes les fonctionnalités associées.
Le seul inconvénient, c’est qu’il faut répéter cette opération pour chaque dépôt de documents. Je n’ai pas trouvé le moyen de définir ces comportements dans la configuration globale de git. Si quelqu’un a une solution, je suis preneur !
Automatisation de la sauvegarde
Afin d’améliorer un peu le processus, il suffit d’un petit script shell qui automatise l’enregistrement du document à intervalles réguliers :
1 2 3 4 5 6 7 8 9 | #!/bin/sh # Intervalle entre deux enregistrements SAVE_PERIOD_IN_SECONDS=120 while : do echo "Autosave : $(date)" git commit -a -m "Autosave $(date)" sleep $SAVE_PERIOD_IN_SECONDS done |
Ce script utilise une des particularités intéressantes de git : si le fichier n’a pas évolué pendant l’intervalle, le commit n’est pas effectué. Ainsi, l’historique des versions du document pourra sauter des enregistrements (si on a oublié d’enregistrer le document entretemps par exemple).
Pour finir, voici donc le script en action :
Mettre en place un workflow git
2/06/11
Si vous avez été à une ou deux présentations de git, vous avez sans doute déjà vu ce diagramme (ou un équivalent).
Après avoir un peu pratiqué git, ce genre de workflow devient naturel, et est particulièrement appréciable :
- les fonctionnalités ont chacune leur branche dédiée : la lecture de son historique n’est donc pas gêné par le reste des développements
- les livraisons peuvent être préparées sans empêcher les personnes qui travaillent sur les futures fonctionnalités de partager leur travail
- etc.
Voila pour la théorie : sur le papier, ça laisse absolument rêveur ! Mais dans la pratique, tout ne fonctionne pas aussi bien, surtout au début. Et c’est là que commence mon retour d’expérience sur la mise en place de ce workflow.
Gérer AUTREMENT un projet Maven avec Git
13/04/11
Comme vous avez été nombreux à apprécier mon article sur Maven et git, en voici la suite ! Il s’agit d’une solution alternative permettant de répondre à la même problématique, basée sur les subtree.
Rappel : mon but était de séparer la gestion de configuration de plusieurs modules Maven d’un même projet, tout en conservant un dépôt pour maintenir le projet (pom racine du projet, etc.).
La problématique étant la même, nous allons nous baser sur le même exemple : un projet créé à partir de l’archetype appfuse-modular-jsf. Pour sa mise en place de ce projet, je vous renvoie donc aux étapes Créer le projet de démonstration et Mise en place des dépôts distants.
Revenons à notre espace de travail
Maintenant que nous avons nos dépôts distants, la première chose à faire pour mettre en place les subtrees est de supprimer les répertoires des deux modules dans l’espace de travail. En effet, avec cette méthode, les modules n’ont pas de dépôt git locaux dédiés.
Déclarons ensuite les dépôts distants de notre espace de travail :
1 2 3 | git remote add origin $BARE_REPOS/demo.git # S'il n'existe pas déjà git remote add core $BARE_REPOS/demo-core.git git remote add webapp $BARE_REPOS/demo-webapp.git |
A ce stade, les habitués de git qui ne sont pas trop endormis doivent crier « KEUOUA ??? ». Effectivement, les démos distants sont normalement des clones du dépôt local. Or nous venons de déclarer trois dépôts distants qui n’ont pas un seul commit en commun.
Ce n’est pas une erreur, et c’est le mode de fonctionnement des subtrees. Contrairement aux submodules pour lesquels on avait trois dépôts locaux, avec les subtree, on a un unique dépôt local : le lien entre cet unique dépôt et les dépôts distants passe donc par les « remotes » du dépôt local.
Des branches locales pour travailler sur les modules
Nous allons maintenant créer des branches locales associées aux branches distantes afin de pouvoir travailler sur nos modules.
1 2 3 4 | git fetch core git fetch webapp git branch localcore --track core/master git branch localwebapp --track webapp/master |
Il est maintenant possible de travailler sur les modules localcore et localwebapp dans leurs branches locales respectives. Le tracking étant défini, les push seront effectués vers les dépôts respectifs des deux modules.
Et l’arborescence globale de notre projet ?
Depuis notre unique dépôt local, nous avons vu comment travailler séparément sur nos différents modules. Mais à ce stade, nous n’avons pas reconstitué l’arborescence de notre projet Maven. C’est à ce stade qu’interviennent les subtrees.
On rebascule dans la branche master de notre projet, et on exécute :
git read-tree --prefix=core/ -u localcore git read-tree --prefix=webapp/ -u localwebapp
Après cette étape, on n’oublie pas de commiter l’ensemble et nous avons récupéré l’arborescence globale de notre projet.
Mettre à jour le projet lorsque les modules évoluent
Notre module core a maintenant évolué dans sa branche. Ces modifications ne sont pas automatiquement reportées dans la branche master de notre projet.
Pour récupérer ces mises à jour, il suffit d’utiliser la commande :
1 | git merge -s subtree localcore |
Cette opération aura pour effet de fusionner dans la branche master les modules (ainsi que leurs historiques respectifs).
On peut juger que ces historiques sont « parasites » à ce niveau : on les a déjà dans la branche du module. On préfèrera dans ce cas la commande :
1 | git merge -s subtree --squash --no-commit localcore |
Cela aura pour effet d’agréger tous les commits en un seul et de préparer le message de commit (qui concatène les messages de tous les commits agrégés). Il ne reste plus qu’à corriger ce message et à valider le commit.
Submodules ou Subtrees ?
Nous avons donc deux méthodes permettant de traiter la même problématique. Il ne reste plus qu’à en choisir une. Les deux approches ont leurs avantages et leurs inconvénients.
Les subtrees sont plus faciles à manipuler : ils nécessitent moins d’opérations, et il est plus difficile de faire une erreur qu’avec les submodules (oubli d’un push par exemple).
Les submodules sont plus complexes à utiliser, mais plus structurés (il s’agit là d’un avis subjectif de ma part) : chaque dépôt distant est associé à un dépôt local.
Personnellement, ce sont les submodules que je préfère.
Partager un projet Talend Open Studio avec git
26/03/11
Récemment, OCTO a publié deux bons billets sur les implémentations de services REST et sur leur testabilité. Je vais donc laisser ce sujet de côté pour le moment et différer le billet que je comptais écrire sur le sujet.
Depuis déjà pas mal de temps, je m’intéresse aux « forges logicielles », en particulier autour de des technologies Java. Dans ce cadre, j’ai testé plusieurs outils de suivi d’anomalies/évolutions : Mantis, JIRA, Redmine, etc.
D’après ce que j’ai pu voir, de nombreux clients utilisent Mantis pour le suivi des anomalies. Dans la forge mise en place en interne, nous utilisons plutôt Redmine (la suite des produits Altassian est également excellente, mais nécessite d’avoir le budget), en particulier pour son excellente intégration avec git :
- possibilité de lier des commits aux fiches Redmine
- pilotage automatique de la résolution et du « time-tracking » des fiches en extrayant automatiquement ces informations des commits git
- visualisation dans l’interface Redmine des diffs
- calcul et affichage de statistiques sur le dépôt du projet
Afin de pouvoir utiliser simultanément ces différents produits (Mantis du client et Redmine ou JIRA interne), j’ai pensé créer un projet Open Source permettant de synchroniser les données entre ces différents produits, en utilisant Talend Open Studio. Pour cela, il fallait donc réussir à partager ce projet en utilisant git (afin de le rendre accessible sur GitHub).
Gérer un projet Maven multi-modules avec Git
4/03/11
J’ai récemment assisté à l’atelier Git avancé de Christophe Porteneuve. Au programme, de nombreuses choses intéressantes, dont les submodules Git, La partie de la formation les concernant m’intéressait particulièrement pour une problématique que je rencontre très fréquemment : travailler avec un projet Maven multi-modules.
Il y a bien sûr la solution qui consiste à utiliser un unique dépôt Git à la racine du projet. Ca fonctionne bien, mais pour des gros projets, je préfère avoir un dépôt dédié à chacun des modules Maven. Cela ne poserait aucun problème, s’il n’y avait une arborescence de répertoires entre le projet principal, et ses modules.
Voyons donc avec un exemple comment mettre en place une gestion de configuration séparée pour chacun des modules d’un projet Maven.
La suite >
Au revoir SVN… Bonjour Git !
7/12/10
Commençons par un résumé des épisodes précédents :
- Tout a commencé avec la découverte de Git.
- Après un premier test concluant, c’est à l’atelier de rentrée de Git-Attitude que j’ai vraiment appris à utiliser Git et eu « l’effet Whaou » !
- Convaincu par l’intérêt des DCVS, j’ai commencé à travailler avec Git comme frontal de Subversion : voir ici et là.
- Après avoir joué avec Git, « Git + SVN » laisse un sérieux arrière-goût d’inachevé. Nous avons donc cherché et trouvé une solution pour coupler Git au SI, de la même manière que SVN avant lui.
La solution ayant été trouvée, il ne reste plus qu’à effectuer la migration définitive de SVN vers Git, en conservant l’historique du projet.
La suite >
Git et LDAP en entreprise
19/11/10
Le gain apporté par les gestionnaires de configuration distribués n’est plus à démontrer. Dans ce domaine, les projets libres montrent la voie, et en utilisent presque tous un, que ce soit Git, Mercurial, etc.
Cela fait maintenant quelques temps que je teste Git, y compris au travail en interface avec SVN, notre gestionnaire de configuration d’entreprise.
Pour aller plus loin dans cette utilisation, il fallait envisager de remplacer (ou de doubler) le serveur SVN central par un repository Git central (« bare repository« ). La contrainte imposée par mon administrateur système préféré étant d’avoir le même système de gestion des droits d’accès, centralisé sur notre serveur LDAP (où chaque projet est associé à un groupe d’utilisateurs).
Voici différentes pistes que nous avons envisagées pour ce faire :
La suite >
Allons un peu plus loin avec Git-SVN
12/10/10
Il y a très peu de temps, j’expliquais comment utiliser Git avec SVN dans Eclipse. C’est maintenant quelque chose que j’utilise au quotidien, que ce soit avec Eclipse ou IntelliJ IDEA, mon nouveau choucou. Dans un cas comme dans l’autre, on ne coupera pas à l’utilisation des « external tools » pour la configuration des commandes « git svn rebase/dcommit/etc. »
Après plusieurs semaines d’utilisation, j’ai voulu étendre cette utilisation à d’autres commandes, afin de voir si on pouvait pousser plus loin les interactions entre Git et SVN.
La suite >
Découverte de IntelliJ IDEA
4/10/10
Je pourrais titrer ce billet « Confessions d’un éclipsien repenti », mais on m’accuserai de mauvais plagiat… et malgré la très bonne impression que m’a faite IntelliJ IDEA, j’apprécie toujours également mon fidèle Eclipse.
Mais revenons un tout petit peu en arrière… Depuis plus d’un an, j’entends parler de cet IDE : blogs, un récent comparatif, le Paris JUG, etc. J’avais donc décidé d’y regarder de plus près, mais sans jamais vraiment prendre le temps de m’y mettre. J’en ai eu récemment l’occasion, en testant le Play! Framework. Celui-ci dispose en effet d’une commande « idealize » permettant de générer le projet au format IDEA, qui n’a pas d’équivalent pour Eclipse. J’ai donc décidé de faire d’une pierre deux coups et de tester Play! en même temps qu’IntelliJ IDEA.
J’ai rapidement beaucoup apprécié les fonctionnalités de l’IDE, et j’ai donc étendu mon test à un projet Java/J2EE. Voici pas à pas le déroulement de ma découverte de l’IDE, pour les retardataires qui, comme moi, n’avaient pas encore franchi le pas…
La suite >
Session de rentrée Git-Attitude
20/09/10
Il est temps de faire un petit retour sur ce samedi, passé à la session de rentrée Git-Attitude. Ce fût une excellente journée, très dynamique et instructive. Cette formation intensive m’a permis de progresser bien plus vite que par une auto-formation… et pour un prix dérisoire, petit-déjeuner et déjeuner compris : nous avons donc eu le Git et le couvert (oui, elle était facile, mais je n’ai pas pu résister !).
Présentation des acteurs
Nous nous sommes retrouvés à 9 participants (dont Rik, Gabriel, Rudy, Bob, etc.) dans les locaux parisiens de Clever Age, plus notre formateur. Par un mystérieux hazard, j’ai découvert aujourd’hui que nous travaillons à quelques centaines de mètres, les locaux de Ciblo étant situés boulevard Bessières.
Premier point positif et remarquable : nous étions environ moitié MAC, moitié Linux (l’utilisation de Git étant, il est vrai, beaucoup plus pénible surWindows…). Le deuxième suit aussitôt : nous avions tous une connexion internet sans restrictions. Ca met de bonne humeur pour commencer la journée. Note :Le café et les viennoiseries du matin étant bien entamées, nous pouvons entamer la journée en douceur…
Les bases
Nous commençons par vérifier notre installation de Git (et sa customisation), et nous sur une présentation générale :
- Petit historique rapide des gestionnaires de configuration
- Comparaison de l’approche centralisée avec l’approche décentralisée, et des différents acteurs de chaque catégorie
- Immédiatement après (évangitlisation oblige), les avantages du décentralisé : travail en mode offline, commits plus atomiques, suppression du « single point of failure« , etc.
- Point sur le vocabulaire : commit et checkout sont des opérations locales. Les opérations distantes s’appellent push, pull, fetch.
- Présentation des quatre « zones » de travail sous Git : les « Untracked » (fichiers non encore gérés sous Git) « Working Tree » (espace de travail), « Index » (snapshot des fichiers prêts à être commités), « HEAD » (position du dernier commit)
- Toutes les références (branche, tag, etc.) sont des hachages SHA
Premiers travaux pratiques
- Création d’un premier dépôt, ajout d’un fichier à l’index (add), commit… Nous voyons tout de suite une première possibilité de Git, l’amendement (–amend) un commit (en cas d’oubli de fichier dans un commit)
- Nous voyons aussi quelques commandes de suivi : diff, status et log : ces quelques méthodes sont déjà impressionantes par le nombre de possibilités (différence entre l’espace de travail et l’index, entre l’index et le HEAD, entre l’espace de travail et le HEAD, etc.)
- Premier « Whaou » du jour : l’ajout interactif (add -i) : on peut mettre dans l’index des portions de fichier, et garder le reste des modifications pour un commit ultérieur.
- Encore plus fort, le retour en arrière en cas d’erreur avec Dick Rivers git reset.
Cette fonction reset est impressionnante. Si nous avons oublié de créer une branche depuis 2 commits, elle permet de corriger ça en 3 commandes :
1 2 3 | git branch ma_nouvelle_branche git reset --hard HEAD~2 # master revient deux commits en arrière git checkout ma_nouvelle_branche # Ni vu ni connu |
Après cette entrée en matière plutôt efficace, nous allons déjeuner, et discuter de choses et d’autres… mais en particulier du Paris Web.
Les branches
De retour, nous abordons un sujet assez inconnu sous Subversion (tant il est difficile de faire des fusions) : les branches. Sous, Git une branche n’est qu’une référence vers l’arbre d’origine (un SHA). C’est-à-dire quelques octets et quelques milli-secondes.
Une fois ces branches créées, elles sont aussi faciles à fusionner, avec une résolution automatique de grand nombres de cas. En particulier si des modifications concurrentes sur un fichier concernent des parties différentes, Git les fusionnera. Ca peut paraître simple… mais Subversion en est incapable.
Et comme c’est simple et que ça marche, on peut mettre en place de véritables stratégies et workflows de développement.
En cas d’urgence, on peut changer de branche sans perdre son travail avec la boite à idée « stash« .
Nous abordons ensuite plus en détail les différentes possibilités de fusion :
- résolution d’un conflit (oui, il arrive qu’on ne puisse y échapper…)
- fusion simultanée de plus de 2 branches (trois, dans notre cas) : et ça marche !
Rebase
(Encore) une fonctionnalité impressionnante de Git. « Rebase » permet :
- de modifier le point de départ d’une branche
- de diviser une branche et deux branches distinctes (dans le cas où elle contient deux parties n’ayant finalement pas de rapport)
- de réécrire l’historique en mode interactif (par exemple pour fusionner plusieurs commits successifs en un seul)
Dépôts distants
Travailler en local, c’est bien… mais à un moment, il faut partager son travail. Nous voyons donc comment se connecter à un dépôt distant, et comment interagir avec celui-ci : push, pull, fetch, etc.
Au passage, nous découvrons des nouveautés (simplification de la syntaxe des commandes) de la version 1.7 et effectuons nos travaux pratiques avec des clés SSH et Gitosis.
Une journée bien remplie…
Pour finir, nous voyons la fonction « tag« . La journée se terminera là-dessus : avec tout ça, nous n’aurons finalement pas eu le temps d’aborder les submodules (mais on pourra facilement trouver en ligne des informations sur ces derniers).
Il nous reste à passer un dernier quizz, et à rentrer chez nous méditer tout ça…
Maintenant, si vous êtes en manque d’imagination pour les nombreux commits que vous allez faire sous Git, allez donc lire What the commit…
