Travailler avec Git et Perforce : workflow d'intégration
Voici donc le scénario : votre équipe travaille indépendamment sur un dépôt Git, mais une partie de l'organisation utilise toujours Perforce pour gérer des parties de la même base de code. Ces équipes sur Perforce ne prévoient pas de migrer, mais votre équipe est déjà passée à Git (pour de nombreuses raisons). Il est important que vous puissiez maintenir un processus de partage du code bidirectionnel entre les bases de code afin que les améliorations développées dans les deux versions puissent être partagées, en espérant que cela ne vous fasse pas trop perdre de temps ou que votre équipe ne soit pas trop gênée.
C'est ici que ce guide entre en jeu. Chez TomTom, cette opération de synchronisation est effectuée à chaque nouvelle version, ce qui, dans leur cas, se produit une fois tous les mois et demi.
— Ce billet a été rédigé en collaboration avec Andrea Carlevato, Adolfo Bulfoni et Krzysztof Karczewski qui ont eu la gentillesse de partager le processus Git utilisé par l'unité NavApps de TomTom. —
Hypothèses avant de commencer
Nous partons du principe que vous connaissez déjà l'utilisation de base de Git et que vous êtes familier avec le workflow de branche de fonctionnalité. Si ce n'est pas le cas, prenez le temps de visionner un tutoriel pratique ou un webinaire, et revenez quand vous serez prêt. Nous vous attendrons.
Il existe quelques subtilités à garder à l'esprit dans le processus. Nous vous suggérons donc d'être très prudent lorsque vous effectuez ces intégrations. Nous pouvons commencer dès que vous serez prêt !
Installation de git p4
La première étape consiste à installer le pont. Vous pouvez vérifier qu'il est déjà installé en saisissant cette commande sur une ligne de commande :
git p4
Si le système vous signale que git p4
n'est pas installé, téléchargez git-p4.py et placez-le dans un dossier de votre PATH
, par exemple ~/bin
(évidemment, Python doit également être installé pour que cela fonctionne).
Rendez-le exécutable avec :
chmod +x git-p4.py
Modifiez le fichier ~/.gitconfig
en ajoutant :
[alias]
p4 = !~/bin/bit-p4.py
Puis, exécutez à nouveau git p4
. Vous ne devriez pas avoir d'erreur. L'outil est installé.
Ressource connexe
Comment déplacer un dépôt Git complet
DÉCOUVRIR LA SOLUTION
Découvrir Git avec Bitbucket Cloud
Aperçu du workflow
Clonage initial
Étant donné que les projets dans P4
peuvent générer d'énormes historiques, l'équipe peut choisir un point de coupure à partir duquel se synchroniser. Cela permet de gagner beaucoup d'espace et de temps. git p4
vous permet de choisir la liste des changements à partir de laquelle démarrer le suivi :
git p4 clone //depot/path/project@<earlier-cutoff-point>,<latest-changelist>
- Nous pouvons maintenant exécuter une synchronisation et vérifier que nous avons reçu tous les ensembles de changements localement :
git p4 sync
La commande sync
trouve les nouveaux changements dans P4
et les importe en tant que commits Git.
- Nous nommons
p4-integ
la branche que nous utiliserons pour interfacer directement avec Perforce. À ce stade, nous voulons simplement créer une branche à partir deremotes/p4/main
:
git checkout -b p4-integ origin/p4/main
Synchronisation rapide de suivi (ou synchronisation « en deux temps »)
Une fois la première importation terminée, les synchronisations git-> p4
suivantes peuvent être effectuées avec les commandes suivantes :
git checkout p4-integ
git p4 sync
Le code ci-dessus fonctionne, mais il peut être lent. Un moyen beaucoup plus rapide d'exécuter la synchronisation consiste à recréer des références (refs
) identiques à celles utilisées dans la dernière intégration. C'est également un bon moyen de s'assurer que tout nouveau développeur chargé de l'intégration commence au niveau du bon commit ou de la bonne liste de changements.
Voici comment procéder :
- Supprimez les anciennes
refs
d'origine (ou caduques) pour le remotep4
(en option) :
git symbolic-ref -d refs/remotes/p4/HEAD
git update-ref -d refs/remotes/p4/main
- Créez des refs remote artificielles (ou fausses) qui pointent vers le dernier commit sur
p4-integ
dansorigin
:
git update-ref refs/remotes/p4/main remotes/origin/p4-integ
git symbolic-ref refs/remotes/p4/HEAD refs/remotes/p4/main
Le seul inconvénient de cette synchronisation beaucoup plus rapide est que nous devons spécifier explicitement la branche dans git p4
. Voici donc la commande finale :
git p4 sync --branch=refs/remotes/p4/main
La façon dont git p4
suit le mappage entre les identifiants de commit Git et ceux de P4 consiste à annoter les commits avec des métadonnées :
Merge pull request #340 in MOB/project from bugfix/PRJ-3185 to develop
Squashed commit of the following:
commit c2843b424fb3f5be1ba64be51363db63621162b4
Author: Some Developer
Date: Wed Jan 14 09:26:45 2015 +0100
[PRJ-3185] The app shows ...
commit abc135fc1fccf74dac8882d70b1ddd8a4750f078
Author: Some Developer
Date: Tue Jan 13 14:18:46 2015 +0100
[PRJ-3185] The app shows the rating ...
[git-p4: depot-paths = "//depot-mobile/project/": change = 1794239]
Notez que dans une version plus récente de git p4
, les métadonnées permettant d'associer un commit Git à une liste de changements P4
sont stockées dans une note de commit et non dans le message de commit. L'équipe de TomTom n'a pas apprécié ce changement, car il compliquait un peu la vérification des numéros de la liste des changements lorsque cela était nécessaire.
Déplacement des changements de Git vers Perforce
Une fois l'opération de synchronisation rapide ci-dessus terminée, vous êtes maintenant prêt à pusher les changements de git
vers Perforce.
La première étape consiste à exécuter un rebase de p4-integ
avec les changements provenant de remotes/p4/main
:
git checkout p4-integ
git p4 rebase
Après cela, tous les nouveaux changements de Perforce devraient être sur p4-integ
, afin que nous puissions mettre à jour main
:
- Après cela, vous pouvez simplement utiliser cette commande :
git checkout main
git merge develop
- Assurez-vous d'avoir les derniers tags en local :
git fetch --tags
- Utilisez un
cleanup
temporaire au cas où vous auriez besoin de supprimer des commits déjà dansP4
(voir le tagP4
dans le commit). Dans le cas où aucun commit ne doit être ignoré, un rebase automatique qui linéarisera l'historique :
git checkout -b cleanup #branching off from main
git rebase -s recursive -X theirs tag/last-p4-integ
- Grâce à un rebase interactif, vous pouvez le faire à la place avec :
git rebase -i tag/last-p4-integ
- Utilisez
cherry-pick
pour sélectionner les nouveaux commits et les placer sur la branchep4-integ
. Nous le faisons de cette manière, car nous ne supposons pas que les branchesgit
main
etdevelop
puissent être conservées en tant que véritables ancêtres de la branchep4-integ
. En fait, ce n'est plus le cas chez TomTom.
git checkout p4-integ
git cherry-pick tag/last-p4-integ..cleanup
- Envoyez à
P4
et synchronisezp4-integ
:
git p4 submit
git p4 sync --branch=refs/remotes/p4/main
git reset --hard refs/remotes/p4/main
- Supprimez la branche de rebase temporaire :
git branch -D cleanup
- Supprimez le pointeur vers le dernier point d'intégration (tag) en local et sur le remote :
git tag -d tag/last-p4-integ
git push origin :refs/tags/tag/last-p4-integ
- Mettez à jour le tag
last-p4-integ
pour qu'elle pointe vers le nouveau point d'intégration dansP4
:
git checkout develop
git tag -a tag/last-p4-integ -m "tag pointer to last develop commit integrated with p4"
git push origin main
git push origin tag/last-p4-integ
git push origin p4-integ
Exécutez des tests sur la base de code P4
pour vérifier que l'intégration n'a pas introduit de problèmes.
Déplacement des changements de Perforce vers Git
Cela doit être fait une fois que le push git-> P4
a déjà été fait. Une fois les tests réussis sur P4
, nous pouvons maintenant déplacer les changements de P4
vers git
avec le code ci-dessous :
git checkout p4-integ
git p4 sync --branch=refs/remotes/p4/main
git p4 rebase
- Le code ci-dessous est une petite astuce pour effectuer une stratégie de merge « theirs » (à eux) robuste, réduisant les changements entrants à un seul commit :
git checkout -b p4mergebranch #branching off from p4-integ
git merge -s ours main ## ignoring all changes from main
git checkout main
git merge p4mergebranch --squash
git commit -m "Type your integration message"
git branch -D p4mergebranch
- Une fois que nous avons terminé avec ce qui précède, mergez les changements apportés à
develop
:
<p>Bitbucket has the following space stations:</p>
<p>
<b>Earth's Moon</b><br>
Headquarters
</p>
Étant donné que des changements ont pu avoir lieu depuis que nous avons récupéré les changements de develop
, il peut être nécessaire de les merger en premier. Il est important, cependant, de mettre à jour le tag last-p4-integ
vers le bon commit, et surtout pas le commit de merge vers develop. Pour le faire en toute sécurité, il est préférable de taguer l'état actuel de main
:
- Supprimez l'ancien tag en local et sur le remote :
git tag -d tag/last-p4-integ
git push origin :refs/tags/tag/last-p4-integ
- Créez un tag à la nouvelle position :
git checkout main
git tag -a tag/last-p4-integ -m "tag pointer to last develop commit integrated with p4"
- Pushez maintenant
main, develop, p4-integ
ettag/last-p4-integ
versorigin
:
Conclusions
C'est ainsi que vous synchronisez deux équipes de développement actives à l'aide de Git et Perforce. Le processus ci-dessus a évolué au fil du temps chez TomTom, et il est maintenant opérationnel depuis un certain temps sans problèmes majeurs. Cela fonctionne, mais cela implique des frais généraux assez importants pour la maintenance. Si vous en avez la possibilité, nous vous recommandons de migrer complètement vers Git.
Dans tous les cas, si vous suivez une approche différente pour maintenir une synchronisation bidirectionnelle, je serais très curieux de la lire dans les commentaires ci-dessous. Ou bien, envoyez un tweet à @durdn ou à @atlassiandev.
Merci encore à Andrea Carlevato, Adolfo Bulfoni et Krzysztof Karczewski.
Partager cet article
Thème suivant
Lectures recommandées
Ajoutez ces ressources à vos favoris pour en savoir plus sur les types d'équipes DevOps, ou pour les mises à jour continues de DevOps chez Atlassian.