Skip to content

Latest commit

 

History

History
671 lines (552 loc) · 31.6 KB

File metadata and controls

671 lines (552 loc) · 31.6 KB

Git et Perforce

Perforce est un système de version très populaire dans les environnements professionnels. Il existe depuis 1995, ce qui en fait le système le plus ancien abordé dans ce chapitre. Avec cette information en tête, il apparaît construit avec les contraintes de cette époque ; il considère que vous êtes toujours connecté à un serveur central et une seule version est conservée sur le disque dur local. C’est certain, ses fonctionnalités et ses contraintes correspondent à quelques problèmes spécifiques, mais de nombreux projets utilisent Perforce là où Git fonctionnerait réellement mieux.

Il y a deux options pour mélanger l’utilisation de Perforce et de Git. La première que nous traiterons est le pont « Git Fusion » créé par les développeurs de Perforce, qui vous permet d’exposer en lecture-écriture des sous-arbres de votre dépôt Perforce en tant que dépôts Git. La seconde s’appelle git-p4, un pont côté client qui permet d’utiliser Git comme un client Perforce, sans besoin de reconfigurer le serveur Perforce.

Git Fusion

Perforce fournit un produit appelé Git Fusion (disponible sur https://www.perforce.com/git-fusion), qui synchronise un serveur Perforce avec des dépôts Git du côté serveur.

Installation

Pour nos exemples, nous utiliserons la méthode d’installation de Git Fusion la plus facile qui consiste à télécharger une machine virtuelle qui embarque le daemon Perforce et Git Fusion. Vous pouvez obtenir la machine virtuelle depuis https://www.perforce.com/downloads/Perforce/20-User, et une fois téléchargée, importez-la dans votre logiciel favori de virtualisation (nous utiliserons VirtualBox).

Au premier lancement de la machine, il vous sera demandé de personnaliser quelques mots de passe pour trois utilisateurs Linux (root, perforce et git), et de fournir un nom d’instance qui peut être utilisé pour distinguer cette installation des autres sur le même réseau. Quand tout est terminé, vous verrez ceci :

L’écran de démarrage de la machine virtuelle Git Fusion.
Figure 1. L’écran de démarrage de la machine virtuelle Git Fusion.

Prenez note de l’adresse IP qui est indiquée ici, car nous en aurons besoin plus tard. Ensuite, nous allons créer l’utilisateur Perforce. Sélectionnez l’option « Login » en bas de l’écran et appuyez sur Entrée (ou connectez-vous en SSH à la machine), puis identifiez-vous comme root. Ensuite, utilisez ces commandes pour créer un utilisateur :

$ p4 -p localhost:1666 -u super user -f john
$ p4 -p localhost:1666 -u john passwd
$ exit

La première commande va ouvrir un éditeur VI pour personnaliser l’utilisateur, mais vous pouvez accepter les valeurs par défaut en tapant :wq et en appuyant sur Entrée. La seconde vous demandera d’entrer le mot de passe deux fois. C’est tout ce qu’il faut faire depuis une invite de commande, et on peut quitter la session.

L’action suivante consiste à indiquer à Git de ne pas vérifier les certificats SSL. L’image Git Fusion contient un certificat, mais celui-ci ne correspond pas au domaine de l’adresse IP de votre machine virtuelle, donc Git va rejeter la connexion HTTPS. Pour une installation permanente, consultez le manuel Perforce Git Fusion pour installer un certificat différent ; pour l’objet de notre exemple, ceci suffira :

$ export GIT_SSL_NO_VERIFY=true

Maintenant, nous pouvons tester que tout fonctionne correctement.

$ git clone https://10.0.1.254/Talkhouse
Cloning into 'Talkhouse'...
Username for 'https://10.0.1.254': john
Password for 'https://john@10.0.1.254':
remote: Counting objects: 630, done.
remote: Compressing objects: 100% (581/581), done.
remote: Total 630 (delta 172), reused 0 (delta 0)
Receiving objects: 100% (630/630), 1.22 MiB | 0 bytes/s, done.
Resolving deltas: 100% (172/172), done.
Checking connectivity... done.

La machine virtuelle contient un projet exemple que vous pouvez cloner. Ici, nous clonons via HTTPS, avec l’utilisateur john que nous avons créé auparavant ; Git demande le mot de passe pour cette connexion, mais le cache d’identifiant permettra de sauter cette étape par la suite.

Configuration de Fusion

Une fois que Git Fusion est installé, vous désirerez sûrement modifier la configuration. C’est assez facile à faire via votre client Perforce favori ; rapatriez simplement le répertoire //.git-fusion du serveur Perforce dans votre espace de travail. La structure du fichier ressemble à ceci :

$ tree
.
├── objects
│   ├── repos
│   │   └── [...]
│   └── trees
│       └── [...]

├── p4gf_config
├── repos
│   └── Talkhouse
│       └── p4gf_config
└── users
    └── p4gf_usermap

498 directories, 287 files

Le répertoire objects est utilisé en interne par Git Fusion pour faire correspondre les objets Perforce avec Git et vice versa et il n’y a pas lieu d’y toucher. Il y a un fichier p4gf_config global dans ce répertoire, ainsi qu’un fichier pour chaque dépôt. Ce sont les fichiers de configuration qui déterminent comment Git Fusion se comporte. Examinons le fichier à la racine :

[repo-creation]
charset = utf8

[git-to-perforce]
change-owner = author
enable-git-branch-creation = yes
enable-swarm-reviews = yes
enable-git-merge-commits = yes
enable-git-submodules = yes
preflight-commit = none
ignore-author-permissions = no
read-permission-check = none
git-merge-avoidance-after-change-num = 12107

[perforce-to-git]
http-url = none
ssh-url = none

[@features]
imports = False
chunked-push = False
matrix2 = False
parallel-push = False

[authentication]
email-case-sensitivity = no

Nous ne nous étendrons pas sur les significations des différents paramètres, mais on voit que c’est un simple fichier INI, du même style que ceux utilisés par Git. Ce fichier spécifie les options globales, qui peuvent être surchargées par chaque fichier de configuration spécifique à un dépôt, tel que repos/Talkhouse/p4gf_config. Si vous ouvrez ce fichier, vous verrez une section [@repo] contenant des paramétrages différents des paramètres globaux par défaut. Vous verrez aussi des sections ressemblant à ceci :

[Talkhouse-master]
git-branch-name = master
view = //depot/Talkhouse/main-dev/... ...

C’est la correspondance entre une branche Perforce et une branche Git. Le nom de la section est libre, du moment qu’il est unique. git-branch-name vous permet de convertir un chemin du dépôt qui serait encombrant sous Git en quelque chose de plus utilisable. L’entrée view contrôle comment les fichiers Perforce sont transformés en dépôts Git, en utilisant la syntaxe standard de description de vue. Des correspondances multiples peuvent être indiquées, comme dans cet exemple :

[multi-project-mapping]
git-branch-name = master
view = //depot/project1/main/... project1/...
       //depot/project2/mainline/... project2/...

De cette manière, si votre montage d’espace de travail normal change de structure de répertoires, vous pouvez répliquer cette modification dans le dépôt Git.

Le dernier fichier que nous examinerons est users/p4gf_usermap, qui fait correspondre les utilisateurs Perforce avec les utilisateurs Git, et qui n’est même pas nécessaire. Quand une modification Perforce est convertie en commit Git, le comportement par défaut de Git Fusion consiste à rechercher l’utilisateur Perforce et à utiliser son adresse de courriel et son nom complet comme champs d’auteur/validateur dans Git. Dans l’autre sens, le comportement par défaut consiste à rechercher l’utilisateur Perforce correspondant à l’adresse de courriel stockée dans le champ auteur du commit Git et de soumettre une modification avec cet identifiant (si les permissions l’accordent). Dans la plupart des cas, ce comportement suffira, mais considérons tout de même le fichier de correspondance suivant :

john john@example.com "John Doe"
john johnny@appleseed.net "John Doe"
bob employeeX@example.com "Anon X. Mouse"
joe employeeY@example.com "Anon Y. Mouse"

Chaque ligne est de la forme <utilisateur> <courriel> <nom complet> et crée une correspondance unique. Les deux premières lignes font correspondre deux adresses de courriel distinctes avec le même utilisateur Perforce. C’est utile si vous avez créé des commits Git sous plusieurs adresses de courriel (ou modifié votre adresse de courriel), mais que vous voulez les faire correspondre au même utilisateur Perforce. À la création d’un commit Git depuis une modification Perforce, la première ligne correspondant à l’utilisateur Perforce est utilisée pour fournir l’information d’auteur à Git.

Les deux dernières lignes masquent les noms réels de Bob et Joe dans les commits Git créés. C’est très utile si vous souhaitez ouvrir les sources d’un projet interne, mais que vous ne souhaitez pas rendre public le répertoire de vos employés. Notez que les adresses de courriel et les noms complets devraient être uniques, à moins que vous ne souhaitiez publier tous les commits Git avec un auteur unique fictif.

Utilisation

Perforce Git Fusion est une passerelle à double-sens entre les contrôles de version Perforce et Git. Voyons comment cela se passe du côté Git. Nous supposerons que nous avons monté le projet « Jam » en utilisant le fichier de configuration ci-dessus, et que nous pouvons le cloner comme ceci :

$ git clone https://10.0.1.254/Jam
Cloning into 'Jam'...
Username for 'https://10.0.1.254': john
Password for 'https://ben@10.0.1.254':
remote: Counting objects: 2070, done.
remote: Compressing objects: 100% (1704/1704), done.
Receiving objects: 100% (2070/2070), 1.21 MiB | 0 bytes/s, done.
remote: Total 2070 (delta 1242), reused 0 (delta 0)
Resolving deltas: 100% (1242/1242), done.
Checking connectivity... done.
$ git branch -a
* master
  remotes/origin/HEAD -> origin/master
  remotes/origin/master
  remotes/origin/rel2.1
$ git log --oneline --decorate --graph --all
* 0a38c33 (origin/rel2.1) Create Jam 2.1 release branch.
| * d254865 (HEAD, origin/master, origin/HEAD, master) Upgrade to latest metrowerks on Beos -- the Intel one.
| * bd2f54a Put in fix for jam's NT handle leak.
| * c0f29e7 Fix URL in a jam doc
| * cc644ac Radstone's lynx port.
[...]

La première fois que vous le faites, cela peut durer un certain temps. Ce qui se passe, c’est que Git Fusion convertit toutes les modifications concernées de l’historique Perforce en commits Git. Cela se passe localement sur le serveur, donc c’est plutôt rapide, mais si votre historique est long, ce n’est pas immédiat. Les récupérations subséquentes ne lancent que des conversions incrémentales, ce qui devrait correspondre à la vitesse native de Git.

Comme vous pouvez le voir, notre dépôt ressemble complètement à un autre dépôt Git. Il y a trois branches et Git a utilement créé une branche master locale qui suit la branche origin/master. Travaillons un peu et créons une paire de commits :

# ...
$ git log --oneline --decorate --graph --all
* cfd46ab (HEAD, master) Add documentation for new feature
* a730d77 Whitespace
* d254865 (origin/master, origin/HEAD) Upgrade to latest metrowerks on Beos -- the Intel one.
* bd2f54a Put in fix for jam's NT handle leak.
[...]

Nous avons deux nouveaux commits. Maintenant, vérifions si quelqu’un d’autre a aussi travaillé :

$ git fetch
remote: Counting objects: 5, done.
remote: Compressing objects: 100% (3/3), done.
remote: Total 3 (delta 2), reused 0 (delta 0)
Unpacking objects: 100% (3/3), done.
From https://10.0.1.254/Jam
   d254865..6afeb15  master     -> origin/master
$ git log --oneline --decorate --graph --all
* 6afeb15 (origin/master, origin/HEAD) Update copyright
| * cfd46ab (HEAD, master) Add documentation for new feature
| * a730d77 Whitespace
|/
* d254865 Upgrade to latest metrowerks on Beos -- the Intel one.
* bd2f54a Put in fix for jam's NT handle leak.
[...]

Il semble bien ! Ça n’apparaît pas sur cette vue, mais le commit 6afeb15 a en fait été créé en utilisant un client Perforce. Il ressemble juste à un commit normal du point de vue de Git, ce qui est exactement l’effet recherché. Voyons comment le serveur Perforce gère le commit de fusion :

$ git merge origin/master
Auto-merging README
Merge made by the 'recursive' strategy.
 README | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
$ git push
Counting objects: 9, done.
Delta compression using up to 8 threads.
Compressing objects: 100% (9/9), done.
Writing objects: 100% (9/9), 917 bytes | 0 bytes/s, done.
Total 9 (delta 6), reused 0 (delta 0)
remote: Perforce: 100% (3/3) Loading commit tree into memory...
remote: Perforce: 100% (5/5) Finding child commits...
remote: Perforce: Running git fast-export...
remote: Perforce: 100% (3/3) Checking commits...
remote: Processing will continue even if connection is closed.
remote: Perforce: 100% (3/3) Copying changelists...
remote: Perforce: Submitting new Git commit objects to Perforce: 4
To https://10.0.1.254/Jam
   6afeb15..89cba2b  master -> master

Git pense que ça a marché. Voyons l’historique du fichier README du point de vue de Perforce, en utilisant la fonctionnalité de graphe de révision de p4v :

Graphe de révision de Perforce résultant d’une poussée depuis Git.
Figure 2. Graphe de révision de Perforce résultant d’une poussée depuis Git.

Si vous n’avez jamais vu ceci auparavant, cela peut dérouter, mais c’est une vue similaire à la vue graphique de l’historique Git. Nous visualisons l’historique du fichier README, donc l’arbre de répertoire en haut à gauche ne montre que ce fichier, aux endroits où il apparaît dans différentes branches. En haut à droite, nous avons le graphe visuel des relations entre les différentes révisions du fichier et la vue en grand du graphe en bas à droite. Le reste de l’écran concerne la visualisation des détails pour la révision sélectionnée (2 dans ce cas).

Une chose à noter est que le graphe ressemble exactement à celui de l’historique Git. Perforce n’avait pas de branche nommée pour stocker les commits 1 et 2, il a donc créé une branche « anonymous » dans le répertoire .git-fusion pour la gérer. Cela arrivera aussi pour des branches Git nommées qui ne correspondent pas à une branche Perforce nommée (et que vous pouvez plus tard faire correspondre à une branche Perforce en utilisant le fichier de configuration).

Tout ceci se passe en coulisse, mais le résultat final est qu’une personne dans l’équipe peut utiliser Git, une autre Perforce et aucune des deux n’a à se soucier du choix de l’autre.

Résumé Git-Fusion

Si vous avez accès (ou pouvez avoir accès) à un votre serveur Perforce, Git Fusion est un excellent moyen de faire parler Git et Perforce ensemble. Cela nécessite un peu de configuration, mais la courbe d’apprentissage n’est pas très raide. C’est une des rares sections de ce chapitre où il est inutile de faire spécifiquement attention à ne pas utiliser toute la puissance de Git. Cela ne signifie pas que Perforce sera ravi de tout ce que vous lui enverrez — si vous réécrivez l’historique qui a déjà été poussé, Git Fusion va le rejeter — Git Fusion cherche vraiment à sembler naturel. Vous pouvez même utiliser les sous-modules Git (bien qu’ils paraîtront étranges pour les utilisateurs Perforce), et fusionner les branches (ce qui sera enregistré comme une intégration du côté Perforce).

Si vous ne pouvez pas convaincre un administrateur de votre serveur d’installer Git Fusion, il existe encore un moyen d’utiliser ces outils ensemble.

Git-p4

Git-p4 est une passerelle à double sens entre Git et Perforce. Il fonctionne intégralement au sein de votre dépôt Git, donc vous n’avez besoin d’aucun accès au serveur Perforce (autre que les autorisations d’utilisateur, bien sûr). Git-p4 n’est pas une solution aussi flexible ou complète que Git Fusion, mais il permet tout de même de réaliser la plupart des activités sans être invasif dans l’environnement serveur.

Note

Vous aurez besoin de l’outil p4 dans votre de chemin de recherche pour travailler avec git-p4. À la date d’écriture du livre, il est disponible à https://www.perforce.com/downloads/Perforce/20-User.

Installation

Pour l’exemple, nous allons lancer le serveur Perforce depuis l’image Git Fusion, comme indiqué ci-dessus, mais nous n’utiliserons pas le serveur Git Fusion et nous dialoguerons avec la gestion de version Perforce directement.

Pour utiliser le client p4 en ligne de commande (dont git-p4 dépend), vous devrez définir quelques variables d’environnement :

$ export P4PORT=10.0.1.254:1666
$ export P4USER=john
Démarrage

Comme d’habitude avec Git, la première commande est un clonage :

$ git p4 clone //depot/www/live www-shallow
Importing from //depot/www/live into www-shallow
Initialized empty Git repository in /private/tmp/www-shallow/.git/
Doing initial import of //depot/www/live/ from revision #head into refs/remotes/p4/master

Cela crée ce qui en parlé Git s’appelle un clone « superficiel » (shallow) ; seule la toute dernière révision Perforce est importée dans Git ; souvenez-vous que Perforce n’a pas été pensé pour fournir toutes les révisions à chaque utilisateur. C’est suffisant pour utiliser Git comme client Perforce, mais pour d’autres utilisations, ce n’est pas assez.

Une fois que c’est terminé, nous avons un dépôt Git complètement fonctionnel.

$ cd myproject
$ git log --oneline --all --graph --decorate
* 70eaf78 (HEAD, p4/master, p4/HEAD, master) Initial import of //depot/www/live/ from the state at revision #head

Notez le dépôt p4 distant pour le serveur Perforce, mais tout le reste ressemble à un clone standard. En fait, c’est trompeur ; ce n’est pas réellement dépôt distant.

$ git remote -v

Il n’y a pas du tout de dépôt distant. Git-p4 a créé des références qui représentent l’état du serveur et celles-ci ressemblent à des références de dépôts distants dans git log, mais elles ne sont pas gérées par Git lui-même et vous ne pouvez pas pousser dessus.

Utilisation

Donc, travaillons un peu. Supposons que vous avez progressé sur une fonctionnalité très importante et que vous êtes prêt à la montrer au reste de votre équipe.

$ git log --oneline --all --graph --decorate
* 018467c (HEAD, master) Change page title
* c0fb617 Update link
* 70eaf78 (p4/master, p4/HEAD) Initial import of //depot/www/live/ from the state at revision #head

Nous avons réalisé deux nouveaux commits qui sont prêts à être soumis au serveur Perforce. Vérifions si quelqu’un d’autre a poussé son travail entre temps.

$ git p4 sync
git p4 sync
Performing incremental import into refs/remotes/p4/master git branch
Depot paths: //depot/www/live/
Import destination: refs/remotes/p4/master
Importing revision 12142 (100%)
$ git log --oneline --all --graph --decorate
* 75cd059 (p4/master, p4/HEAD) Update copyright
| * 018467c (HEAD, master) Change page title
| * c0fb617 Update link
|/
* 70eaf78 Initial import of //depot/www/live/ from the state at revision #head

Il semblerait que ce soit le cas, et master et p4/master ont divergé. Le système de branchement de Perforce ne ressemble en rien à celui de Git, donc soumettre des commits de fusion n’a aucun sens. Git-p4 recommande de rebaser vos commits et fournit même un raccourci pour le faire :

$ git p4 rebase
Performing incremental import into refs/remotes/p4/master git branch
Depot paths: //depot/www/live/
No changes to import!
Rebasing the current branch onto remotes/p4/master
First, rewinding head to replay your work on top of it...
Applying: Update link
Applying: Change page title
 index.html | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

Vous pouvez déjà le deviner aux messages affichés, mais git p4 rebase est un raccourci pour git p4 sync suivi de git rebase p4/master. C’est légèrement plus intelligent que cela, spécifiquement lors de la gestion de branches multiples, mais ça correspond bien.

À présent, notre historique est linéaire à nouveau et nous sommes prêts à remonter nos modifications sur Perforce. La commande git p4 submit va essayer de créer une nouvelle révision Perforce pour chaque commit Git entre p4/master et master. Son lancement ouvre notre éditeur favori et le contenu du fichier ouvert ressemble à ceci :

# A Perforce Change Specification.
#
#  Change:      The change number. 'new' on a new changelist.
#  Date:        The date this specification was last modified.
#  Client:      The client on which the changelist was created.  Read-only.
#  User:        The user who created the changelist.
#  Status:      Either 'pending' or 'submitted'. Read-only.
#  Type:        Either 'public' or 'restricted'. Default is 'public'.
#  Description: Comments about the changelist.  Required.
#  Jobs:        What opened jobs are to be closed by this changelist.
#               You may delete jobs from this list.  (New changelists only.)
#  Files:       What opened files from the default changelist are to be added
#               to this changelist.  You may delete files from this list.
#               (New changelists only.)

Change:  new

Client:  john_bens-mbp_8487

User: john

Status:  new

Description:
   Update link

Files:
   //depot/www/live/index.html   # edit


######## git author ben@straub.cc does not match your p4 account.
######## Use option --preserve-user to modify authorship.
######## Variable git-p4.skipUserNameCheck hides this message.
######## everything below this line is just the diff #######
--- //depot/www/live/index.html  2014-08-31 18:26:05.000000000 0000
+++ /Users/ben/john_bens-mbp_8487/john_bens-mbp_8487/depot/www/live/index.html   2014-08-31 18:26:05.000000000 0000
@@ -60,7 +60,7 @@
 </td>
 <td valign=top>
 Source and documentation for
-<a href="https://www.perforce.com/jam/jam.html">
+<a href="jam.html">
 Jam/MR</a>,
 a software build tool.
 </td>

C’est quasiment le même contenu qu’on verrait en lançant p4 submit, mis à part le bloc à la fin que git-p4 a utilement inclus. Git-p4 essaye d’honorer vos réglages Git et Perforce individuellement quand il doit fournir un nom pour un commit ou une modification, mais dans certains cas, vous voudrez le modifier. Par exemple, si le commit Git que vous importez a été écrit par un contributeur qui n’a pas de compte utilisateur dans Perforce, vous voudrez tout de même que la modification résultante ait l’air d’avoir été écrite par lui, et non par vous.

Git-p4 a importé le message du commit Git comme contenu de la modification Perforce, donc tout ce qu’il nous reste à faire et de sauvegarder et de quitter, deux fois (une fois par commit). La sortie qui en résulte ressemble à ceci :

$ git p4 submit
Perforce checkout for depot path //depot/www/live/ located at /Users/ben/john_bens-mbp_8487/john_bens-mbp_8487/depot/www/live/
Synchronizing p4 checkout...
... - file(s) up-to-date.
Applying dbac45b Update link
//depot/www/live/index.html#4 - opened for edit
Change 12143 created with 1 open file(s).
Submitting change 12143.
Locking 1 files ...
edit //depot/www/live/index.html#5
Change 12143 submitted.
Applying 905ec6a Change page title
//depot/www/live/index.html#5 - opened for edit
Change 12144 created with 1 open file(s).
Submitting change 12144.
Locking 1 files ...
edit //depot/www/live/index.html#6
Change 12144 submitted.
All commits applied!
Performing incremental import into refs/remotes/p4/master git branch
Depot paths: //depot/www/live/
Import destination: refs/remotes/p4/master
Importing revision 12144 (100%)
Rebasing the current branch onto remotes/p4/master
First, rewinding head to replay your work on top of it...
$ git log --oneline --all --graph --decorate
* 775a46f (HEAD, p4/master, p4/HEAD, master) Change page title
* 05f1ade Update link
* 75cd059 Update copyright
* 70eaf78 Initial import of //depot/www/live/ from the state at revision #head

À la sortie, c’est comme si nous avions fait un git push, ce qui est l’analogie la plus proche avec ce qui s’est réellement passé.

Notez aussi que durant ce processus, les commits Git sont transformés en modifications Perforce ; si vous voulez les comprimer en une seule modification, vous pouvez le faire avec un rebasage interactif avant de lancer git p4 submit. Notez aussi que les empreintes SHA-1 de tous les commits qui ont été soumis comme modifications ont changé ; c’est parce que git-p4 ajoute une ligne à la fin de chaque message de validation qu’il convertit :

$ git log -1
commit 775a46f630d8b46535fc9983cf3ebe6b9aa53145
Author: John Doe <john@example.com>
Date:   Sun Aug 31 10:31:44 2014 -0800

    Change page title

    [git-p4: depot-paths = "//depot/www/live/": change = 12144]

Que se passe-t-il si vous essayez de soumettre un commit de fusion ? Essayons pour voir. Voici la situation dans laquelle nous sommes :

$ git log --oneline --all --graph --decorate
* 3be6fd8 (HEAD, master) Correct email address
*   1dcbf21 Merge remote-tracking branch 'p4/master'
|\
| * c4689fc (p4/master, p4/HEAD) Grammar fix
* | cbacd0a Table borders: yes please
* | b4959b6 Trademark
|/
* 775a46f Change page title
* 05f1ade Update link
* 75cd059 Update copyright
* 70eaf78 Initial import of //depot/www/live/ from the state at revision #head

Les historiques Git et Perforce divergent à partir de 775a46f. Le côté Git contient deux commits, puis un commit de fusion avec la tête Perforce, puis un autre commit. Nous allons essayer de les soumettre au sommet d’un seul changement côté Perforce. Voyons ce qui se passerait si nous essayions de soumettre cet historique maintenant :

$ git p4 submit -n
Perforce checkout for depot path //depot/www/live/ located at /Users/ben/john_bens-mbp_8487/john_bens-mbp_8487/depot/www/live/
Would synchronize p4 checkout in /Users/ben/john_bens-mbp_8487/john_bens-mbp_8487/depot/www/live/
Would apply
  b4959b6 Trademark
  cbacd0a Table borders: yes please
  3be6fd8 Correct email address

L’option -n est un raccourci pour --dry-run qui essaie d’afficher ce qui se passerait si la commande submit était réellement lancée. Dans ce cas, il semble que nous créerions trois modifications Perforce, ce qui correspond aux trois commits sans fusion qui n’existent pas encore sur le serveur Perforce. Cela ressemble exactement à ce que nous souhaitons, voyons comment cela se passe :

$ git p4 submit
[…]
$ git log --oneline --all --graph --decorate
* dadbd89 (HEAD, p4/master, p4/HEAD, master) Correct email address
* 1b79a80 Table borders: yes please
* 0097235 Trademark
* c4689fc Grammar fix
* 775a46f Change page title
* 05f1ade Update link
* 75cd059 Update copyright
* 70eaf78 Initial import of //depot/www/live/ from the state at revision #head

Notre historique est devenu linéaire, comme si nous avions rebasé avant de soumettre (ce qui est exactement ce qui s’est passé). Cela signifie que vous êtes libre de créer, modifier, jeter et fusionner les branches du côté Git sans crainte que votre historique deviennent à un moment incompatible avec Perforce. Si vous pouvez le rebaser, vous pourrez le reporter dans le serveur Perforce.

Branche

Si votre projet Perforce a de multiples branches, vous n’êtes pas malchanceux ; git-p4 peut gérer cette configuration d’une manière similaire à Git. Supposons que votre dépôt Perforce ait la forme suivante :

//depot
  └── project
      ├── main
      └── dev

Et supposons que vous ayez une branche dev qui contient une view spec qui ressemble à ceci :

//depot/project/main/... //depot/project/dev/...

Git-p4 peut détecter automatiquement cette situation et faire ce qu’il faut :

$ git p4 clone --detect-branches //depot/project@all
Importing from //depot/project@all into project
Initialized empty Git repository in /private/tmp/project/.git/
Importing revision 20 (50%)
    Importing new branch project/dev

    Resuming with change 20
Importing revision 22 (100%)
Updated branches: main dev
$ cd project; git log --oneline --all --graph --decorate
* eae77ae (HEAD, p4/master, p4/HEAD, master) main
| * 10d55fb (p4/project/dev) dev
| * a43cfae Populate //depot/project/main/... //depot/project/dev/....
|/
* 2b83451 Project init

Notez le déterminant « @all » ; il indique à git-p4 de cloner non seulement la dernière modification pour ce sous-arbre, mais aussi toutes les modifications qui ont déjà touché à ces chemins. C’est plus proche du concept de clone dans Git, mais si vous travaillez sur un projet avec un long historique, cela peut prendre du temps à se terminer.

L’option --detect-branches indique à git-p4 d’utiliser les spécifications de branche de Perforce pour faire correspondre aux références Git. Si ces correspondances ne sont pas présentes sur le serveur Perforce (ce qui est une manière tout à fait valide d’utiliser Perforce), vous pouvez dire à git-p4 ce que sont les correspondances de branches, et vous obtiendrez le même résultat :

$ git init project
Initialized empty Git repository in /tmp/project/.git/
$ cd project
$ git config git-p4.branchList main:dev
$ git clone --detect-branches //depot/project@all .

Renseigner la variable de configuration git-p4.branchList à main:dev indique à git-p4 que main et dev sont toutes deux des branches et que la seconde est la fille de la première.

Si nous lançons maintenant git checkout -b dev p4/project/dev et ajoutons quelques commits, git-p4 est assez intelligent pour cibler la bonne branche quand nous lançons git-p4 submit. Malheureusement, git-p4 ne peut pas mélanger les clones superficiels et les branches multiples ; si vous avez un projet gigantesque et que vous voulez travailler sur plus d’une branche, vous devrez lancer git p4 clone une fois pour chaque branche à laquelle vous souhaitez soumettre.

Pour créer ou intégrer des branches, vous devrez utiliser un client Perforce. Git-p4 ne peut synchroniser et soumettre que sur des branches préexistantes, et il ne peut le faire qu’avec une modification linéaire à la fois. Si vous fusionnez deux branches dans Git et que vous essayez de soumettre la nouvelle modification, tout ce qui sera enregistré sera une série de modifications de fichiers ; les métadonnées relatives aux branches impliquées dans cette intégration seront perdues.

Résumé Git et Perforce

Git-p4 rend possible l’usage des modes d’utilisation de Git avec un serveur Perforce, et ce, de manière plutôt réussie. Cependant, il est important de se souvenir que Perforce gère les sources et qu’on ne travaille avec Git que localement. Il faut rester vraiment attentif au partage de commits Git ; si vous avez un dépôt distant que d’autres personnes utilisent, ne poussez aucun commit qui n’a pas déjà été soumis au serveur Perforce.

Si vous souhaitez mélanger l’utilisation de Git et de Perforce comme clients pour la gestion de source sans restriction et si vous arrivez à convaincre un administrateur de l’installer, Git Fusion fait de Git un client de premier choix pour un serveur Perforce.