-
1. DĂ©marrage rapide
-
2. Les bases de Git
-
3. Les branches avec Git
-
4. Git sur le serveur
- 4.1 Protocoles
- 4.2 Installation de Git sur un serveur
- 4.3 Génération des clés publiques SSH
- 4.4 Mise en place du serveur
- 4.5 DĂ©mon (Daemon) Git
- 4.6 HTTP intelligent
- 4.7 GitWeb
- 4.8 GitLab
- 4.9 Git hébergé
- 4.10 Résumé
-
5. Git distribué
-
6. GitHub
-
7. Utilitaires Git
- 7.1 SĂ©lection des versions
- 7.2 Indexation interactive
- 7.3 Remisage et nettoyage
- 7.4 Signer votre travail
- 7.5 Recherche
- 7.6 RĂ©Ă©crire lâhistorique
- 7.7 Reset démystifié
- 7.8 Fusion avancée
- 7.9 Rerere
- 7.10 DĂ©boguer avec Git
- 7.11 Sous-modules
- 7.12 Empaquetage (bundling)
- 7.13 Replace
- 7.14 Stockage des identifiants
- 7.15 Résumé
-
8. Personnalisation de Git
- 8.1 Configuration de Git
- 8.2 Attributs Git
- 8.3 Crochets Git
- 8.4 Exemple de politique gérée par Git
- 8.5 Résumé
-
9. Git et les autres systĂšmes
- 9.1 Git comme client
- 9.2 Migration vers Git
- 9.3 Résumé
-
10. Les tripes de Git
- 10.1 Plomberie et porcelaine
- 10.2 Les objets de Git
- 10.3 Références Git
- 10.4 Fichiers groupés
- 10.5 La refspec
- 10.6 Les protocoles de transfert
- 10.7 Maintenance et récupération de données
- 10.8 Les variables dâenvironnement
- 10.9 Résumé
-
A1. Annexe A: Git dans dâautres environnements
- A1.1 Interfaces graphiques
- A1.2 Git dans Visual Studio
- A1.3 Git dans Visual Studio Code
- A1.4 Git dans IntelliJ / PyCharm / WebStorm / PhpStorm / RubyMine
- A1.5 Git dans Sublime Text
- A1.6 Git dans Bash
- A1.7 Git dans Zsh
- A1.8 Git dans PowerShell
- A1.9 Résumé
-
A2. Annexe B: Embarquer Git dans vos applications
- A2.1 Git en ligne de commande
- A2.2 Libgit2
- A2.3 JGit
- A2.4 go-git
- A2.5 Dulwich
-
A3. Commandes Git
- A3.1 Installation et configuration
- A3.2 Obtention et création des projets
- A3.3 Capture dâinstantanĂ© basique
- A3.4 Création de branches et fusion
- A3.5 Partage et mise Ă jour de projets
- A3.6 Inspection et comparaison
- A3.7 DĂ©bogage
- A3.8 Patchs
- A3.9 Courriel
- A3.10 SystĂšmes externes
- A3.11 Administration
- A3.12 Commandes de plomberie
9.1 Git et les autres systĂšmes - Git comme client
Le monde nâest pas parfait. Habituellement, vous ne pouvez pas basculer immĂ©diatement sous Git tous les projets que vous pourriez rencontrer. Quelques fois, vous ĂȘtes bloquĂ© sur un projet utilisant un autre VCS et vous regrettez que ce ne soit pas Git. Dans la premiĂšre partie de ce chapitre, nous traiterons de la maniĂšre dâutiliser git comme client pour les projets utilisant un autre systĂšme.
Ă un moment, vous voudrez convertir votre projet Ă Git. La seconde partie de ce chapitre traite la migration de votre projet dans Git depuis certains systĂšmes spĂ©cifiques et enfin par un script dâimport personnalisĂ© pour les cas non-standards.
Git comme client
Git fournit de si bonnes sensations aux dĂ©veloppeurs que de nombreuses personnes ont cherchĂ© Ă lâutiliser sur leur station de travail, mĂȘme si le reste de leur Ă©quipe utilise un VCS complĂštement diffĂ©rent. Il existe un certain nombre dâadaptateurs appelĂ©s « passerelles ». Nous allons en dĂ©crire certains des plus communs.
Git et Subversion
Aujourdâhui, la majoritĂ© des projets de dĂ©veloppement libre et un grand nombre de projets dans les sociĂ©tĂ©s utilisent Subversion pour gĂ©rer leur code source. Il a Ă©tĂ© le VCS libre le plus populaire depuis une bonne dĂ©cennie et a Ă©tĂ© considĂ©rĂ© comme le choix de facto pour les projets open-source. Il est aussi trĂšs similaire Ă CVS qui a Ă©tĂ© le grand chef des gestionnaires de source avant lui.
Une des grandes fonctionnalités de Git est sa passerelle vers Subversion, git svn
.
Cet outil vous permet dâutiliser Git comme un client valide dâun serveur Subversion pour que vous puissiez utiliser les capacitĂ©s de Git en local puis pousser sur le serveur Subversion comme si vous utilisiez Subversion localement.
Cela signifie que vous pouvez rĂ©aliser localement les embranchements et les fusions, utiliser lâindex, utiliser le rebasage et le picorage de commits, etc, tandis que vos collaborateurs continuent de travailler avec leurs mĂ©thodes ancestrales et obscures.
Câest une bonne maniĂšre dâintroduire Git dans un environnement professionnel et dâaider vos collĂšgues dĂ©veloppeurs Ă devenir plus efficaces tandis que vous ferez pression pour une modification de lâinfrastructure vers lâutilisation massive de Git.
La passerelle Subversion nâest que la premiĂšre dose vers la drogue du monde des DVCS.
git svn
La commande de base dans Git pour toutes les commandes de passerelle est git svn
.
Vous préfixerez tout avec cette paire de mots.
Les possibilités étant nombreuses, nous traiterons des plus communes pendant que nous détaillerons quelques petits modes de gestion.
Il est important de noter que lorsque vous utilisez git svn
, vous interagissez avec Subversion qui est un systÚme fonctionnant trÚs différemment de Git.
Bien que vous puissiez rĂ©aliser des branches locales et les fusionner, il est gĂ©nĂ©ralement conseillĂ© de conserver votre historique le plus linĂ©aire possible en rebasant votre travail et en Ă©vitant des activitĂ©s telles quâinteragir dans le mĂȘme temps avec un dĂ©pĂŽt Git distant.
Ne rĂ©Ă©crivez pas votre historique avant dâessayer de pousser Ă nouveau et ne poussez pas en parallĂšle dans un dĂ©pĂŽt Git pour collaborer avec vos collĂšgues dĂ©veloppant avec Git. Subversion ne supporte quâun historique linĂ©aire et il est trĂšs facile de lâĂ©garer. Si vous travaillez avec une Ă©quipe dont certains membres utilisent SVN et dâautres utilisent Git, assurez-vous que tout le monde nâutilise que le serveur SVN pour collaborer, cela vous rendra service.
Installation
Pour montrer cette fonctionnalité, il faut un serveur SVN sur lequel vous avez des droits en écriture.
Pour copier ces exemples, vous avez besoin de faire une copie inscriptible dâun dĂ©pĂŽt SVN de test accessible.
Dans cette optique, vous pouvez utiliser un outil appelé svnsync
qui est livrĂ© avec les versions les plus rĂ©centes de Subversion â il devrait ĂȘtre distribuĂ© avec les versions Ă partir de 1.4.
En préparation, créez un nouveau dépÎt local Subversion :
$ mkdir /tmp/test-svn
$ svnadmin create /tmp/test-svn
Ensuite, autorisez tous les utilisateurs Ă changer les revprops â le moyen le plus simple consiste Ă ajouter un script pre-revprop-change
qui renvoie toujours 0Â :
$ cat /tmp/test-svn/hooks/pre-revprop-change
#!/bin/sh
exit 0;
$ chmod +x /tmp/test-svn/hooks/pre-revprop-change
Vous pouvez à présent synchroniser ce projet sur votre machine locale en lançant svnsync init
avec les dépÎts source et cible.
$ svnsync init file:///tmp/test-svn https://votre-serveur-svn.org/svn/
Cela initialise les propriétés nécessaires à la synchronisation. Vous pouvez ensuite cloner le code en lançant :
$ svnsync sync file:///tmp/test-svn
Committed revision 1.
Copied properties for revision 1.
Transmitting file data .............................[...]
Committed revision 2.
Copied properties for revision 2.
[âŠ]
Bien que cette opĂ©ration ne dure que quelques minutes, si vous essayez de copier le dĂ©pĂŽt original sur un autre dĂ©pĂŽt distant au lieu dâun dĂ©pĂŽt local, le processus durera prĂšs dâune heure, en dĂ©pit du fait quâil y a moins de 100 commits. Subversion doit cloner rĂ©vision par rĂ©vision puis pousser vers un autre dĂ©pĂŽt â câest ridiculement inefficace mais câest la seule possibilitĂ©.
DĂ©marrage
Avec des droits en Ă©criture sur un dĂ©pĂŽt Subversion, vous voici prĂȘt Ă expĂ©rimenter une mĂ©thode typique.
Commençons par la commande git svn clone
qui importe un dépÎt Subversion complet dans un dépÎt Git local.
Souvenez-vous que si vous importez depuis un dĂ©pĂŽt Subversion hĂ©bergĂ© sur Internet, il faut remplacer lâURL file://tmp/test-svn
ci-dessous par lâURL de votre dĂ©pĂŽt Subversion :
$ git svn clone file:///tmp/test-svn -T trunk -b branches -t tags
Initialized empty Git repository in /private/tmp/progit/test-svn/.git/
r1 = dcbfb5891860124cc2e8cc616cded42624897125 (refs/remotes/origin/trunk)
A m4/acx_pthread.m4
A m4/stl_hash.m4
A java/src/test/java/com/google/protobuf/UnknownFieldSetTest.java
A java/src/test/java/com/google/protobuf/WireFormatTest.java
âŠ
r75 = 556a3e1e7ad1fde0a32823fc7e4d046bcfd86dae (refs/remotes/origin/trunk)
Found possible branch point: file:///tmp/test-svn/trunk => file:///tmp/test-svn/branches/my-calc-branch, 75
Found branch parent: (refs/remotes/origin/my-calc-branch) 556a3e1e7ad1fde0a32823fc7e4d046bcfd86dae
Following parent with do_switch
Successfully followed parent
r76 = 0fb585761df569eaecd8146c71e58d70147460a2 (refs/remotes/origin/my-calc-branch)
Checked out HEAD:
file:///tmp/test-svn/trunk r75
Cela Ă©quivaut Ă lancer git svn init
suivi de git svn fetch
sur lâURL que vous avez fournie.
Cela peut prendre un certain temps.
Le projet de test ne contient que 75 commits et la taille du code nâest pas extraordinaire, ce qui prend juste quelques minutes.
Cependant, Git doit extraire chaque version, une par une et les valider individuellement.
Pour un projet contenant des centaines ou des milliers de commits, cela peut prendre littĂ©ralement des heures ou mĂȘme des jours Ă terminer.
La partie -T trunk -b branches -t tags
indique Ă Git que ce dĂ©pĂŽt Subversion suit les conventions de base en matiĂšre dâembranchement et dâĂ©tiquetage.
Si vous nommez votre trunk, vos branches ou vos étiquettes différemment, vous pouvez modifier ces options.
Comme cette organisation est la plus commune, ces options peuvent ĂȘtre simplement remplacĂ©es par -s
qui signifie structure standard.
La commande suivante est équivalente :
$ git svn clone file:///tmp/test-svn -s
Ă prĂ©sent, vous disposez dâun dĂ©pĂŽt Git valide qui a importĂ© vos branches et vos Ă©tiquettes :
$ git branch -a
* master
remotes/origin/my-calc-branch
remotes/origin/tags/2.0.2
remotes/origin/tags/release-2.0.1
remotes/origin/tags/release-2.0.2
remotes/origin/tags/release-2.0.2rc1
remotes/origin/trunk
Il est important de remarquer comment cet outil sous-classe vos références distantes différemment.
Voyons de plus prĂšs avec la commande Git de plomberie show-ref
 :
