Cette période de l'année s'achève, celle où des tas de candidats envoient des dossiers de candidature dans les facs de France et de Navarre dans l'espoir de pouvoir accéder à une audition qui, peut-être, leur permettra de décrocher le poste convoité. Ça fait beaucoup de "si", j'y reviendrai dans un prochain article. Ici il est question d'utiliser un système de gestion de version pour pouvoir stocker et manipuler plus facilement son dossier de candidature.


Dans un premier temps, qui dit gestion de version dit format texte. Je suppose que Word donne la possibilité de gérer les versions d'un document, mais j'ai quelques doutes sur les possibilités de "branchement" et de scriptage qui seront listées ci-après. Ensuite on a envie de bouger un peu partout avec sa machine et donc on n'a pas toujours accès à un serveur central de versionnement. Donc exit Subversion, par exemple. Les manips que je décrirai ci-après se basent sur un dossier écrit en LaTeX et utilisent Git, mais ça doit se transposer assez facilement dans tout format texte avec Darcs, Mercurial, Bazaar, etc.

Si on a 42 dossiers à envoyer, il y a des chances qu'ils partagent une assez grosse base commune (le CV par exemple, la description de la thèse, etc). Les parties qui peuvent changer sont l'intitulé du poste, des descriptions de travaux plus orientées vers le poste en question, des perspectives de recherche plus pertinentes par rapport à l'équipe de recherche d'accueil, bref, des points précis ici et là. Il serait donc naturel que ces 42 dossiers partagent une base commune et ne se différencient que par les points précisés plus tôt. De plus, certains postes sont situés dans la même université, ce qui fait que le descriptif de perspectives peut être commun, par exemple. Nous allons donc utiliser l'exemple suivant:


 commun
   \\
    \\--- Poste2009-Paris --- Poste2009-Paris-001
     \\         \\
      \\         \\--- Poste2009-Paris-002
       \\
        \\--- Poste2009-Lille --- Poste2009-Lille-003
                   \\
                    \\--- Poste2009-Lille-004

Nous supposerons pour l'exemple qu'il n'y a qu'un seul laboratoire d'accueil à Paris et à Lille. Donc les postes de Paris ont en commun les perspectives de recherche qui peuvent intéresser le labo de Paris (de même pour Lille) et tous les postes ont en commun un socle global (le CV, les publications, etc).

Les années précédentes j'avais utilisé une façon un peu plus rustique de faire qui identifiait bien les parties différentes dans des fichiers à part, et ces fichiers étaient liés symboliquement pour générer le document complet. Soit par exemple l'organisation suivante:


  dossier.tex -> cv.tex
             \\-> recherche.tex

J'avais (très schématiquement) un sous-répertoire postes/ avec recherche-001.tex, recherche-002.tex, etc et je liais symboliquement recherche.tex vers l'un de ces fichiers selon le dossier que je voulais générer en pdf. Comme je disais, un peu rustique (et c'était un peu plus compliqué que ça) mais ça marchait. Le problème de cette organisation, c'est que pour peu que les scripts soient un peu mal faits, un lien peut être oublié et on peut par accident mettre un descriptif de recherche autre que celui voulu pour le poste visé. Il est donc plus élégant de voir le dossier dans sa globalité et qu'à chaque dossier corresponde un contexte différent. C'est là que Git entre en jeu.

Si vous reprenez le schéma des postes plus haut, vous avez en fait l'organisation des branches de Git: Poste2009-Paris est une dérivation de la branche principale où j'ai ajouté un descriptif de recherche orienté pour Paris (de même pour Lille). Poste2009-Paris-001 est une dérivation de Poste2009-Paris où seul l'intitulé du poste dans le dossier change (par exemple). "commun" sera en fait le tronc principal (la branche "master" de Git).

La création de cette organisation sera donc:


git checkout -b Poste2009-Paris master
git checkout -b Poste2009-Lille master
git checkout -b Poste2009-Paris-001 Poste2009-Paris
...

Vous voyez l'idée.

Maintenant, supposons que j'ai une nouvelle publication à valoriser, je vais la mettre dans la description commune (la branche "master"). Ensuite je vais fusionner ces changements vers les postes de chaque université -- exemple:


git checkout master
[ajout de publis]
git commit -a
git checkout Poste2009-Paris && git merge master

puis pour chaque poste:


git checkout Poste2009-Paris-001 && git merge Poste2009-Paris

Si on veut changer des choses dans les perspectives de recherche d'un labo particulier, on se placera dans la branche commune aux postes du labo, on fera ses amendements et on répercutera les changements dans les branches de postes. Par exemple:


git checkout Poste2009-Paris
[modifications, pour dire qu'on est beaucoup dans les thèmes du labo, tout ça]
git commit -a
git checkout Poste2009-Paris-001 && git merge Poste2009-Paris
git checkout Poste2009-Paris-002 && git merge Poste2009-Paris

Voilà, les changements pour Paris sont reflétés. Si nous reprenons les choses plus diagrammatiquement:



 master
   \\
    \\--- Poste2009-Paris --- Poste2009-Paris-001
     \\         \\
      \\         \\--- Poste2009-Paris-002
       \\
        \\--- Poste2009-Lille --- Poste2009-Lille-003
                   \\
                    \\--- Poste2009-Lille-004

git checkout master
[ajout de publis (+p)]
git commit -a


 master(+p)
   \\
    \\--- Poste2009-Paris --- Poste2009-Paris-001
     \\         \\
      \\         \\--- Poste2009-Paris-002
       \\
        \\--- Poste2009-Lille --- Poste2009-Lille-003
                   \\
                    \\--- Poste2009-Lille-004

git checkout Poste2009-Paris && git merge master
git checkout Poste2009-Lille && git merge master

 master(+p)
   \\
    \\--- Poste2009-Paris(+p) --- Poste2009-Paris-001
     \\         \\
      \\         \\--- Poste2009-Paris-002
       \\
        \\--- Poste2009-Lille(+p) --- Poste2009-Lille-003
                   \\
                    \\--- Poste2009-Lille-004


git checkout Poste2009-Paris-001 && git merge Poste2009-Paris
git checkout Poste2009-Paris-002 && git merge Poste2009-Paris
git checkout Poste2009-Lille-003 && git merge Poste2009-Lille
git checkout Poste2009-Lille-004 && git merge Poste2009-Lille


 master(+p)
   \\
    \\--- Poste2009-Paris(+p) --- Poste2009-Paris-001(+p)
     \\         \\
      \\         \\--- Poste2009-Paris-002(+p)
       \\
        \\--- Poste2009-Lille(+p) --- Poste2009-Lille-003(+p)
                   \\
                    \\--- Poste2009-Lille-004(+p)


git checkout Poste2009-Paris
[modifications, tout ça... (+l)]
git commit -a

 master(+p)
   \\
    \\--- Poste2009-Paris(+p+l) --- Poste2009-Paris-001(+p)
     \\         \\
      \\         \\--- Poste2009-Paris-002(+p)
       \\
        \\--- Poste2009-Lille(+p) --- Poste2009-Lille-003(+p)
                   \\
                    \\--- Poste2009-Lille-004(+p)


git checkout Poste2009-Paris-001 && git merge Poste2009-Paris
git checkout Poste2009-Paris-002 && git merge Poste2009-Paris


 master(+p)
   \\
    \\--- Poste2009-Paris(+p+l) --- Poste2009-Paris-001(+p+l)
     \\         \\
      \\         \\--- Poste2009-Paris-002(+p+l)
       \\
        \\--- Poste2009-Lille(+p) --- Poste2009-Lille-003(+p)
                   \\
                    \\--- Poste2009-Lille-004(+p)

C'est assez régulier, donc cette procédure est facile à scripter, d'où l'importance de nommer de manière cohérente les différentes branches. Un inconvénient qui n'apparaît pas dans le processus décrit ci-dessus est l'apparition de conflits (lorsqu'on "merge" des modifications sur des lignes qu'on a modifiées localement). Comme dans mon cas j'avais prévu le coup et "modularisé" les différentes sections de mon document, je n'ai pas eu de cas de conflit. On gardera donc à l'esprit que la validité de cette solution d'organisation n'a pas été testée dans le cas où des conflits peuvent apparaître (et le scriptage dans ce cas est probablement plus délicat).

Lorsqu'on a complété tous les dossiers, générer le dossier final est facile. Si on a un Makefile pour ce faire, alors il suffit de faire un "checkout" sur chaque branche, de générer le dossier puis de le copier ailleurs avec un nom explicite à chaque fois. Par exemple:


for i in `git branch -a | grep '[-][0-9]\\+'`
do
  git checkout "$i"
  make
  mv dossier.pdf ~/other/directory/"$i".pdf
  make purge
done
git checkout master

Le "grep" permet d'identifier les branches qui correspondent aux postes décrits complètement (d'où l'importance d'un nom assez régulier pour les branches des différents postes). Ensuite, une fois les dossiers envoyés on peut marquer dans le temps les versions via un "git tag -a" pour finalement fusionner toutes les branches vers master en gardant uniquement les modifications de master ("git merge -s ours Poste2009-Paris-001"). Une fois cela fait, on peut effacer les branches, l'historique sera conservé quelque part et on pourra regénérer le dossier à l'envi.

La solution Git a donc l'avantage d'exploiter les mécanismes de Git, ce qui est un peu mieux qu'une solution plus primaire à base de liens. On garde également tout l'historique selon des contextes de postes bien séparés (moins de risque de se mélanger les pinceaux) et ça se scripte assez facilement. En espérant que ces quelques recommandations techniques pourront faciliter la vie d'autres candidats (qui savent utiliser Git, Darcs, Mercurial, etc) à l'avenir.