-
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
5.2 Git distribué - Contribution à un projet
Contribution Ă un projet
La principale difficultĂ© Ă dĂ©crire ce processus rĂ©side dans lâextraordinaire quantitĂ© de variations dans sa rĂ©alisation. Comme Git est trĂšs flexible, les gens peuvent collaborer de diffĂ©rentes façons et ils le font, et il devient problĂ©matique de dĂ©crire de maniĂšre unique comment devrait se rĂ©aliser la contribution Ă un projet. Chaque projet est lĂ©gĂšrement diffĂ©rent. Les variables incluent la taille du corps des contributeurs, le choix du flux de gestion, les accĂšs en validation et la mĂ©thode de contribution externe.
La premiĂšre variable est la taille du corps de contributeurs. Combien de personnes contribuent activement du code sur ce projet et Ă quelle vitesse ? Dans de nombreux cas, vous aurez deux Ă trois dĂ©veloppeurs avec quelques validations par jour, voire moins pour des projets endormis. Pour des sociĂ©tĂ©s ou des projets particuliĂšrement grands, le nombre de dĂ©veloppeurs peut ĂȘtre de plusieurs milliers, avec des centaines ou des milliers de patchs ajoutĂ©s chaque jour. Ce cas est important car avec de plus en plus de dĂ©veloppeurs, les problĂšmes de fusion et dâapplication de patch deviennent de plus en plus courants. Les modifications soumises par un dĂ©veloppeur peuvent ĂȘtre obsolĂštes ou impossibles Ă appliquer Ă cause de changements qui ont eu lieu dans lâintervalle de leur dĂ©veloppement, de leur approbation ou de leur application. Comment dans ces conditions conserver son code en permanence synchronisĂ© et ses patchs valides ?
La variable suivante est le mode de gestion utilisĂ© pour le projet. Est-il centralisĂ© avec chaque dĂ©veloppeur ayant un accĂšs Ă©gal en Ă©criture sur la ligne de dĂ©veloppement principale ? Le projet prĂ©sente-t-il un mainteneur ou un gestionnaire dâintĂ©gration qui vĂ©rifie tous les patchs ? Tous les patchs doivent-ils subir une revue de pair et une approbation ? Faites-vous partie du processus ? Un systĂšme Ă lieutenants est-il en place et doit-on leur soumettre les modifications en premier ?
La variable suivante est la gestion des accĂšs en Ă©criture. Le mode de gestion nĂ©cessaire Ă la contribution au projet est trĂšs diffĂ©rent selon que vous avez ou non accĂšs au dĂ©pĂŽt en Ă©criture. Si vous nâavez pas accĂšs en Ă©criture, quelle est la mĂ©thode prĂ©fĂ©rĂ©e pour la soumission de modifications ? Y a-t-il seulement une politique en place ? Quelle est la quantitĂ© de modifications fournie Ă chaque fois ? Quelle est la pĂ©riodicitĂ© de contribution ?
Toutes ces questions affectent la maniĂšre de contribuer efficacement Ă un projet et les modes de gestion disponibles ou prĂ©fĂ©rables. Je vais traiter ces sujets dans une sĂ©rie de cas dâutilisation allant des plus simples aux plus complexes. Vous devriez pouvoir construire vos propres modes de gestion Ă partir de ces exemples.
Guides pour une validation
Avant de passer en revue les cas dâutilisation spĂ©cifiques, voici un point rapide sur les messages de validation.
La dĂ©finition et lâutilisation dâune bonne ligne de conduite sur les messages de validation facilitent grandement lâutilisation de Git et la collaboration entre dĂ©veloppeurs.
Le projet Git fournit un document qui dĂ©crit un certain nombre de bonnes pratiques pour crĂ©er des commits qui serviront Ă fournir des patchs â le document est accessible dans les sources de Git, dans le fichier Documentation/SubmittingPatches
.
PremiĂšrement, il ne faut pas soumettre de patchs comportant des erreurs dâespace (caractĂšres espace inutiles en fin de ligne ou entrelacement dâespaces et de tabulations).
Git fournit un moyen simple de le vĂ©rifier â avant de valider, lancez la commande git diff --check
qui identifiera et listera les erreurs dâespace.
git diff --check
.En lançant cette commande avant chaque validation, vous pouvez vĂ©rifier que vous ne commettez pas dâerreurs dâespace qui pourraient ennuyer les autres dĂ©veloppeurs.
Ensuite, assurez-vous de faire de chaque validation une modification logiquement atomique.
Si possible, rendez chaque modification digeste â ne codez pas pendant un week-end entier sur cinq sujets diffĂ©rents pour enfin les soumettre tous dans une Ă©norme validation le lundi suivant.
MĂȘme si vous ne validez pas du week-end, utilisez la zone dâindex le lundi pour dĂ©couper votre travail en au moins une validation par problĂšme, avec un message utile par validation.
Si certaines modifications touchent au mĂȘme fichier, essayez dâutiliser git add --patch
pour indexer partiellement des fichiers (cette fonctionnalité est traitée au chapitre Indexation interactive).
LâinstantanĂ© final sera identique, que vous utilisiez une validation unique ou cinq petites validations, Ă condition que toutes les modifications soient intĂ©grĂ©es Ă un moment, donc nâhĂ©sitez pas Ă rendre la vie plus simple Ă vos compagnons dĂ©veloppeurs lorsquâils auront Ă vĂ©rifier vos modifications.
Cette approche simplifie aussi le retrait ou lâinversion ultĂ©rieurs dâune modification en cas de besoin.
Le chapitre RĂ©Ă©crire lâhistorique dĂ©crit justement quelques trucs et astuces de Git pour rĂ©Ă©crire lâhistorique et indexer interactivement les fichiers â utilisez ces outils pour fabriquer un historique propre et comprĂ©hensible.
Le dernier point Ă soigner est le message de validation. Sâhabituer Ă Ă©crire des messages de validation de qualitĂ© facilite grandement lâemploi et la collaboration avec Git. En rĂšgle gĂ©nĂ©rale, les messages doivent dĂ©buter par une ligne unique dâau plus 50 caractĂšres dĂ©crivant concisĂ©ment la modification, suivie dâune ligne vide, suivie dâune explication plus dĂ©taillĂ©e. Le projet Git exige que lâexplication dĂ©taillĂ©e inclue la motivation de la modification en contrastant le nouveau comportement par rapport Ă lâancien â câest une bonne rĂšgle de rĂ©daction. Une bonne rĂšgle consiste aussi Ă utiliser le prĂ©sent de lâimpĂ©ratif ou des verbes substantivĂ©s dans le message. En dâautres termes, utilisez des ordres. Au lieu dâĂ©crire « Jâai ajoutĂ© des tests pour » ou « En train dâajouter des tests pour », utilisez juste « Ajoute des tests pour » ou « Ajout de tests pour ».
Voici ci-dessous un modÚle écrit par Tim Pope :
Court résumé des modifications (50 caractÚres ou moins) avec majuscule
Explication plus détaillée, si nécessaire. Retour à la ligne vers 72
caractÚres. Dans certains contextes, la premiÚre ligne est traitée
comme le sujet d'un courriel et le reste comme le corps. La ligne
vide qui sépare le titre du corps est importante (à moins d'omettre
totalement le corps). Des outils tels que rebase peuvent ĂȘtre gĂȘnĂ©s
si vous les laissez collés.
Ăcrivez votre message de validation en mode impĂ©ratif : "Corrige le
bogue" et non "Bug corrigé" ou "cela corrige le bug". Cette convention
correspond avec les messages de validation générés par les commandes
telles que git merge our git revert.
Paragraphes supplémentaires aprÚs des lignes vides.
- Les listes à puce sont aussi acceptées
- Typiquement, un tiret ou un astérisque précédés d'un espace unique
séparés par des lignes vides mais les conventions peuvent varier
- Utilisez une indentation sur les lignes suivantes.
Si tous vos messages de validation ressemblent à ceci, les choses seront beaucoup plus simples pour vous et les développeurs avec qui vous travaillez.
Le projet Git montre des messages de commit bien formatĂ©s â lancez donc git log --no-merges
dessus pour voir à quoi ressemble un historique de commits avec des messages bien formatés.
Note
|
Faites ce que je dis, pas ce que je fais.
Dans les exemples suivants et Ă travers tout ce livre, par souci de simplification, je ne formaterai pas les messages aussi proprement.
Jâutiliserai plutĂŽt lâoption En rĂ©sumĂ©, faites ce que je dis, pas ce que je fais. |
Cas dâune petite Ă©quipe privĂ©e
Le cas le plus probable que vous rencontrerez est celui du projet privĂ© avec un ou deux autres dĂ©veloppeurs. Par privĂ©, jâentends code source fermĂ© non accessible au public en lecture. Vous et les autres dĂ©veloppeurs aurez accĂšs en poussĂ©e au dĂ©pĂŽt.
Dans cet environnement, vous pouvez suivre une méthode similaire à ce que vous feriez en utilisant Subversion ou tout autre systÚme centralisé.
Vous bĂ©nĂ©ficiez toujours dâavantages tels que la validation hors-ligne et la gestion de branche et de fusion grandement simplifiĂ©e mais les Ă©tapes restent similaires.
La différence principale reste que les fusions ont lieu du cÎté client plutÎt que sur le serveur au moment de valider.
Voyons à quoi pourrait ressembler la collaboration de deux développeurs sur un dépÎt partagé.
Le premier développeur, John, clone le dépÎt, fait une modification et valide localement.
Dans les exemples qui suivent, les messages de protocole sont remplacĂ©s par âŠâ
pour les raccourcir.
# Ordinateur de John
$ git clone john@githost:simplegit.git
Clonage dans 'simplegit'...
...
$ cd simplegit/
$ vim lib/simplegit.rb
$ git commit -am 'Eliminer une valeur par défaut invalide'
[master 738ee87] Eliminer une valeur par défaut invalide
1 files changed, 1 insertions(+), 1 deletions(-)
La deuxiĂšme dĂ©veloppeuse, Jessica, fait la mĂȘme chose. Elle clone le dĂ©pĂŽt et valide une modification :
# Ordinateur de Jessica
$ git clone jessica@githost:simplegit.git
Clonage dans 'simplegit'...
...
$ cd simplegit/
$ vim TODO
$ git commit -am 'Ajouter une tache reset'
[master fbff5bc] Ajouter une tache reset
1 files changed, 1 insertions(+), 0 deletions(-)
à présent, Jessica pousse son travail sur le serveur :
# Ordinateur de Jessica
$ git push origin master
...
To jessica@githost:simplegit.git
1edee6b..fbff5bc master -> master
La derniĂšre ligne de la sortie indique un message de retour utile sur lâopĂ©ration de poussĂ©e.
Le format de base est <ancienne-ref>..<nouvelle-ref> ref-origin â ref-cible
oĂč ancienne-ref
indique la référence précédente, nouvelle-ref
indique la référence actualisée, ref-origin
est le nom de la référence poussée, et ref-cible
est le nom de la référence distante supposément mise à jour.
Vous verrez des sorties similaires dans la discussion qui suit plus bas, dâoĂč cette explication pour mieux comprendre la signification des diffĂ©rents Ă©tats des dĂ©pĂŽts.
Plus de détails sont disponibles dans la documentation pour git-push.
Continuons avec cet exemple. Un peu plus tard, John fait quelques modifications, les valide dans son dĂ©pĂŽt local et essaie de les pousser sur le mĂȘme serveur :
# Ordinateur de John
$ git push origin master
To john@githost:simplegit.git
! [rejected] master -> master (non-fast forward)
error: impossible de pousser des références vers 'john@githost:simplegit.git'
John nâa pas le droit de pousser parce que Jessica a dĂ©jĂ poussĂ© dans lâintervalle. Il est trĂšs important de comprendre ceci si vous avez dĂ©jĂ utilisĂ© Subversion, parce quâil faut remarquer que les deux dĂ©veloppeurs nâont pas modifiĂ© le mĂȘme fichier. Quand des fichiers diffĂ©rents ont Ă©tĂ© modifiĂ©s, Subversion rĂ©alise cette fusion automatiquement sur le serveur alors que Git nĂ©cessite une fusion des modifications locale. John doit rĂ©cupĂ©rer les modifications amont de Jessica et les fusionner avant dâĂȘtre autorisĂ© Ă pousser :
En premiÚre étape, John récupÚre le travail de Jessica (ceci ne fait que récupérer le travail de Jessica, ça ne le fusionne pas encore dans le travail de John) :
$ git fetch origin
...
From john@githost:simplegit
+ 049d078...fbff5bc master -> origin/master
à présent, le dépÎt local de John ressemble à la figure 5-4.
John a une rĂ©fĂ©rence aux modifications que Jessica a poussĂ©es, mais il doit les fusionner dans sa propre branche avant dâĂȘtre autorisĂ© Ă pousser :
$ git merge origin/master
Merge made by recursive.
TODO | 1 +
1 files changed, 1 insertions(+), 0 deletions(-)
Cette fusion se passe sans problĂšme â lâhistorique de commits de John ressemble Ă prĂ©sent Ă ceci :
Maintenant, John peut tester son code pour sâassurer quâil fonctionne encore correctement et peut pousser son travail nouvellement fusionnĂ© sur le serveur :
$ git push origin master
...
To john@githost:simplegit.git
fbff5bc..72bbc59 master -> master
Ă la fin, lâhistorique des commits de John ressemble Ă ceci :
Dans lâintervalle, Jessica a travaillĂ© sur une branche thĂ©matique.
Elle a créé une branche thématique nommée prob54
et réalisé trois validations sur cette branche.
Elle nâa pas encore rĂ©cupĂ©rĂ© les modifications de John, ce qui donne un historique semblable Ă ceci :
Jessica souhaite se synchroniser sur le travail de John. Elle récupÚre donc ses modifications :
# Ordinateur de Jessica
$ git fetch origin
...
From jessica@githost:simplegit
fbff5bc..72bbc59 master -> origin/master
Cette commande tire le travail que John avait poussĂ© dans lâintervalle. Lâhistorique de Jessica ressemble maintenant Ă ceci :
Jessica pense que sa branche thĂ©matique est prĂȘte mais elle souhaite savoir si elle doit fusionner son travail avant de pouvoir pousser.
Elle lance git log
pour sâen assurer :
$ git log --no-merges issue54..origin/master
commit 738ee872852dfaa9d6634e0dea7a324040193016
Author: John Smith <jsmith@example.com>
Date: Fri May 29 16:01:27 2009 -0700
Eliminer une valeur par defaut invalide
La syntaxe prob54..origin/master
est un filtre du journal qui ordonne Ă Git de ne montrer que la liste des commits qui sont sur la seconde branche (dans ce cas origin/master
) et qui ne sont pas sur la premiĂšre (dans ce cas prob54
).
Nous aborderons cette syntaxe en détail dans Plages de commits.
Pour lâinstant, nous pouvons voir dans le rĂ©sultat quâil nây a quâun seul commit crĂ©Ă© par John que Jessica nâa pas fusionnĂ©.
Si elle fusionne origin/master
, ce sera le seul commit qui modifiera son travail local.
Maintenant, Jessica peut fusionner sa branche thématique dans sa branche master
, fusionner le travail de John (origin/master
) dans sa branche master
, puis pousser le résultat sur le serveur.
PremiÚrement (en ayant validé tout le travail sur la branche thématique prob54
), elle rebascule sur sa branche master
pour intégrer son travail :
$ git checkout master
Basculement sur la branche 'master'
Votre branche est en retard sur 'origin/master' de 2 commits, et peut ĂȘtre mise Ă jour en avance rapide.
Elle peut fusionner soit origin/master
soit prob54
en premier â les deux sont en avance, mais lâordre nâimporte pas.
LâinstantanĂ© final devrait ĂȘtre identique quel que soit lâordre de fusion quâelle choisit.
Seul lâhistorique sera lĂ©gĂšrement diffĂ©rent.
Elle choisit de fusionner en premier prob54
 :
$ git merge issue54
Mise Ă jour fbff5bc..4af4298
Avance rapide
LISEZMOI | 1 +
lib/simplegit.rb | 6 +++++-
2 files changed, 6 insertions(+), 1 deletions(-)
Aucun problĂšme nâapparaĂźt.
Comme vous pouvez le voir, câest une simple avance rapide.
Maintenant, Jessica fusionne le travail de John (origin/master
)Â :
$ git merge origin/master
Fusion automatique de lib/simplegit.rb
Merge made by recursive.
lib/simplegit.rb | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
Tout a fusionnĂ© proprement et lâhistorique de Jessica ressemble Ă ceci :
Maintenant origin/master
est accessible depuis la branche master
de Jessica, donc elle devrait ĂȘtre capable de pousser (en considĂ©rant que John nâa pas encore poussĂ© dans lâintervalle) :
$ git push origin master
...
To jessica@githost:simplegit.git
72bbc59..8059c15 master -> master
Chaque dĂ©veloppeur a validĂ© quelques fois et fusionnĂ© les travaux de lâautre avec succĂšs.
Câest un des schĂ©mas les plus simples.
Vous travaillez pendant quelque temps, généralement sur une branche thématique, et fusionnez dans votre branche master
quand elle est prĂȘte Ă ĂȘtre intĂ©grĂ©e.
Quand vous souhaitez partager votre travail, vous récupérez origin/master
et la fusionnez si elle a changé, puis finalement vous poussez le résultat sur la branche master
du serveur.
La séquence correspond à ceci :
Ăquipe privĂ©e importante
Dans le scĂ©nario suivant, nous aborderons les rĂŽles de contributeur dans un groupe privĂ© plus grand. Vous apprendrez comment travailler dans un environnement oĂč des petits groupes collaborent sur des fonctionnalitĂ©s, puis les contributions de chaque Ă©quipe sont intĂ©grĂ©es par une autre entitĂ©.
Supposons que John et Jessica travaillent ensemble sur une premiÚre fonctionnalité, tandis que Jessica et Josie travaillent sur une autre.
Dans ce cas, lâentreprise utilise un mode dâopĂ©ration de type « gestionnaire dâintĂ©gration » oĂč le travail des groupes est intĂ©grĂ© par certains ingĂ©nieurs, et la branche master
du dĂ©pĂŽt principal ne peut ĂȘtre mise Ă jour que par ces ingĂ©nieurs.
Dans ce scénario, tout le travail est validé dans des branches orientées équipe, et tiré plus tard par les intégrateurs.
Suivons le cheminement de Jessica tandis quâelle travaille sur les deux nouvelles fonctionnalitĂ©s, collaborant en parallĂšle avec deux dĂ©veloppeurs diffĂ©rents dans cet environnement.
En supposant quâelle ait clonĂ© son dĂ©pĂŽt, elle dĂ©cide de travailler sur la fonctionA
en premier.
Elle crée une nouvelle branche pour cette fonction et travaille un peu dessus :
# Ordinateur de Jessica
$ git checkout -b fonctionA
Basculement sur la nouvelle branche 'fonctionA'
$ vim lib/simplegit.rb
$ git commit -am 'Ajouter une limite Ă la fonction de log'
[fonctionA 3300904] Ajouter une limite Ă la fonction de log
1 files changed, 1 insertions(+), 1 deletions(-)
Ă ce moment, elle a besoin de partager son travail avec John, donc elle pousse les commits de sa branche fonctionA
sur le serveur.
Jessica nâa pas le droit de pousser sur la branche master
â seuls les intĂ©grateurs lâont â et elle doit donc pousser sur une autre branche pour collaborer avec John :
$ git push -u origin fonctionA
...
To jessica@githost:simplegit.git
* [nouvelle branche] fonctionA -> fonctionA
Jessica envoie un courriel Ă John pour lui indiquer quâelle a poussĂ© son travail dans la branche appelĂ©e fonctionA
et quâil peut lâinspecter.
Pendant quâelle attend le retour de John, Jessica dĂ©cide de commencer Ă travailler sur la fonctionB
avec Josie.
Pour commencer, elle crée une nouvelle branche thématique, à partir de la base master
du serveur :
# Jessica's Machine
$ git fetch origin
$ git checkout -b fonctionB origin/master
Basculement sur la nouvelle branche 'fonctionB'
à présent, Jessica réalise quelques validations sur la branche fonctionB
 :
$ vim lib/simplegit.rb
$ git commit -am 'made the ls-tree function recursive'
[featureB e5b0fdc] made the ls-tree function recursive
1 files changed, 1 insertions(+), 1 deletions(-)
$ vim lib/simplegit.rb
$ git commit -am 'add ls-files'
[featureB 8512791] add ls-files
1 files changed, 5 insertions(+), 0 deletions(-)
Le dépÎt de Jessica ressemble à la figure suivante :
Elle est prĂȘte Ă pousser son travail, mais elle reçoit un mail de Josie indiquant quâune branche avec un premier travail a dĂ©jĂ Ă©tĂ© poussĂ© sur le serveur en tant que fonctionBee
.
Jessica doit dâabord fusionner ces modifications avec les siennes avant de pouvoir pousser sur le serveur.
Elle peut récupérer les modifications de Josie avec git fetch
 :
$ git fetch origin
...
From jessica@githost:simplegit
* [nouvelle branche] fonctionBee -> origin/fonctionBee
Jessica peut Ă prĂ©sent fusionner ceci dans le travail quâelle a rĂ©alisĂ© grĂące Ă git merge
 :
$ git merge origin/fonctionBee
Fusion automatique de lib/simplegit.rb
Merge made by recursive.
lib/simplegit.rb | 4 ++++
1 files changed, 4 insertions(+), 0 deletions(-)
Mais il y a un petit problĂšme â elle doit pousser son travail fusionnĂ© dans sa branche fonctionB
sur la branche fonctionBee
du serveur.
Elle peut le faire en spécifiant la branche locale suivie de deux points (:) suivi de la branche distante à la commande git push
 :