$ git show-ref
556a3e1e7ad1fde0a32823fc7e4d046bcfd86dae refs/heads/master
0fb585761df569eaecd8146c71e58d70147460a2 refs/remotes/origin/my-calc-branch
bfd2d79303166789fc73af4046651a4b35c12f0b refs/remotes/origin/tags/2.0.2
285c2b2e36e467dd4d91c8e3c0c0e1750b3fe8ca refs/remotes/origin/tags/release-2.0.1
cbda99cb45d9abcb9793db1d4f70ae562a969f1e refs/remotes/origin/tags/release-2.0.2
a9f074aa89e826d6f9d30808ce5ae3ffe711feda refs/remotes/origin/tags/release-2.0.2rc1
556a3e1e7ad1fde0a32823fc7e4d046bcfd86dae refs/remotes/origin/trunk
Git ne fait pas cela quand il clone depuis un serveur Git ; voici à quoi ressemble un dépÎt avec des étiquettes juste aprÚs le clonage :
$ git show-ref
c3dcbe8488c6240392e8a5d7553bbffcb0f94ef0 refs/remotes/origin/master
32ef1d1c7cc8c603ab78416262cc421b80a8c2df refs/remotes/origin/branch-1
75f703a3580a9b81ead89fe1138e6da858c5ba18 refs/remotes/origin/branch-2
23f8588dde934e8f33c263c6d8359b2ae095f863 refs/tags/v0.1.0
7064938bd5e7ef47bfd79a685a62c1e2649e2ce7 refs/tags/v0.2.0
6dcb09b5b57875f334f61aebed695e2e4193db5e refs/tags/v1.0.0
Git entrepose les Ă©tiquettes directement dans refs/tags
, plutĂŽt que de les traiter comme des branches distantes.
Valider en retour sur le serveur Subversion
Comme vous disposez dâun dĂ©pĂŽt en Ă©tat de marche, vous pouvez commencer Ă travailler sur le projet et pousser vos commits en utilisant efficacement Git comme client SVN. Si vous Ă©ditez un des fichiers et le validez, vous crĂ©ez un commit qui existe localement dans Git mais qui nâexiste pas sur le serveur Subversion :
$ git commit -am 'Adding git-svn instructions to the README'
[master 4af61fd] Adding git-svn instructions to the README
1 file changed, 5 insertions(+)
Ensuite, vous avez besoin de pousser vos modifications en amont.
Remarquez que cela modifie la maniĂšre de travailler par rapport Ă Subversion â vous pouvez rĂ©aliser plusieurs validations en mode dĂ©connectĂ© pour ensuite les pousser toutes en une fois sur le serveur Subversion.
Pour pousser sur un serveur Subversion, il faut lancer la commande git svn dcommit
 :
