Utiliser Git et bitbucket pour écrire un livre en LaTeX (partie 2)

Dans le premier article de cette série, nous avons découvert ce qu’était un système de gestion de versions et en quoi il peut être utile dans le cadre de la rédaction collaborative d’un document en LaTeX.  J’ai expliqué également comment utiliser Bitbucket, ainsi que les concepts de base de Git: projet Git, cloner un dépôt, créer un commit.  Jusqu’à présent, je n’ai pas encore réellement abordé ce qui fait la force de Git dans notre cas d’usage: c’est l’objet de ce deuxième article.

Cette deuxième partie couvrira donc les sujets suivants:

  • affichage de l’historique du projet, et comment revenir à des versions antérieures de certains fichiers.
  • comment identifier avec une étiquette précise certaines versions du projet (par exemple, la version envoyée pour relecture aux autres collègues, la version imprimée en début d’année…)
  • comment travailler sur plusieurs versions du document en même temps (par exemple pour préparer la deuxième édition du livre tout en corrigeant les éventuelles coquilles de la première édition)

Historique

Git conserve toutes les différentes versions de tous les fichiers d’un projet.  Cela permet de retrouver facilement toutes les modifications effectuées.  L’historique complet d’un projet est affichée simplement avec:

git log
git log --oneline
git log --oneline --decorate --graph

La première forme fournit l’historique complet; la seconde forme est plus compacte et n’affiche que le résumé des commits; la dernière forme est plus jolie car elle tente d’afficher un arbre.

Avec SourceTree, La fenêtre principale permet de visualiser l’historique des commits du projet courant.

Historique d'un projet avec SourceTree
Historique d’un projet avec SourceTree

 

Pour afficher l’historique sur un fichier précis, avec le contenu des modifications, il suffit de rajouter l’option –patch:

git log --patch monfichier.tex

Revenir en arrière

Il faut d’abord savoir qu’il est impossible (ou plutôt très difficile et pas recommandé) de supprimer quelque chose qui a déjà été mis dans le système de gestion de version (qui a été committé). Pour « revenir en arrière », on ira récupérer une ancienne version du fichier et l’on committera à nouveau cette version.

Supposons que pour x raison, je souhaite finalement reprendre le fichier math3_includes.tex tel qu’il était dans l’historique au niveau du commit 366799068f1a371d94c6ff01cab1cb5f51929029, c’est-à-dire celui étiquetté « impression_20150901 ».

Revenir à une ancienne version
Revenir à une ancienne version

Dans la fenêtre en bas à gauche, on sélectionne « Loguer la sélection… »

Revenir à une ancienne version (2)
Revenir à une ancienne version (2)

Cela ouvre une nouvelle fenêtre avec l’historique de ce fichier particulier. En cliquant droit sur le bon commit et en sélectionnant Revenir à la dernière validation…, le fichier en question sera remis dans notre copie locale à son état lors du commit sélectionné.

Revenir à une ancienne version (3)
Revenir à une ancienne version (3)

On modifie ensuite le fichier si nécessaire, et on le committe à nouveau.

Avec Git, il suffit de faire :

git checkout 366799068f1a371d94c6ff01cab1cb5f51929029 math3_includes.tex

À noter qu’en général, on peut se contenter des six premiers caractères :

git checkout 366799 math3_includes.tex

À ce moment là, mon fichier math3_includes.tex est remplacé par sa version du commit 366799. Je peux dès lors enregistrer dans l’historique le retour à cette version :

git add  math3_includes.tex
git commit -m "en fait, je ne voulais pas de titre : revenons à l'état 366799068f1a371d94c6ff01cab1cb5f51929029 pour le fichier math3_includes.tex"

En revanche, supposons que je ne voulais que consulter l’état du fichier au commit 366799068f1a371d94c6ff01cab1cb5f51929029, mais ne souhaitais pas y revenir. J’ai effectué ma consultation, et maintenant j’aimerais retrouver la version la plus à jour.

La solution est simple:

git checkout master

Il faut bien comprendre ce que fait la commande git checkout. Git va rechercher dans l’historique du projet le commit demandé et va modifier localement tous les fichiers du projet pour les mettre dans l’état qu’ils ont dans le commit demandé. La commande checkout modifie donc les fichiers locaux!

 

Marquer les étapes: la notion de tag

Plutôt que de retenir une étiquette de commit imprononçable, il peut être utile de pouvoir se référer à un commit particulier avec un nom plus « gentil ». Poser un tag sur un commit revient à mettre une étiquette particulière sur un commit.

Pour rajouter un tag avec SourceTree, il faut cliquer sur le bouton « Tag ». Dans la fenêtre suivante, il faut indiquer le nom du tag, ici impression_20150915.

Ajouter un tag
Ajouter un tag

Si on sélectionne « Parent de la copie de travail », le tag sera placé sur le commit actuel de notre copie locale. Si on sélectionne « Soummission spécifiée », il est possible de choisir un commit spécifique dans l’historique sur lequel placer le tag.