$ git push -u origin fonctionB:fonctionBee
...
To jessica@githost:simplegit.git
fba9af8..cd685d1 fonctionB -> fonctionBee
Cela sâappelle une refspec.
RĂ©fĂ©rez-vous Ă La refspec pour une explication plus dĂ©taillĂ©e des refspecs Git et des possibilitĂ©s quâelles offrent.
Notez lâoption -u
.
Câest un raccourci pour --set-upstream
, qui configure les branches pour faciliter les poussées et les tirages plus tard.
Ensuite, John envoie un courriel Ă Jessica pour lui indiquer quâil a poussĂ© des modifications sur la branche fonctionA
et lui demander de les vérifier.
Elle lance git fetch
pour tirer toutes ces modifications :
$ git fetch origin
...
From jessica@githost:simplegit
3300904..aad881d fonctionA -> origin/fonctionA
Elle peut voir ce qui a été modifié avec git log
 :
$ git log fonctionA..origin/fonctionA
commit aad881d154acdaeb2b6b18ea0e827ed8a6d671e6
Author: John Smith <jsmith@example.com>
Date: Fri May 29 19:57:33 2009 -0700
largeur du log passee de 25 a 30
Finalement, elle fusionne le travail de John dans sa propre branche fonctionA
 :
$ git checkout fonctionA
Basculement sur la branche 'fonctionA'
$ git merge origin/fonctionA
Updating 3300904..aad881d
Avance rapide
lib/simplegit.rb | 10 +++++++++-
1 files changed, 9 insertions(+), 1 deletions(-)
Jessica veut régler quelques détails. Elle valide donc encore et pousse ses changements sur le serveur :
$ git commit -am 'details regles'
[fonctionA ed774b3] details regles
1 files changed, 1 insertions(+), 1 deletions(-)
$ git push
...
To jessica@githost:simplegit.git
3300904..ed774b3 fonctionA -> fonctionA
Lâhistorique des commits de Jessica ressemble Ă prĂ©sent Ă ceci :
Jessica, Josie et John informent les intégrateurs que les branches fonctionA
et fonctionB
du serveur sont prĂȘtes pour une intĂ©gration dans la branche principale.
AprÚs cette intégration dans la branche principale, une synchronisation apportera les commits de fusion, ce qui donnera un historique comme celui-ci :
De nombreux groupes basculent vers Git du fait de cette capacitĂ© Ă gĂ©rer plusieurs Ă©quipes travaillant en parallĂšle, fusionnant plusieurs lignes de dĂ©veloppement trĂšs tard dans le processus de livraison. La capacitĂ© donnĂ©e Ă plusieurs sous-groupes dâĂ©quipes de collaborer au moyen de branches distantes sans nĂ©cessairement impacter le reste de lâĂ©quipe est un grand bĂ©nĂ©fice apportĂ© par Git. La sĂ©quence de travail qui vous a Ă©tĂ© dĂ©crite ressemble Ă la figure suivante :
Projet public dupliqué
Contribuer Ă un projet public est assez diffĂ©rent. Il faut prĂ©senter le travail au mainteneur dâune autre maniĂšre parce que vous nâavez pas la possibilitĂ© de mettre Ă jour directement des branches du projet. Ce premier exemple dĂ©crit un mode de contribution via des serveurs Git qui proposent facilement la duplication de dĂ©pĂŽt. De nombreux sites proposent cette mĂ©thode (dont GitHub, BitBucket, Google Code, repo.or.cz), et de nombreux mainteneurs sâattendent Ă ce style de contribution. Le chapitre suivant traite des projets qui prĂ©fĂšrent accepter les contributions sous forme de patch via courriel.
PremiÚrement, vous souhaiterez probablement cloner le dépÎt principal, créer une nouvelle branche thématique pour le patch ou la série de patchs que seront votre contribution, et commencer à travailler. La séquence ressemble globalement à ceci :
$ git clone (url)
$ cd projet
$ git checkout -b fonctionA
# (travail)
$ git commit
# (travail)
$ git commit
Note
|
Vous pouvez utiliser |
Lorsque votre branche de travail est prĂȘte et que vous ĂȘtes prĂȘt Ă la fournir au mainteneur, rendez-vous sur la page du projet et cliquez sur le bouton « Fork » pour crĂ©er votre propre projet dupliquĂ© sur lequel vous aurez les droits en Ă©criture.
Vous devez alors ajouter lâURL de ce nouveau dĂ©pĂŽt en tant que second dĂ©pĂŽt distant, dans notre cas nommĂ© macopie
 :