$ git svn dcommit
Committing to file:///tmp/test-svn/trunk ...
M README.txt
Committed r77
M README.txt
r77 = 95e0222ba6399739834380eb10afcd73e0670bc5 (refs/remotes/origin/trunk)
No changes between 4af61fd05045e07598c553167e0f31c84fd6ffe1 and refs/remotes/origin/trunk
Resetting to the latest refs/remotes/origin/trunk
Cette commande rassemble tous les commits que vous avez validĂ©s par-dessus le code du serveur Subversion et rĂ©alise un commit sur le serveur pour chacun, puis rĂ©Ă©crit lâhistorique Git local pour y ajouter un identifiant unique.
Cette étape est à souligner car elle signifie que toutes les sommes de contrÎle SHA-1 de vos commits locaux ont changé.
Câest en partie pour cette raison que câest une idĂ©e trĂšs pĂ©rilleuse de vouloir travailler dans le mĂȘme temps avec des serveurs Git distants.
Lâexamen du dernier commit montre que le nouveau git-svn-id
a été ajouté :
$ git log -1
commit 95e0222ba6399739834380eb10afcd73e0670bc5
Author: ben <ben@0b684db3-b064-4277-89d1-21af03df0a68>
Date: Thu Jul 24 03:08:36 2014 +0000
Adding git-svn instructions to the README
git-svn-id: file:///tmp/test-svn/trunk@77 0b684db3-b064-4277-89d1-21af03df0a68
Remarquez que la somme de contrÎle SHA qui commençait par 4af61fd
quand vous avez validé commence à présent par 95e0222
.
Si vous souhaitez pousser Ă la fois sur un serveur Git et un serveur Subversion, il faut obligatoirement pousser (dcommit
) sur le serveur Subversion en premier, car cette action va modifier vos données des commits.
Tirer des modifications
Quand vous travaillez avec dâautres dĂ©veloppeurs, il arrive Ă certains moments que ce quâun dĂ©veloppeur a poussĂ© provoque un conflit lorsquâun autre voudra pousser Ă son tour.
Cette modification sera rejetĂ©e jusquâĂ ce quâelle soit fusionnĂ©e.
Dans git svn
, cela ressemble à ceci :
$ git svn dcommit
Committing to file:///tmp/test-svn/trunk ...
ERROR from SVN:
Transaction is out of date: File '/trunk/README.txt' is out of date
W: d5837c4b461b7c0e018b49d12398769d2bfc240a and refs/remotes/origin/trunk differ, using rebase:
:100644 100644 f414c433af0fd6734428cf9d2a9fd8ba00ada145 c80b6127dd04f5fcda218730ddf3a2da4eb39138 M README.txt
Current branch master is up to date.
ERROR: Not all changes have been committed into SVN, however the committed
ones (if any) seem to be successfully integrated into the working tree.
Please see the above messages for details.
Pour résoudre cette situation, vous pouvez lancer la commande git svn rebase
qui tire depuis le serveur toute modification apparue entre temps et rebase votre travail sur le sommet de lâhistorique du serveur :
$ git svn rebase
Committing to file:///tmp/test-svn/trunk ...
ERROR from SVN:
Transaction is out of date: File '/trunk/README.txt' is out of date
W: eaa029d99f87c5c822c5c29039d19111ff32ef46 and refs/remotes/origin/trunk differ, using rebase:
:100644 100644 65536c6e30d263495c17d781962cfff12422693a b34372b25ccf4945fe5658fa381b075045e7702a M README.txt
First, rewinding head to replay your work on top of it...
Applying: update foo
Using index info to reconstruct a base tree...
M README.txt
Falling back to patching base and 3-way merge...
Auto-merging README.txt
ERROR: Not all changes have been committed into SVN, however the committed
ones (if any) seem to be successfully integrated into the working tree.
Please see the above messages for details.
Ă prĂ©sent, tout votre travail se trouve au-delĂ de lâhistorique du serveur et vous pouvez effectivement rĂ©aliser un dcommit
 :