Pour que le tag soit envoyé directement vers le dépôt distant sur Bitbucket, il faut également cocher la case « Envoyer le tag: origin », comme dans l’écran ci-dessous.

Pousser le tag vers Bitbucket
Pousser le tag vers Bitbucket

Avec git en ligne de commande, ajouter un tag est très simple:

git tag "mon_tag"
git push origin "mon_tag"

Cela ajoutera un tag sur le commit actuel de notre copie locale. La deuxième commande envoie le tag vers Bitbucket.

Les branches: travailler sur plusieurs versions en parallèle

Les branches permettent de travailler sur plusieurs versions du document en parallèle.

Par exemple, cela peut être utilise lors de l’ajout d’un nouveau chapitre: le chapitre est en cours de rédaction et ne compile pas ou n’est pas assez complet que pour pouvoir être intégré dans le document final.  Par contre, il est utile de l’inclure déjà dans le projet afin que tous les collaborateurs puissent le relire.  Dans ce cas, une branche sera créée pour contenir les modifications nécessaires pour ce nouveau chapitre. Une fois ce chapitre dans un état suffisamment mature, cette branche sera fusionnée avec la branche de base du projet.

De manière générale, tout nouvel ajout conséquent au projet sera d’abord réalisé sur une branche. Une fois la modification terminée, la branche sera fusionnée (merge) avec le tronc commun.

Voici la marche à suivre pour travailler avec les branches:

  1. Créer une branche pour un nouveau chapitre: git checkout -b chapitre5. Ou avec SourceTree:
Créer une branche
Créer une branche

 

  1. Travailler dans cette branche comme décrit plus haut:
    1. git add chapitre5_equations_contenu.tex
    2. git commit
    3. On continue à modifier les fichiers, avec plusieurs commits éventuels.
  2. A la fin de notre édition de cette branche, quand on considère que le travail est suffisamment abouti que pour pouvoir être intégré dans le projet global, on doit fusionner cette branche sur le tronc commun. git checkout master pour se positionner sur le tronc commun suivi de git merge --no-ff chapitre5. Enfin un git push envoie ces modifications vers Bitbucket.

Avec SourceTree, l’étape 3 se réalise simplement en se positionnant d’abord sur le tronc commun master (double click sur master), puis en cliquant sur le bouton fusionner. Ensuite:

Fusionner une branche avec master
Fusionner une branche avec master

Dans cet écran, on clique sur la branche à fusionner (ici « branche_test »), on coche bien l’option « Créer une nouvelle soumission même si fast-forward est possible », et on valide. Enfin, on envoie le tout vers Bitbucket en cliquant sur le bouton « Envoyer ».

Fusionner une branche (2)
Fusionner une branche (2)

Dans l’écran ci-dessus, on voit bien le résultat de la fusion. Il reste encore à pousser les modifications vers Bitbucket: le bouton « Envoyer » indique qu’il y a bien deux changements à envoyer.

Avec Git, la fusion doit se faire avec le flag --no-ff pour conserver l’historique lisible.

Méthode de travail à plusieurs: quelques conseils

  • La branche principale du projet – la branche master, ou tronc commun – doit toujours être stable, ce qui signifie que sa compilation avec LaTeX doit toujours fournir un résultat correct et « abouti ». La branche master compile toujours correctement.
  • Cela a comme conséquence que toute modification ou nouvelle partie se commence dans une nouvelle branche. Cela permet de garder master stable pendant que le nouveau chapitre ou la modification est en cours d’élaboration sur sa branche propre.
  • Quand une modification ou nouvelle partie est finalisée, on la fusionne dans la branche master (avec l’option --no-ff pour conserver un historique lisible).
  • Pour tout événement marquant du projet (publication, impression PDF…), tagguer le commit correspondant de la branche master avec un tag explicite.
  • La première ligne du message de commit doit résumer clairement le contenu des modifications. Laisser ensuite une ligne vide, puis détailler éventuellement les modifications.

Sans oublier les règles à suivre pour LaTeX:

  • pas d’espace ni d’accent dans les noms de fichier et répertoire.
  • pas de majuscule dans les noms de fichiers. En effet, Windows ne fait pas la différence entre monfichier.tex et MonFichier.TEX, alors que pour macOS et Linux, ce sont deux fichiers différents… Bonjour la confusion…

Conclusion

Avec cette introduction en tête, il devrait être possible de rédiger son premier document LaTeX sous le contrôle de Git via Bitbucket. En tout cas, cela a été utilisé avec succès par une équipe de quatre professeurs de mathématiques pour la rédaction d’un nouveau support de cours, sans aucune connaissance préalable de Git ou Bitbucket.

Si vous avez des retours d’expérience à partager, je suis intéressé 🙂

Références

Sources

  1. Garder un historique de son travail grâce à Git
  2. Un workflow Git efficace pour les projets à moyen/long terme

Documentation additionnelle

  1. Pro Git – la bible Git en français
  2. Tutoriel SourceTree officiel (en anglais)
  3. Tutoriel Git sur Bitbucket (en anglais)

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *