mardi 20 novembre 2012

Utiliser Git pour patcher un projet open-source sous svn

J’ai commencé il y a quelques mois à modifier pour mon usage personnel un logiciel open-source. Son code étant hébergé dans une base Subversion (svn) sur SourceForge, j’avais tout simplement fait un « svn checkout » du projet et commencé à taper dans le code pour faire mes modifications.

Et puis un jour j’ai voulu soumettre un patch aux développeurs. Problème : si je fais un « svn diff », j’obtiens tous mes changements en vrac. Comment faire ? Éditer le diff à la main n’est pas très pratique et source d’erreurs. Faire un deuxième checkout et y copier-coller à la main ce que je veux intégrer au patch est fastidieux.

J’ai donc décidé d’utiliser Git et sa supériorité écrasante (si si, il parait) dans la gestion des branches pour créer mes futurs patchs. L’idée est de créer une nouvelle branche pour chaque patch. Ensuite un simple diff entre deux branches permet de générer le patch souhaité.


La méthode pas à pas


Voici comment ça marche :


1) Récupérer le projet


git svn clone https://…

Ça peut prendre très longtemps car ça récupère tout l’historique du projet. Dans mon cas, ça a pris dans les 2 heures pour environ 5500 révisions svn.

Cette opération crée automatiquement une branche nommée « master » dans laquelle on ne fera jamais de commit. Ça sera la branche de référence permettant de générer les patchs.


2) Créer une branche dédiée à notre premier patch


git checkout -b my-great-patch master

3) Coder le patch… et faire autant de commits que l’on souhaite


- pour voir les fichiers modifiés :

git status

- pour vérifier ce qu’on a changé avant de commiter :

git diff

- pour commiter :

git commit -a -m "Description du commit."

4) Générer le patch


git diff master >my-great-patch.diff

5) L’envoyer aux développeurs



6) Supprimer la branche


Si le patch est intégré au code source officiel du projet, vous pouvez alors supprimer la branche :

git checkout master
git branch -d my-great-patch


La méthode est au final assez simple et je peux confirmer que les développeurs n’ont aucun souci avec les patchs créés par git ;-).


Autres commandes


Il y a tout de même quelques autres commandes à connaitre :

- Récupérer la dernière version du code source officiel


D’abord mettre à jour la branche master :

git checkout master
git svn rebase

Puis mettre à jour la branche sur laquelle vous travaillez :

git checkout my-great-patch
git rebase master

Il peut arriver qu’il y ait des conflits à cette étape, mais je n’ai pas d’instructions détaillées à proposer dans ce cas de figure. Git indique lui-même les commandes à taper pour annuler ou continuer la mise à jour.

- Voir les branches existantes et savoir sur laquelle on se trouve


git branch

- Passer d’une branche à une autre


git checkout my-other-great-patch

Notez que si vous avez compilé la branche my-great-patch avant de passer à la branche my-other-great-patch, il faudra probablement faire un « make clean » pour effacer tous les fichiers générés du projet avant de le recompiler (utilisez ccache pour gagner du temps !).

Notez également qu’une pression sur TAB complete tout seul les noms de branche git (sous zsh / Arch Linux). Très pratique :-). Il est également possible de configurer son prompt pour qu’il affiche le nom de la branche courante (je vous laisse chercher comment ; je ne l’ai pas fait).

- Voir le log des révisions svn


git svn log

(C’est totalement indépendant de la branche git courante.)

- Voir le log des commits de la branche courante


git log


Combiner tous les patchs


Si en attendant que vos patchs soient acceptés vous voulez les utiliser en local, il peut être intéressant de créer une branche combinant toutes les autres… À priori le plus simple est d’utiliser « git merge » :

git checkout -b all-my-patches master
git merge my-great-patch
git merge my-other-great-patch


Voilà pour cette fois. Have fun ;-).

Aucun commentaire:

Enregistrer un commentaire