$ git svn dcommit
Committing to file:///tmp/test-svn/trunk ...
M README.txt
Committed r85
M README.txt
r85 = 9c29704cc0bbbed7bd58160cfb66cb9191835cd8 (refs/remotes/origin/trunk)
No changes between 5762f56732a958d6cfda681b661d2a239cc53ef5 and refs/remotes/origin/trunk
Resetting to the latest refs/remotes/origin/trunk
Il est important de se souvenir quâĂ la diffĂ©rence de Git qui requiert une fusion avec les modifications distantes non prĂ©sentes localement avant de pouvoir pousser, git svn
ne vous y contraint que si vos modifications provoquent un conflit (de la mĂȘme maniĂšre que svn
).
Si une autre personne pousse une modification Ă un fichier et que vous poussez une modification Ă un autre fichier, votre dcommit
passera sans problÚme :
$ git svn dcommit
Committing to file:///tmp/test-svn/trunk ...
M configure.ac
Committed r87
M autogen.sh
r86 = d8450bab8a77228a644b7dc0e95977ffc61adff7 (refs/remotes/origin/trunk)
M configure.ac
r87 = f3653ea40cb4e26b6281cec102e35dcba1fe17c4 (refs/remotes/origin/trunk)
W: a0253d06732169107aa020390d9fefd2b1d92806 and refs/remotes/origin/trunk differ, using rebase:
:100755 100755 efa5a59965fbbb5b2b0a12890f1b351bb5493c18 e757b59a9439312d80d5d43bb65d4a7d0389ed6d M autogen.sh
First, rewinding head to replay your work on top of it...
Il faut sâen souvenir car le rĂ©sultat de ces actions est un Ă©tat du dĂ©pĂŽt qui nâexistait pas sur aucun des ordinateurs quand vous avez poussĂ©. Si les modifications sont incompatibles mais ne crĂ©ent pas de conflits, vous pouvez crĂ©er des dĂ©fauts qui seront trĂšs difficiles Ă diagnostiquer. Câest une grande diffĂ©rence avec un serveur Git â dans Git, vous pouvez tester complĂštement lâĂ©tat du projet sur votre systĂšme client avant de le publier, tandis quâavec SVN, vous ne pouvez jamais ĂȘtre totalement certain que les Ă©tats avant et aprĂšs validation sont identiques.
Vous devrez aussi lancer cette commande pour tirer les modifications depuis le serveur Subversion, mĂȘme si vous nâĂȘtes pas encore prĂȘt Ă valider.
Vous pouvez lancer git svn fetch
pour tirer les nouveaux commits, mais git svn rebase
tire non seulement les commits distants mais rebase aussi vos commits locaux.
$ git svn rebase
M autogen.sh
r88 = c9c5f83c64bd755368784b444bc7a0216cc1e17b (refs/remotes/origin/trunk)
First, rewinding head to replay your work on top of it...
Fast-forwarded master to refs/remotes/origin/trunk.
Lancer git svn rebase
de temps en temps vous assure que votre travail est toujours synchronisé avec le serveur.
Vous devrez cependant vous assurer que votre copie de travail est propre quand vous la lancez.
Si vous avez des modifications locales, il vous faudra soit remiser votre travail, soit valider temporairement vos modifications avant de lancer git svn rebase
, sinon la commande sâarrĂȘtera si elle dĂ©tecte que le rebasage provoquerait un conflit de fusion.
Le problĂšme avec les branches Git
AprĂšs vous ĂȘtre habituĂ© Ă la maniĂšre de faire avec Git, vous souhaiterez sĂ»rement crĂ©er des branches thĂ©matiques, travailler dessus, puis les fusionner.
Si vous poussez sur un serveur Subversion via git svn
, vous souhaiterez Ă chaque fois rebaser votre travail sur une branche unique au lieu de fusionner les branches ensemble.
La raison principale en est que Subversion gÚre un historique linéaire et ne gÚre pas les fusions comme Git y excelle.
De ce fait, git svn
suit seulement le premier parent lorsquâil convertit les instantanĂ©s en commits Subversion.
Supposons que votre historique ressemble Ă ce qui suit.
Vous avez créé une branche experience
, avez réalisé deux validations puis les avez fusionnées dans master
.
Lors du dcommit
, vous voyez le résultat suivant :
$ git svn dcommit
Committing to file:///tmp/test-svn/trunk ...
M CHANGES.txt
Committed r89
M CHANGES.txt
r89 = 89d492c884ea7c834353563d5d913c6adf933981 (refs/remotes/origin/trunk)
M COPYING.txt
M INSTALL.txt
Committed r90
M INSTALL.txt
M COPYING.txt
r90 = cb522197870e61467473391799148f6721bcf9a0 (refs/remotes/origin/trunk)
No changes between 71af502c214ba13123992338569f4669877f55fd and refs/remotes/origin/trunk
Resetting to the latest refs/remotes/origin/trunk
Lancer dcommit
sur une branche avec un historique fusionnĂ© fonctionne correctement, Ă lâexception que lâexamen de lâhistorique du projet Git indique quâil nâa rĂ©Ă©crit aucun des commits rĂ©alisĂ©s sur la branche experience
, mais que toutes les modifications introduites apparaissent dans la version SVN de lâunique commit de fusion.
Quand quelquâun dâautre clone ce travail, tout ce quâil voit, câest le commit de la fusion avec toutes les modifications injectĂ©es en une fois, comme si vous aviez lancĂ© git merge --squash
.
Il ne voit aucune information sur son origine ni sur sa date de validation.
Les embranchements dans Subversion
La gestion de branches dans Subversion nâa rien Ă voir avec celle de Git.
Ăvitez de lâutiliser autant que possible.
Cependant vous pouvez créer des branches et valider dessus dans Subversion en utilisant git svn
.
Créer une nouvelle branche SVN
Pour créer une nouvelle branche dans Subversion, vous pouvez utiliser la commande git svn branch [nom de la branche]
 :