$ git remote add macopie <url>
Vous devez pousser votre travail sur ce dépÎt distant.
Câest beaucoup plus facile de pousser la branche sur laquelle vous travaillez sur une branche distante que de fusionner et de pousser le rĂ©sultat sur le serveur.
La raison principale en est que si le travail nâest pas acceptĂ© ou sâil est picorĂ©, vous nâaurez pas Ă faire marche arriĂšre sur votre branche master
(la commande de picorage cherry-pick
est traitée en détail dans Gestion par rebasage et sélection de commit).
Si le mainteneur fusionne, rebase ou picore votre travail, vous le saurez en tirant depuis son dépÎt de toute façon.
En tout cas, vous pouvez pousser votre travail avec :
$ git push -u macopie fonctionA
Une fois votre travail poussé sur votre dépÎt copie, vous devez notifier le mainteneur.
Ce processus est souvent appelĂ© une demande de tirage (pull request) et vous pouvez la gĂ©nĂ©rer soit via le site web â GitHub propose son propre mĂ©canisme qui sera traitĂ© au chapitre GitHub â soit lancer la commande git request-pull
et envoyer manuellement par courriel le résultat au mainteneur de projet.
La commande request-pull
prend en paramĂštres la branche de base dans laquelle vous souhaitez que votre branche thĂ©matique soit fusionnĂ©e et lâURL du dĂ©pĂŽt Git depuis lequel vous souhaitez quâelle soit tirĂ©e, et gĂ©nĂšre un rĂ©sumĂ© des modifications que vous demandez Ă faire tirer.
Par exemple, si Jessica envoie Ă John une demande de tirage et quâelle a fait deux validations dans la branche thĂ©matique quâelle vient de pousser, elle peut lancer ceci :
$ git request-pull origin/master macopie
The following changes since commit 1edee6b1d61823a2de3b09c160d7080b8d1b3a40:
John Smith (1):
ajout d'une nouvelle fonction
are available in the git repository at:
git://githost/simplegit.git fonctionA
Jessica Smith (2):
Ajout d'une limite Ă la fonction de log
change la largeur du log de 25 a 30
lib/simplegit.rb | 10 +++++++++-
1 files changed, 9 insertions(+), 1 deletions(-)
Le rĂ©sultat peut ĂȘtre envoyĂ© au mainteneur â cela lui indique dâoĂč la modification a Ă©tĂ© branchĂ©e, le rĂ©sumĂ© des validations et dâoĂč tirer ce travail.
Pour un projet dont vous nâĂȘtes pas le mainteneur, il est gĂ©nĂ©ralement plus aisĂ© de toujours laisser la branche master
suivre origin/master
et de réaliser vos travaux sur des branches thématiques que vous pourrez facilement effacer si elles sont rejetées.
Garder les thĂšmes de travaux isolĂ©s sur des branches thĂ©matiques facilite aussi leur rebasage si le sommet du dĂ©pĂŽt principal a avancĂ© dans lâintervalle et que vos modifications ne sâappliquent plus proprement.
Par exemple, si vous souhaitez soumettre un second sujet de travail au projet, ne continuez pas à travailler sur la branche thématique que vous venez de pousser mais démarrez-en plutÎt une depuis la branche master
du dépÎt principal :
$ git checkout -b fonctionB origin/master
# (travail)
$ git commit
$ git push macopie fonctionB
# (email au maintainer)
$ git fetch origin
Ă prĂ©sent, chaque sujet est contenu dans son propre silo â similaire Ă une file de patchs â que vous pouvez rĂ©Ă©crire, rebaser et modifier sans que les sujets nâinterfĂšrent ou ne dĂ©pendent les uns des autres, comme ceci :
Supposons que le mainteneur du projet a tirĂ© une poignĂ©e dâautres patchs et essayĂ© par la suite votre premiĂšre branche, mais celle-ci ne sâapplique plus proprement.
Dans ce cas, vous pouvez rebaser cette branche au sommet de origin/master
, résoudre les conflits pour le mainteneur et soumettre de nouveau vos modifications :
$ git checkout fonctionA
$ git rebase origin/master
$ git push -f macopie fonctionA
Cette action rĂ©Ă©crit votre historique pour quâil ressemble Ă Historique des validations aprĂšs le travail sur fonctionA..
Comme vous avez rebasĂ© votre branche, vous devez spĂ©cifier lâoption -f
Ă votre commande pour pousser, pour forcer le remplacement de la branche fonctionA
sur le serveur par la suite de commits qui nâen est pas descendante.
Une solution alternative serait de pousser ce nouveau travail dans une branche différente du serveur (appelée par exemple fonctionAv2
).
Examinons un autre scĂ©nario possible : le mainteneur a revu les modifications dans votre seconde branche et apprĂ©cie le concept, mais il souhaiterait que vous changiez des dĂ©tails dâimplĂ©mentation.
Vous en profiterez pour rebaser ce travail sur le sommet actuel de la branche master
du projet.
Vous démarrez une nouvelle branche à partir de la branche origin/master
courante, y collez les modifications de fonctionB
en rĂ©solvant les conflits, changez lâimplĂ©mentation et poussez le tout en tant que nouvelle branche :
$ git checkout -b fonctionBv2 origin/master
$ git merge --no-commit --squash fonctionB
# (changement d'implémentation)
$ git commit
$ git push macopie fonctionBv2
Lâoption --squash
prend tout le travail de la branche Ă fusionner et le colle dans un commit sans fusion au sommet de la branche extraite.
Lâoption --no-commit
indique Ă Git de ne pas enregistrer automatiquement une validation.
Cela permet de reporter toutes les modifications dâune autre branche, puis de rĂ©aliser dâautres modifications avant de rĂ©aliser une nouvelle validation.
Ă prĂ©sent, vous pouvez envoyer au mainteneur un message indiquant que vous avez rĂ©alisĂ© les modifications demandĂ©es et quâil peut trouver cette nouvelle mouture sur votre branche fonctionBv2
.
Projet public via courriel
De nombreux grands projets ont des procĂ©dures Ă©tablies pour accepter des patchs â il faut vĂ©rifier les rĂšgles spĂ©cifiques Ă chaque projet qui peuvent varier. Comme il existe quelques gros projets Ă©tablis qui acceptent les patchs via une liste de diffusion de dĂ©veloppement, nous allons Ă©clairer cette mĂ©thode dâun exemple.
La mĂ©thode est similaire au cas prĂ©cĂ©dent â vous crĂ©ez une branche thĂ©matique par sĂ©rie de patchs sur laquelle vous travaillez. La diffĂ©rence rĂ©side dans la maniĂšre de les soumettre au projet. Au lieu de dupliquer le projet et de pousser vos soumissions sur votre dĂ©pĂŽt, il faut gĂ©nĂ©rer des versions courriel de chaque sĂ©rie de commits et les envoyer Ă la liste de diffusion de dĂ©veloppement.
$ git checkout -b topicA
# (travail)
$ git commit
# (travail)
$ git commit
Vous avez à présent deux commits que vous souhaitez envoyer à la liste de diffusion.
Vous utilisez git format-patch
pour générer des fichiers au format mbox que vous pourrez envoyer à la liste.
Cette commande transforme chaque commit en un message courriel dont le sujet est la premiĂšre ligne du message de validation et le corps contient le reste du message plus le patch correspondant.
Un point intĂ©ressant de cette commande est quâappliquer le patch Ă partir dâun courriel formatĂ© avec format-patch
prĂ©serve toute lâinformation de validation.
$ git format-patch -M origin/master
0001-Ajout-d-une-limite-la-fonction-de-log.patch
0002-change-la-largeur-du-log-de-25-a-30.patch
La commande format-patch
affiche les noms de fichiers de patch créés.
Lâoption -M
indique Ă Git de suivre les renommages.
Le contenu des fichiers ressemble à ceci :
$ cat 0001-Ajout-d-une-limite-la-fonction-de-log.patch
From 330090432754092d704da8e76ca5c05c198e71a8 Mon Sep 17 00:00:00 2001
From: Jessica Smith <jessica@example.com>
Date: Sun, 6 Apr 2008 10:17:23 -0700
Subject: [PATCH 1/2] Ajout d'un limite Ă la fonction de log
Limite la fonctionnalité de log aux 20 premiÚres lignes
---
lib/simplegit.rb | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/lib/simplegit.rb b/lib/simplegit.rb
index 76f47bc..f9815f1 100644
--- a/lib/simplegit.rb
+++ b/lib/simplegit.rb
@@ -14,7 +14,7 @@ class SimpleGit
end
def log(treeish = 'master')
- command("git log #{treeish}")
+ command("git log -n 20 #{treeish}")
end
def ls_tree(treeish = 'master')
--
2.1.0
Vous pouvez maintenant Ă©diter ces fichiers de patch pour ajouter plus dâinformations Ă destination de la liste de diffusion mais que vous ne souhaitez pas voir apparaĂźtre dans le message de validation.
Si vous ajoutez du texte entre la ligne ---
et le début du patch (la ligne diff --git
), les dĂ©veloppeurs peuvent le lire mais lâapplication du patch ne le prend pas en compte.
Pour envoyer par courriel ces fichiers, vous pouvez soit copier leur contenu dans votre application de courriel, soit lâenvoyer via une ligne de commande.
Le copier-coller cause souvent des problĂšmes de formatage, spĂ©cialement avec les applications « intelligentes » qui ne prĂ©servent pas les retours Ă la ligne et les types dâespace.
Heureusement, Git fournit un outil pour envoyer correctement les patchs formatés via IMAP, la méthode la plus facile.
Je dĂ©montrerai comment envoyer un patch via Gmail qui sâavĂšre ĂȘtre la boĂźte mail que jâutilise ; vous pourrez trouver des instructions dĂ©taillĂ©es pour de nombreuses applications de mail Ă la fin du fichier susmentionnĂ© Documentation/SubmittingPatches
du code source de Git.
PremiÚrement, il est nécessaire de paramétrer la section imap
de votre fichier ~/.gitconfig
.
Vous pouvez positionner ces valeurs séparément avec une série de commandes git config
, ou vous pouvez les ajouter manuellement.
à la fin, le fichier de configuration doit ressembler à ceci :
[imap]
folder = "[Gmail]/Drafts"
host = imaps://imap.gmail.com
user = utilisateur@gmail.com
pass = x67Nrs,/V:Xt84N
port = 993
sslverify = false
Si votre serveur IMAP nâutilise pas SSL, les deux derniĂšres lignes ne sont probablement pas nĂ©cessaires et le paramĂštre host
commencera par imap://
au lieu de imaps://
.
Quand câest fait, vous pouvez utiliser la commande git imap-send
pour placer la série de patchs dans le répertoire Drafts du serveur IMAP spécifié :
$ cat *.patch | git imap-send
Resolving imap.gmail.com... ok
Connecting to [74.125.142.109]:993... ok
Logging in...
sending 2 messages
100% (2/2) done
Ă ce stade, vous devriez ĂȘtre capable dâaller dans votre dossier « Brouillons », remplacer le champ « Destinataire » par la liste de diffusion Ă laquelle vous envoyez le patch, peut-ĂȘtre mettre en copie le mainteneur ou la personne responsable de cette section, et lâenvoyer.
Vous pouvez aussi envoyer les patchs via un serveur SMTP.
Comme précédemment, vous pouvez définir chaque valeur séparément avec une serie de commandes git config
, ou vous pouvez les ajouter manuellement dans la section « sendmail » dans votre fichier ~/.gitconfig
 :
