Aider un collègue
Dans le précédent atelier pratique, nous avons vu comment nous pouvons récupérer la travail effectué par un collègue sur sa propre branche. Cette manipulation nous permet de faire quelque chose d'inédit : modifier le travail d'un collaborateur sur sa propre branche. Voyons en détail les implications pratiques de cette façon de travailler.
Les cuistots et la sauce
Vous connaissez sans doute le fameux proverbe qui dit que trop de cuistots gâtent la sauce. La raison d'être de Git consiste justement à éviter ce genre de désordre. Continuons donc notre démonstration pratique des précédents ateliers :
$ cd formation-git/atelier-37/
$ ls -l
total 12
drwxrwxr-x. 3 kikinovak kikinovak 4096 Apr 7 09:38 clone-de-charles
drwxrwxr-x. 3 kikinovak kikinovak 4096 Apr 7 09:53 clone-de-paul
drwxrwxr-x. 3 kikinovak kikinovak 4096 Apr 7 08:10 clone-de-stephane
$ cd clone-de-charles/
Stéphane a demandé un coup de main à Charles. Il est en mal d'inspiration pour son poème Renouveau et aimerait bien que Charles lui fasse une suggestion sous forme d'un deuxième quatrain. Charles va donc jeter un œil :
$ git switch renouveau
Switched to branch 'renouveau'
Your branch is up to date with 'origin/renouveau'.
$ cat Renouveau.md
# Renouveau
*Stéphane Mallarmé*
Le printemps maladif a chassé tristement
L'hiver, saison de l'art serein, l'hiver lucide,
Et, dans mon être à qui le sang morne préside
L'impuissance s'étire en un long bâillement.
Charles va éditer le fichier Renouveau.md et ajouter un deuxième
quatrain :
Des crépuscules blancs tiédissent sous mon crâne
Qu'un cercle de fer serre ainsi qu'un vieux tombeau
Et triste, j'erre après un rêve vague et beau,
Par les champs où la sève immense se pavane.
Il ajoute le fichier à l'index et effectue un commit :
Où en sommes-nous maintenant ? Adoptez le réflexe d'utiliser la commande git
status lorsque vous vous posez cette question :
$ git status
On branch renouveau
Your branch is ahead of 'origin/renouveau' by 1 commit.
(use "git push" to publish your local commits)
En langage tam-tam, cela signifie que la branche locale renouveau est
« en avance » d'un commit par rapport à la branche de suivi à
distance origin/renouveau. Là comme ailleurs, les suggestions de Git
s'avèrent pertinentes, et il suffit d'un git push bien senti pour être à
jour :
Notez ici que Git « sait » que la branche locale renouveau
dispose d'une branche de suivi distant correspondante origin/renouveau.
À présent, Stéphane peut songer à récupérer le travail de Charles. Voyons à quoi cela ressemble concrètement.
$ cd ../clone-de-stephane/
$ git status
On branch renouveau
Your branch is up to date with 'origin/renouveau'.
Quoi de neuf ?
Un détail important : Git ne nous dit pas s'il y a du nouveau dans le dépôt public. C'est là un choix de conception du logiciel.
Et très concrètement, c'est aux collaborateurs d'un projet d'aller vérifier de leur côté s'il y a du nouveau :
$ git fetch
remote: Enumerating objects: 12, done.
remote: Counting objects: 100% (12/12), done.
remote: Compressing objects: 100% (9/9), done.
remote: Total 9 (delta 1), reused 8 (delta 0), pack-reused 0
Unpacking objects: 100% (9/9), 1.37 KiB | 1.38 MiB/s, done.
From github.com:kikinovak/poesie-symboliste
45cb7ce..69736f3 renouveau -> origin/renouveau
* [new branch] aurore -> origin/aurore
* [new branch] voyage -> origin/voyage
Peu importe la branche sur laquelle vous vous trouvez, git fetch va
récupérer les nouveautés de toutes les branches de suivi à distance.
Stéphane se trouve bien sur la branche renouveau :
Comment se fait-il alors que pour l'instant, il ne voie pas les modifications apportées par Charles ?
$ cat Renouveau.md
# Renouveau
*Stéphane Mallarmé*
Le printemps maladif a chassé tristement
L'hiver, saison de l'art serein, l'hiver lucide,
Et, dans mon être à qui le sang morne préside
L'impuissance s'étire en un long bâillement.
La réponse à cela est simple et nous sert de base pour comprendre le workflow spécifique à Git :
$ git status
On branch renouveau
Your branch is behind 'origin/renouveau' by 1 commit, and can be fast-forwarded.
(use "git pull" to update your local branch)
Pour une fois, nous allons faire fi de la suggestion de Git qui consisterait à
invoquer git pull. Regardons plutôt ce qu'il nous dit une ligne plus haut.
Your branch is behind 'origin/renouveau' by 1 commit, and can be
fast-forwarded. En d'autres termes, nous pouvons effectuer un fast-forward
merge avec la branche origin/renouveau :
$ git merge origin/renouveau
Updating 45cb7ce..69736f3
Fast-forward
Renouveau.md | 5 +++++
1 file changed, 5 insertions(+)
Cette fois-ci, les modifications apportées par Charles ont bien été récupérées dans le clone de Stéphane :
$ cat Renouveau.md
# Renouveau
*Stéphane Mallarmé*
Le printemps maladif a chassé tristement
L'hiver, saison de l'art serein, l'hiver lucide,
Et, dans mon être à qui le sang morne préside
L'impuissance s'étire en un long bâillement.
Des crépuscules blancs tiédissent sous mon crâne
Qu'un cercle de fer serre ainsi qu'un vieux tombeau
Et triste, j'erre après un rêve vague et beau,
Par les champs où la sève immense se pavane.
Pourquoi s'agit-il d'un fast-forward merge ? Tout simplement parce
que les deux branches renouveau et origin/renouveau n'ont pas divergé
depuis que Charles a ajouté une strophe.
Imaginons maintenant un autre cas de figure, où la fusion se complique un tout
petit peu. Paul travaille sur son clone local, toujours sur la branche
aurore :
$ cd ../clone-de-paul/
$ git switch aurore
Switched to branch 'aurore'
Your branch is up to date with 'origin/aurore'.
Avant de continuer à travailler sur Aurore, il a l'idée de faire en parallèle
une parodie de soi-même. Il crée un fichier Aurore-Parodie.md et l'édite comme
ceci :
# Aurore (parodie)
La félicité sans bornes
De ronfler en ton giron
Se dissipe dès la morne
Apparence des klaxons.
Dans mon âme je recule,
Toutes mes idées se bousculent ;
C'est la première livraison !
À peine sorti des vapes,
Je me lève et je dérape
Sur le fil du téléphon.
Note de la rédaction
Cette parodie est de mon cru. En 1995 je m'étais inscrit à un cours terriblement ennuyeux sur Paul Valéry à la Fac de Lettres de Montpellier. Vu que les smartphones n'existaient pas encore à l'époque, je me suis amusé à ma façon.
Paul ajoute le fichier à l'index et effectue un commit :
Il publie ces modifications :
C'est au tour de Charles. Il veut bien filer un autre coup de main à Paul, mais avant de faire quoi que ce soit, il va d'abord vérifier s'il y a du nouveau :
$ cd ../clone-de-charles/
$ git switch aurore
Switched to branch 'aurore'
Your branch is up to date with 'origin/aurore'.
$ git fetch
remote: Enumerating objects: 4, done.
remote: Counting objects: 100% (4/4), done.
remote: Compressing objects: 100% (3/3), done.
remote: Total 3 (delta 0), reused 3 (delta 0), pack-reused 0
Unpacking objects: 100% (3/3), 508 bytes | 508.00 KiB/s, done.
From github.com:kikinovak/poesie-symboliste
44d5975..a449645 aurore -> origin/aurore
$ git status
On branch aurore
Your branch is behind 'origin/aurore' by 1 commit, and can be fast-forwarded.
(use "git pull" to update your local branch)
Il y a du nouveau sur la branche origin/aurore. Il va donc fusionner cette
branche :
$ git merge origin/aurore
Updating 44d5975..a449645
Fast-forward
Aurore-Parodie.md | 12 ++++++++++++
1 file changed, 12 insertions(+)
create mode 100644 Aurore-Parodie.md
Charles voit apparaître la nouvelle version du poème :
Cette version n'est pas vraiment à son goût, et il préfère ajouter une strophe
au poème original dans le fichier Aurore.md :
Salut ! encore endormies
À vos sourires jumeaux,
Similitudes amies
Qui brillez parmi les mots !
Au vacarme des abeilles
Je vous aurai par corbeilles,
Et sur l'échelon tremblant
De mon échelle dorée,
Ma prudence évaporée
Déjà pose son pied blanc.
Il ajoute cette modification à l'index et effectue un commit :
Il publie cette suggestion :
Pendant que Charles est occupé à faire tout ça, Paul continue à travailler sur son clone local :
Il se dit qu'il a oublié de signer la parodie. Il ouvre le fichier
Aurore-Parodie.md et ajoute l'auteur :
# Aurore (parodie)
*Kiki Novak*
La félicité sans bornes
De ronfler en ton giron
Se dissipe dès la morne
Apparence des klaxons.
Dans mon âme je recule,
Toutes mes idées se bousculent ;
C'est la première livraison !
À peine sorti des vapes,
Je me lève et je dérape
Sur le fil du téléphon.
Il enregistre les modifications et effectue un commit :
Malheureusement, la tentative de publication avec git push se solde par un
échec :
$ git push
To github.com:kikinovak/poesie-symboliste.git
! [rejected] aurore -> aurore (fetch first)
error: failed to push some refs to 'github.com:kikinovak/poesie-symboliste.git'
hint: Updates were rejected because the remote contains work that you do
hint: not have locally. This is usually caused by another repository pushing
hint: to the same ref. You may want to first integrate the remote changes
hint: (e.g., 'git pull ...') before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for details.
Une solution propre consiste ici à récupérer dans un premier temps les nouveautés dans les branches de suivi à distance sans pour autant perturber les branches locales :
$ git fetch
remote: Enumerating objects: 10, done.
remote: Counting objects: 100% (10/10), done.
remote: Compressing objects: 100% (6/6), done.
remote: Total 6 (delta 0), reused 6 (delta 0), pack-reused 0
Unpacking objects: 100% (6/6), 1.19 KiB | 1.19 MiB/s, done.
From github.com:kikinovak/poesie-symboliste
a449645..3b3a59c aurore -> origin/aurore
45cb7ce..69736f3 renouveau -> origin/renouveau
Où en sommes-nous ? Là encore, c'est git status qui va nous aider à nous
repérer :
$ git status
On branch aurore
Your branch and 'origin/aurore' have diverged,
and have 1 and 1 different commits each, respectively.
Paul va tenter de fusionner les deux branches aurore et
origin/aurore :
Cette fois-ci, Git affiche le message de fusion suivant :
Que s'est-il passé ?
Nous obtenons un merge commit pour la simple raison que les deux branches
aurore et origin/aurore ont divergé.
Où en sommes-nous maintenant que la fusion a été effectuée avec succès ?
$ git status
On branch aurore
Your branch is ahead of 'origin/aurore' by 2 commits.
(use "git push" to publish your local commits)
Il ne nous reste plus qu'à prendre Git au pied de la lettre et à rendre tout cela public :
S'il ne fallait retenir que cela
Dans cet atelier pratique, j'ai mis la charrue de la pratique avant les bœufs
de la théorie pour vous faire comprendre par l'exemple que la commande git
pull n'est en somme que la combinaison de git fetch suivi d'un git merge. Autrement
dit (on insiste un peu là) :
git pull=git fetch+git merge
Vous aviez peut-être l'habitude d'utiliser git pull au quotidien. Le hic ici,
c'est que dans certaines situations, beaucoup de choses se passent sous le
capot de manière automagique. Le simple fait de remplacer git pull par la
combinaison de git fetch et git merge permet de reprendre le contrôle sur
tous les détails des opérations, notamment lorsqu'il s'agit de concilier des
branches qui divergent un tant soit peu.
Pour aller plus loin
-
Complétez petit à petit et strophe par strophe l'anthologie de la poésie symboliste.
-
Le texte intégral des trois poèmes est disponible librement sur le web.
-
Endossez successivement le rôle de Charles, de Paul et de Stéphane.
-
Ne vous découragez pas si vous vous tirez dans le pied.
-
Si votre dépôt est dans un piteux état, faites une pause et recommencez le lendemain.
-
À un moment, il va falloir intégrer tout ce travail dans la branche principale
main.
Bonus : un peu de ménage
Une fois que nous avons tout intégré dans la branche main, il nous reste à
faire le ménage dans les branches que nous n'utilisons plus. Vous savez comment
supprimer une branche locale :
La suppression d'une branche de suivi distant n'est pas tout à fait intuitive :
La commande git fetch -p (ou --prune) permet de faire le ménage dans les
branches qui n'ont plus de branche distante correspondante :
La rédaction de cette documentation demande du temps et des quantités significatives de café espresso. Vous appréciez ce site ? Offrez un café au rédacteur en cliquant sur la tasse.