$ git svn branch opera
Copying file:///tmp/test-svn/trunk at r90 to file:///tmp/test-svn/branches/opera...
Found possible branch point: file:///tmp/test-svn/trunk => file:///tmp/test-svn/branches/opera, 90
Found branch parent: (refs/remotes/origin/opera) cb522197870e61467473391799148f6721bcf9a0
Following parent with do_switch
Successfully followed parent
r91 = f1b64a3855d3c8dd84ee0ef10fa89d27f1584302 (refs/remotes/origin/opera)
Cela est Ă©quivalent Ă la commande Subversion svn copy trunk branches/opera
et rĂ©alise lâopĂ©ration sur le serveur Subversion.
Remarquez que cette commande ne vous bascule pas sur cette branche ; si vous validez, le commit sâappliquera Ă trunk
et non Ă la branche opera
.
Basculer de branche active
Git devine la branche cible des dcommits
en se rĂ©fĂ©rant au sommet des branches Subversion dans votre historique â vous ne devriez en avoir quâun et celui-ci devrait ĂȘtre le dernier possĂ©dant un git-svn-id
dans lâhistorique actuel de votre branche.
Si vous souhaitez travailler simultanément sur plusieurs branches, vous pouvez régler vos branches locales pour que le dcommit
arrive sur une branche Subversion spécifique en les démarrant sur le commit de cette branche importée depuis Subversion.
Si vous voulez une branche opera
sur laquelle travailler séparément, vous pouvez lancer :
$ git branch opera remotes/origin/opera
à présent, si vous voulez fusionner votre branche opera
dans trunk
(votre branche master
), vous pouvez le faire en réalisant un git merge
normal.
Mais vous devez préciser un message de validation descriptif (via -m
), ou la fusion indiquera simplement « Merge branch opera » au lieu dâun message plus informatif.
Souvenez-vous que bien que vous utilisez git merge
qui facilitera lâopĂ©ration de fusion par rapport Ă Subversion (Git dĂ©tectera automatiquement lâancĂȘtre commun pour la fusion), ce nâest pas un commit de fusion normal de Git.
Vous devrez pousser ces données finalement sur le serveur Subversion qui ne sait pas tracer les commits possédant plusieurs parents.
Donc, ce sera un commit unique qui englobera toutes les modifications de lâautre branche.
AprÚs avoir fusionné une branche dans une autre, il est difficile de continuer à travailler sur cette branche, comme vous le feriez normalement dans Git.
La commande dcommit
qui a Ă©tĂ© lancĂ©e efface toute information sur la branche qui a Ă©tĂ© fusionnĂ©e, ce qui rend faux tout calcul dâantĂ©rioritĂ© pour la fusion.
dcommit
fait ressembler le résultat de git merge
Ă celui de git merge --squash
.
Malheureusement, il nây a pas de moyen efficace de remĂ©dier Ă ce problĂšme â Subversion ne stocke pas cette information et vous serez toujours contraints par ses limitations si vous lâutilisez comme serveur.
Pour Ă©viter ces problĂšmes, le mieux reste dâeffacer la branche locale (dans notre cas, opera
) dĂšs quâelle a Ă©tĂ© fusionnĂ©e dans trunk
.
Commandes Subversion
La boĂźte Ă outil git svn
fournit des commandes de nature Ă faciliter la transition vers Git en mimant certaines commandes disponibles avec Subversion.
Voici quelques commandes qui vous fournissent les mĂȘmes services que Subversion.
Lâhistorique dans le style Subversion
Si vous ĂȘtes habituĂ© Ă Subversion, vous pouvez lancer git svn log
pour visualiser votre historique dans un format SVNÂ :
$ git svn log
------------------------------------------------------------------------
r87 | schacon | 2014-05-02 16:07:37 -0700 (Sat, 02 May 2014) | 2 lines
autogen change
------------------------------------------------------------------------
r86 | schacon | 2014-05-02 16:00:21 -0700 (Sat, 02 May 2014) | 2 lines
Merge branch 'experiment'
------------------------------------------------------------------------
r85 | schacon | 2014-05-02 16:00:09 -0700 (Sat, 02 May 2014) | 2 lines
updated the changelog
Deux choses importantes Ă connaĂźtre sur git svn log
.
PremiÚrement, à la différence de la véritable commande svn log
qui interroge le serveur, cette commande fonctionne hors connexion.
DeuxiÚmement, elle ne montre que les commits qui ont été effectivement remontés sur le serveur Subversion.
Les commits locaux qui nâont pas encore Ă©tĂ© remontĂ©s via dcommit
nâapparaissent pas, pas plus que ceux qui auraient Ă©tĂ© poussĂ©s sur le serveur par des tiers entre-temps.
Cela donne plutĂŽt le dernier Ă©tat connu des commits sur le serveur Subversion.
Annotations SVN
De la mĂȘme maniĂšre que git svn log
simule une commande svn log
dĂ©connectĂ©e, vous pouvez obtenir lâĂ©quivalent de svn annotate
en lançant git svn blame [fichier]
.
Le résultat ressemble à ceci :
$ git svn blame README.txt
2 temporal Protocol Buffers - Google's data interchange format
2 temporal Copyright 2008 Google Inc.
2 temporal https://code.google.com/apis/protocolbuffers/
2 temporal
22 temporal C++ Installation - Unix
22 temporal =======================
2 temporal
79 schacon Committing in git-svn.
78 schacon
2 temporal To build and install the C++ Protocol Buffer runtime and the Protocol
2 temporal Buffer compiler (protoc) execute the following:
2 temporal
Ici aussi, tous les commits locaux dans Git ou ceux poussĂ©s sur Subversion dans lâintervalle nâapparaissent pas.
Information sur le serveur SVN
Vous pouvez aussi obtenir le mĂȘme genre dâinformation que celle fournie par svn info
en lançant git svn info
 :