[sendemail]
smtpencryption = tls
smtpserver = smtp.gmail.com
smtpuser = user@gmail.com
smtpserverport = 587
AprĂšs que ceci soit fait, vous pouvez utiliser git send-email
pour envoyer vos patchs :
$ git send-email *.patch
0001-Ajout-d-une-limite-la-fonction-de-log.patch
0002-change-la-largeur-du-log-de-25-a-30.patch
Who should the emails appear to be from? [Jessica Smith <jessica@example.com>]
Emails will be sent from: Jessica Smith <jessica@example.com>
Who should the emails be sent to? jessica@example.com
Message-ID to be used as In-Reply-To for the first email? y
Ensuite, Git crache un certain nombre dâinformations qui ressemblent Ă ceci pour chaque patch Ă envoyer :
(mbox) Adding cc: Jessica Smith <jessica@example.com> from
\line 'From: Jessica Smith <jessica@example.com>'
OK. Log says:
Sendmail: /usr/sbin/sendmail -i jessica@example.com
From: Jessica Smith <jessica@example.com>
To: jessica@example.com
Subject: [PATCH 1/2] added limit to log function
Date: Sat, 30 May 2009 13:29:15 -0700
Message-Id: <1243715356-61726-1-git-send-email-jessica@example.com>
X-Mailer: git-send-email 1.6.2.rc1.20.g8c5b.dirty
In-Reply-To: <y>
References: <y>
Result: OK
Astuce
|
Pour plus dâaide sur comment configurer votre systĂšme et votre courriel, plus de trucs et astuces, et un bac Ă sable pour faire ses essais dâenvoi de rustines par courriel, rendez-vous sur git-send-email.io. |
Résumé
Ce chapitre a traitĂ© quelques-unes des mĂ©thodes communes de gestion de types diffĂ©rents de projets Git, et discutĂ© des diffĂ©rences entre travailler dans une petite Ă©quipe sur des projets en source fermĂ© et sur un gros projet public. Vous savez comment vĂ©rifier les erreurs dâespaces avant de valider et aussi comment Ă©crire des messages de validation sĂ©rieux. Vous avez appris Ă formater des rustines et les envoyer par courriel Ă une liste de diffusion de dĂ©veloppeurs. La gestion des fusions a Ă©tĂ© abordĂ©e dans les contextes des diffĂ©rents modes de gestion. Vous ĂȘtre bien prĂ©parĂ© Ă collaborer sur de nombreux projets.
Dans la section suivante, nous allons voir comment travailler de lâautre cĂŽtĂ© de la barriĂšre : en tant que mainteneur de projet Git. Vous apprendrez comment travailler comme dictateur bienveillant ou gestionnaire dâintĂ©gration.