$ git svn info
Path: .
URL: https://schacon-test.googlecode.com/svn/trunk
Repository Root: https://schacon-test.googlecode.com/svn
Repository UUID: 4c93b258-373f-11de-be05-5f7a86268029
Revision: 87
Node Kind: directory
Schedule: normal
Last Changed Author: schacon
Last Changed Rev: 87
Last Changed Date: 2009-05-02 16:07:37 -0700 (Sat, 02 May 2009)
Comme blame
et log
, cette commande travaille hors connexion et nâest Ă jour quâĂ la derniĂšre date Ă laquelle vous avez communiquĂ© avec le serveur Subversion.
Ignorer ce que Subversion ignore
Si vous clonez un dépÎt Subversion contenant des propriétés svn:ignore
, vous souhaiterez sûrement paramétrer les fichiers .gitignore
en correspondance pour vous Ă©viter de valider accidentellement des fichiers qui ne devraient pas lâĂȘtre.
git svn
dispose de deux commandes pour le faire.
La premiĂšre est git svn create-ignore
qui crée automatiquement pour vous les fichiers .gitignore
prĂȘts pour lâinclusion dans votre prochaine validation.
La seconde commande est git svn show-ignore
qui affiche sur stdout
les lignes nécessaires à un fichier .gitignore
quâil suffira de rediriger dans votre fichier dâexclusion de projet :
$ git svn show-ignore > .git/info/exclude
De cette maniĂšre, vous ne parsemez pas le projet de fichiers .gitignore
.
Câest une option optimale si vous ĂȘtes le seul utilisateur de Git dans une Ă©quipe Subversion et que vos coĂ©quipiers ne veulent pas voir de fichiers .gitignore
dans le projet.
Résumé sur Git-Svn
Les outils git svn
sont utiles si vous ĂȘtes bloquĂ© avec un serveur Subversion pour le moment ou si vous devez travailler dans un environnement de dĂ©veloppement qui nĂ©cessite un serveur Subversion.
Il faut cependant les considérer comme une version estropiée de Git ou vous pourriez rencontrer des problÚmes de conversion qui vous embrouilleront vous et vos collaborateurs.
Pour éviter tout problÚme, essayez de suivre les principes suivants :
-
Gardez un historique Git linéaire qui ne contient pas de commits de fusion issus de
git merge
. -
Rebasez tout travail réalisé en dehors de la branche principale sur celle-ci ; ne la fusionnez pas.
-
Ne mettez pas en place et ne travaillez pas en parallĂšle sur un serveur Git. Si nĂ©cessaire, montez-en un pour accĂ©lĂ©rer les clones pour de nouveaux dĂ©veloppeurs mais nây poussez rien qui nâait dĂ©jĂ une entrĂ©e
git-svn-id
. Vous devriez mĂȘme y ajouter un crochetpre-receive
qui vérifie la présence degit-svn-id
dans chaque message de validation et rejette les remontĂ©es dont un des commits nâen contiendrait pas.
Si vous suivez ces principes, le travail avec un serveur Subversion peut ĂȘtre supportable. Cependant, si le basculement sur un vrai serveur Git est possible, votre Ă©quipe y gagnera beaucoup.
Git et Mercurial
Lâunivers des systĂšmes de gestion de version distribuĂ©s ne se limite pas Ă Git. En fait, il existe de nombreux autres systĂšmes, chacun avec sa propre approche sur la gestion distribuĂ©e des versions. Ă part Git, le plus populaire est Mercurial, et ces deux-ci sont trĂšs ressemblants par de nombreux aspects.
La bonne nouvelle si vous prĂ©fĂ©rez le comportement de Git cĂŽtĂ© client mais que vous devez travailler sur un projet gĂ©rĂ© sous Mercurial, câest que lâon peut utiliser Git avec un dĂ©pĂŽt gĂ©rĂ© sous Mercurial. Du fait que Git parle avec les dĂ©pĂŽts distants au moyen de greffons de protocole distant, il nâest pas surprenant que cette passerelle prenne la forme dâun greffon de protocole distant. Le projet sâappelle git-remote-hg et peut ĂȘtre trouvĂ© Ă lâadresse https://github.com/felipec/git-remote-hg.
git-remote-hg
PremiÚrement, vous devez installer git-remote-hg. Cela revient simplement à copier ce fichier quelque part dans votre chemin de recherche, comme ceci :
$ curl -o ~/bin/git-remote-hg \
https://raw.githubusercontent.com/felipec/git-remote-hg/master/git-remote-hg
$ chmod +x ~/bin/git-remote-hg
âŠen supposant que ~/bin
est présent dans votre $PATH
. git-remote-hg est aussi dépendant de la bibliothÚque Mercurial
pour Python. Si Python est dĂ©jĂ installĂ©, câest aussi simple que :
$ pip install mercurial
Si Python nâest pas dĂ©jĂ installĂ©, visitez https://www.python.org/ et rĂ©cupĂ©rez-le.
La derniĂšre dĂ©pendance est le client Mercurial. Rendez-vous sur https://www.mercurial-scm.org/ et installez-le si ce nâest pas dĂ©jĂ fait.
Maintenant, vous voilĂ prĂȘt. Vous nâavez besoin que dâun dĂ©pĂŽt Mercurial oĂč pousser. Heureusement, tous les dĂ©pĂŽts Mercurial peuvent servir et nous allons donc simplement utiliser le dĂ©pĂŽt "hello world" dont tout le monde se sert pour apprendre Mercurial :
$ hg clone https://selenic.com/repo/hello /tmp/hello
DĂ©marrage
Avec un dĂ©pĂŽt « cĂŽtĂ© serveur » maintenant disponible, dĂ©taillons un flux de travail typique. Comme vous le verrez, ces deux systĂšmes sont suffisamment similaires pour quâil y ait peu de friction.
Comme toujours avec Git, commençons par cloner :
$ git clone hg::/tmp/hello /tmp/hello-git
$ cd /tmp/hello-git
$ git log --oneline --graph --decorate
* ac7955c (HEAD, origin/master, origin/branches/default, origin/HEAD, refs/hg/origin/branches/default, refs/hg/origin/bookmarks/master, master) Create a makefile
* 65bb417 Create a standard "hello, world" program
Notez bien que pour travailler avec un dépÎt Mercurial, on utilise la commande standard git clone
. Câest dĂ» au fait que git-remote-hg travaille Ă un niveau assez bas, en utilisant un mĂ©canisme similaire Ă celui du protocole HTTP/S de Git. Comme Git et Mercurial sont tous les deux organisĂ©s pour que chaque client rĂ©cupĂšre une copie complĂšte de lâhistorique du dĂ©pĂŽt, cette commande rĂ©alise rapidement un clone complet, incluant tout lâhistorique du projet.
La commande log montre deux commits, dont le dernier est pointĂ© par une ribambelle de refs. En fait, certaines dâentre elles nâexistent par vraiment. Jetons un Ćil Ă ce qui est rĂ©ellement prĂ©sent dans le rĂ©pertoire .git
 :
$ tree .git/refs
.git/refs
âââ heads
â  âââ master
âââ hg
â  âââ origin
â  âââ bookmarks
â  â  âââ master
â  âââ branches
â  âââ default
âââ notes
â  âââ hg
âââ remotes
â  âââ origin
â  âââ HEAD
âââ tags
9 directories, 5 files
Git-remote-hg essaie de rendre les choses plus idiomatiquement Git-esques, mais sous le capot, il gÚre la correspondance conceptuelle entre deux systÚmes légÚrement différents. Par exemple, le fichier refs/hg/origin/branches/default
est un fichier Git de références, qui contient le SHA-1 commençant par « ac7955c », qui est le commit pointé par master
. Donc le répertoire refs/hg
est en quelque sorte un faux refs/remotes/origin
, mais il contient la distinction entre les marque-pages et les branches.
Le fichier notes/hg
est le point de départ pour comprendre comment git-remote-hg fait correspondre les empreintes des commits Git avec les IDs de modification de Mercurial. Explorons-le un peu :
$ cat notes/hg
d4c10386...
$ git cat-file -p d4c10386...
tree 1781c96...
author remote-hg <> 1408066400 -0800
committer remote-hg <> 1408066400 -0800
Notes for master
$ git ls-tree 1781c96...
100644 blob ac9117f... 65bb417...
100644 blob 485e178... ac7955c...
$ git cat-file -p ac9117f
0a04b987be5ae354b710cefeba0e2d9de7ad41a9
Donc, refs/notes/hg
pointe sur un arbre qui correspond dans la base de données des objets de Git à une liste des autres objets avec des noms. git-ls-tree
affiche le mode, le type, lâempreinte de lâobjet et le nom de fichier des articles dâun arbre. Quand nous creusons un de ces articles, nous trouvons Ă lâintĂ©rieur un blob appelĂ© « ac9117f » (lâempreinte SHA-1 du commit pointĂ© par master
), avec le contenu « 0a04b98 » (qui est lâID de la modification Mercurial au sommet de la branche default
).
La bonne nouvelle est que nous nâavons quasiment pas Ă nous soucier de tout ceci. Le mode de travail ne sera pas trĂšs diffĂ©rent de celui avec un serveur distant Git.
Il reste une chose à gérer avant de passer à la suite : les fichiers ignore
. Mercurial et Git utilisent un mécanisme trÚs similaire pour cette fonctionnalité, mais il est trÚs probable que vous ne souhaitez pas valider un fichier .gitignore
dans un dĂ©pĂŽt Mercurial. Heureusement, Git dispose dâun moyen dâignorer les fichiers dâun dĂ©pĂŽt local et le format Mercurial est compatible avec Git. Il suffit donc de le copier :
$ cp .hgignore .git/info/exclude
Le fichier .git/info/exclude
se comporte simplement comme un fichier .gitignore
, mais nâest pas inclus dans les commits.
DĂ©roulement
Supposons que nous avons travaillé et validé quelques commits sur la branche master
et que nous sommes prĂȘts Ă pousser ce travail sur un dĂ©pĂŽt distant. Notre dĂ©pĂŽt ressemble actuellement Ă ceci :
$ git log --oneline --graph --decorate
* ba04a2a (HEAD, master) Update makefile
* d25d16f Goodbye
* ac7955c (origin/master, origin/branches/default, origin/HEAD, refs/hg/origin/branches/default, refs/hg/origin/bookmarks/master) Create a makefile
* 65bb417 Create a standard "hello, world" program
Notre branche master
est en avance de deux commits par rapport Ă origin/master
, mais ces deux commits nâexistent que sur notre machine locale. Voyons si quelquâun dâautre a poussĂ© son travail dans le mĂȘme temps :
$ git fetch
From hg::/tmp/hello
ac7955c..df85e87 master -> origin/master
ac7955c..df85e87 branches/default -> origin/branches/default
$ git log --oneline --graph --decorate --all
* 7b07969 (refs/notes/hg) Notes for default
* d4c1038 Notes for master
* df85e87 (origin/master, origin/branches/default, origin/HEAD, refs/hg/origin/branches/default, refs/hg/origin/bookmarks/master) Add some documentation
| * ba04a2a (HEAD, master) Update makefile
| * d25d16f Goodbye
|/
* ac7955c Create a makefile
* 65bb417 Create a standard "hello, world" program
Comme nous avons utilisĂ© lâoption --all
, nous voyons les références « notes » qui sont utilisées en interne par git-remote-hg, mais nous pouvons les ignorer. Le reste était attendu ; origin/master
a avancĂ© dâun commit et notre historique a divergĂ©. Ă la diffĂ©rence dâautres systĂšmes que nous dĂ©crivons dans ce chapitre, Mercurial est capable de gĂ©rer les fusions, donc ce que nous allons faire nâa rien dâextraordinaire.
$ git merge origin/master
Auto-merging hello.c
Merge made by the 'recursive' strategy.
hello.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
$ git log --oneline --graph --decorate
* 0c64627 (HEAD, master) Merge remote-tracking branch 'origin/master'
|\
| * df85e87 (origin/master, origin/branches/default, origin/HEAD, refs/hg/origin/branches/default, refs/hg/origin/bookmarks/master) Add some documentation
* | ba04a2a Update makefile
* | d25d16f Goodbye
|/
* ac7955c Create a makefile
* 65bb417 Create a standard "hello, world" program
Parfait. Nous lançons les tests et tout passe, et nous voilĂ prĂȘts Ă partager notre travail avec lâĂ©quipe :
$ git push
To hg::/tmp/hello
df85e87..0c64627 master -> master
Câest fini ! Si vous inspectez le dĂ©pĂŽt Mercurial, vous verrez que le rĂ©sultat se prĂ©sente comme attendu :
$ hg log -G --style compact
o 5[tip]:4,2 dc8fa4f932b8 2014-08-14 19:33 -0700 ben
|\ Merge remote-tracking branch 'origin/master'
| |
| o 4 64f27bcefc35 2014-08-14 19:27 -0700 ben
| | Update makefile
| |
| o 3:1 4256fc29598f 2014-08-14 19:27 -0700 ben
| | Goodbye
| |
@ | 2 7db0b4848b3c 2014-08-14 19:30 -0700 ben
|/ Add some documentation
|
o 1 82e55d328c8c 2005-08-26 01:21 -0700 mpm
| Create a makefile
|
o 0 0a04b987be5a 2005-08-26 01:20 -0700 mpm
Create a standard "hello, world" program
La modification numérotée 2 a été faite par Mercurial et celles numérotées 3 et 4 ont été faites par git-remote-hg, en poussant les commits réalisés avec Git.
Branches et marque-pages
Git nâa quâun seul type de branche : une rĂ©fĂ©rence qui se dĂ©place quand des commits sont ajoutĂ©s. Dans Mercurial, ce type de rĂ©fĂ©rence est appelĂ© « marque-page » et se comporte de la mĂȘme maniĂšre quâune branche Git.
Le concept de « branche » dans Mercurial est plus contraignant. La branche sur laquelle une modification est rĂ©alisĂ©e est enregistrĂ©e avec la modification, ce qui signifie que cette derniĂšre sera toujours prĂ©sente dans lâhistorique du dĂ©pĂŽt. Voici un exemple dâun commit ajoutĂ© Ă la branche develop
 :
$ hg log -l 1
changeset: 6:8f65e5e02793
branch: develop
tag: tip
user: Ben Straub <ben@straub.cc>
date: Thu Aug 14 20:06:38 2014 -0700
summary: More documentation
Notez la ligne qui commence par « branch ». Git ne peut pas vraiment rĂ©pliquer ce comportement (il nâen a pas besoin ; les deux types de branches peuvent ĂȘtre reprĂ©sentĂ©s par une ref Git), mais git-remote-hg a besoin de comprendre cette diffĂ©rence, puisque quâelle a du sens pour Mercurial.
La création de marque-pages Mercurial est aussi simple que la création de branches Git. Du cÎté Git :
$ git checkout -b featureA
Switched to a new branch 'featureA'
$ git push origin featureA
To hg::/tmp/hello
* [new branch] featureA -> featureA
Câest tout ce qui est nĂ©cessaire. Du cĂŽtĂ© Mercurial, cela ressemble Ă ceci :
$ hg bookmarks
featureA 5:bd5ac26f11f9
$ hg log --style compact -G
@ 6[tip] 8f65e5e02793 2014-08-14 20:06 -0700 ben
| More documentation
|
o 5[featureA]:4,2 bd5ac26f11f9 2014-08-14 20:02 -0700 ben
|\ Merge remote-tracking branch 'origin/master'
| |
| o 4 0434aaa6b91f 2014-08-14 20:01 -0700 ben
| | update makefile
| |
| o 3:1 318914536c86 2014-08-14 20:00 -0700 ben
| | goodbye
| |
o | 2 f098c7f45c4f 2014-08-14 20:01 -0700 ben
|/ Add some documentation
|
o 1 82e55d328c8c 2005-08-26 01:21 -0700 mpm
| Create a makefile
|
o 0 0a04b987be5a 2005-08-26 01:20 -0700 mpm
Create a standard "hello, world" program
Remarquez la nouvelle Ă©tiquette [featureA]
sur la rĂ©vision 5. Elle se comporte exactement comme une branche Git du cĂŽtĂ© Git, avec une exception : vous ne pouvez pas effacer un marque-page depuis le cĂŽtĂ© Git (câest une limitation des greffons de gestion distante).
Vous pouvez travailler aussi sur une branche « lourde » Mercurial : placez une branche dans lâespace de nom branches
 :
$ git checkout -b branches/permanent
Switched to a new branch 'branches/permanent'
$ vi Makefile
$ git commit -am 'A permanent change'
$ git push origin branches/permanent
To hg::/tmp/hello
* [new branch] branches/permanent -> branches/permanent
Voici à quoi ça ressemble du cÎté Mercurial :
$ hg branches
permanent 7:a4529d07aad4
develop 6:8f65e5e02793
default 5:bd5ac26f11f9 (inactive)
$ hg log -G
o changeset: 7:a4529d07aad4
| branch: permanent
| tag: tip
| parent: 5:bd5ac26f11f9
| user: Ben Straub <ben@straub.cc>
| date: Thu Aug 14 20:21:09 2014 -0700
| summary: A permanent change
|
| @ changeset: 6:8f65e5e02793
|/ branch: develop
| user: Ben Straub <ben@straub.cc>
| date: Thu Aug 14 20:06:38 2014 -0700
| summary: More documentation
|
o changeset: 5:bd5ac26f11f9
|\ bookmark: featureA
| | parent: 4:0434aaa6b91f
| | parent: 2:f098c7f45c4f
| | user: Ben Straub <ben@straub.cc>
| | date: Thu Aug 14 20:02:21 2014 -0700
| | summary: Merge remote-tracking branch 'origin/master'
[...]
Le nom de branche « permanent » a été enregistré avec la modification marquée 7.
Du cĂŽtĂ© Git, travailler avec les deux styles de branches revient au mĂȘme : employez les commandes checkout
, commit
, fetch
, merge
, pull
et push
comme vous feriez normalement. Une chose Ă savoir cependant est que Mercurial ne supporte pas la rĂ©Ă©criture de lâhistorique mais seulement les ajouts. Voici Ă quoi ressemble le dĂ©pĂŽt Mercurial aprĂšs un rebasage interactif et une poussĂ©e forcĂ©e :
$ hg log --style compact -G
o 10[tip] 99611176cbc9 2014-08-14 20:21 -0700 ben
| A permanent change
|
o 9 f23e12f939c3 2014-08-14 20:01 -0700 ben
| Add some documentation
|
o 8:1 c16971d33922 2014-08-14 20:00 -0700 ben
| goodbye
|
| o 7:5 a4529d07aad4 2014-08-14 20:21 -0700 ben
| | A permanent change
| |
| | @ 6 8f65e5e02793 2014-08-14 20:06 -0700 ben
| |/ More documentation
| |
| o 5[featureA]:4,2 bd5ac26f11f9 2014-08-14 20:02 -0700 ben
| |\ Merge remote-tracking branch 'origin/master'
| | |
| | o 4 0434aaa6b91f 2014-08-14 20:01 -0700 ben
| | | update makefile
| | |
+---o 3:1 318914536c86 2014-08-14 20:00 -0700 ben
| | goodbye
| |
| o 2 f098c7f45c4f 2014-08-14 20:01 -0700 ben
|/ Add some documentation
|
o 1 82e55d328c8c 2005-08-26 01:21 -0700 mpm
| Create a makefile
|
o 0 0a04b987be5a 2005-08-26 01:20 -0700 mpm
Create a standard "hello, world" program
Les modifications 8, 9 et 10 ont été créées et appartiennent à la branche permanent
mais les anciennes modifications sont toujours prĂ©sentes. Ăa a toutes les chances de perdre vos collĂšgues qui utilisent Mercurial, donc câest Ă Ă©viter Ă tout prix.
Résumé Mercurial
Git et Mercurial sont suffisamment similaires pour que le travail pendulaire entre les deux se passe sans accroc. Si vous Ă©vitez de modifier lâhistorique qui a dĂ©jĂ quittĂ© votre machine (comme il lâest recommandĂ©), vous pouvez tout simplement ignorer que le dĂ©pĂŽt distant fonctionne avec Mercurial.
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 :
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
 :
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 |
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.