Git
Chapters ▾ 2nd Edition

3.5 Les branches avec Git - Branches distantes

Branches distantes

Les références distantes sont des références (pointeurs) vers les éléments de votre dépôt distant tels que les branches, les tags, etc…​ Vous pouvez obtenir la liste complète de ces références distantes avec la commade git ls-remote (remote), ou git remote show (remote). Néanmoins, une manière plus courante consiste à tirer parti des branches distantes.

Les branches distantes sont des références (des pointeurs) vers l’état des branches sur votre dépôt distant. Ce sont des branches locales qu’on ne peut pas modifier ; elles sont modifiées automatiquement pour vous lors de communications réseau. Les branches distantes agissent comme des marques-pages pour vous aider à vous souvenir de l’état des branches sur votre dépôt distant lors de votre dernière connexion.

Elles prennent la forme de (distant)/(branche). Par exemple, si vous souhaitiez visualiser l’état de votre branche master sur le dépôt distant origin lors de votre dernière communication, il vous suffirait de vérifier la branche origin/master. Si vous étiez en train de travailler avec un collègue et qu’il avait publié la branche iss53, vous pourriez avoir votre propre branche iss53 ; mais la branche sur le serveur pointerait sur le commit de origin/iss53.

Cela peut être un peu déconcertant, essayons d’éclaircir les choses par un exemple. Supposons que vous avez un serveur Git sur le réseau à l’adresse git.notresociete.com. Si vous clonez à partir de ce serveur, la commande clone de Git le nomme automatiquement origin, tire tout son historique, crée un pointeur sur l’état actuel de la branche master et l’appelle localement origin/master. Git crée également votre propre branche master qui démarre au même endroit que la branche master d’origine, pour que vous puissiez commencer à travailler.

Note
origin n’est pas spécial

De la même manière que le nom de branche master n’a aucun sens particulier pour Git, le nom origin n’est pas spécial. Tandis que master est le nom attribué par défaut à votre branche initiale lorsque vous lancez la commande git init et c’est la seule raison pour laquelle ce nom est utilisé aussi largement, origin est le nom utilisé par défaut pour un dépôt distant lorsque vous lancez git clone. Si vous lancez à la place git clone -o booyah, votre branche distante par défaut s’appellera booyah/master.

Dépôts distant et local après un _clone_.
Figure 30. Dépôts distant et local après un clone

Si vous travaillez sur votre branche locale master et que dans le même temps, quelqu’un publie sur git.notresociete.com et met à jour cette même branche master, alors vos deux historiques divergent. Tant que vous restez sans contact avec votre serveur distant, votre pointeur vers origin/master n’avance pas.

Les travaux locaux et distants peuvent diverger.
Figure 31. Les travaux locaux et distants peuvent diverger

Lancez la commande git fetch origin pour synchroniser vos travaux. Cette commande recherche le serveur hébergeant origin (dans notre cas, git.notresociete.com), y récupère toutes les nouvelles données et met à jour votre base de donnée locale en déplaçant votre pointeur origin/master vers une nouvelle position, plus à jour.

`git fetch` met à jour vos références distantes.
Figure 32. git fetch met à jour vos références distantes

Pour démontrer l’usage de multiples serveurs distants et le fonctionnement des branches distantes pour ces projets distants, supposons que vous avez un autre serveur Git interne qui n’est utilisé que par une équipe de développeurs. Ce serveur se trouve sur git.equipe1.notresociete.com. Vous pouvez l’ajouter aux références distantes de votre projet en lançant la commande git remote add comme nous l’avons décrit au chapitre Les bases de Git. Nommez ce serveur distant equipeun qui sera le raccourci pour l’URL complète.

Ajout d'un nouveau server en tant que référence distante.
Figure 33. Ajout d’un nouveau server en tant que référence distante

Maintenant, vous pouvez lancez git fetch equipeun pour récupérer l’ensemble des informations du serveur distant equipeun que vous ne possédez pas. Comme ce serveur contient déjà un sous-ensemble des données du serveur origin, Git ne récupère aucune donnée mais initialise une branche distante appelée equipeun/master qui pointe sur le même commit que celui vers lequel pointe la branche master de equipeun.

Suivi d'une branche distante `equipeun/master`.
Figure 34. Suivi d’une branche distante equipeun/master

Pousser les branches

Lorsque vous souhaitez partager une branche avec le reste du monde, vous devez la pousser sur un serveur distant sur lequel vous avez accès en écriture. Vos branches locales ne sont pas automatiquement synchronisées sur les serveurs distants — vous devez pousser explicitement les branches que vous souhaitez partager. De cette manière, vous pouvez utiliser des branches privées pour le travail que vous ne souhaitez pas partager et ne pousser que les branches sur lesquelles vous souhaitez collaborer.

Si vous possédez une branche nommée correctionserveur sur laquelle vous souhaitez travailler avec d’autres, vous pouvez la poussez de la même manière que vous avez poussé votre première branche. Lancez git push (serveur distant) (branche) :

$ git push origin correctionserveur
Counting objects: 24, done.
Delta compression using up to 8 threads.
Compressing objects: 100% (15/15), done.
Writing objects: 100% (24/24), 1.91 KiB | 0 bytes/s, done.
Total 24 (delta 2), reused 0 (delta 0)
To https://github.com/schacon/simplegit
 * [new branch]      correctionserveur -> correctionserveur

Il s’agit en quelque sorte d’un raccourci. Git développe automatiquement le nom de branche correctionserveur en refs/heads/correctionserveur:refs/heads/correctionserveur, ce qui signifie "Prendre ma branche locale correctionserveur et la pousser pour mettre à jour la branche distante correctionserveur". Nous traiterons plus en détail la partie refs/heads/ au chapitre Les tripes de Git mais généralement, vous pouvez l’oublier. Vous pouvez aussi lancer git push origin correctionserveur:correctionserveur, qui réalise la même chose — ce qui signifie « Prendre ma branche correctionserveur et en faire la branche correctionserveur distante ». Vous pouvez utiliser ce format pour pousser une branche locale vers une branche distante nommée différemment. Si vous ne souhaitez pas l’appeler correctionserveur sur le serveur distant, vous pouvez lancer à la place git push origin correctionserveur:branchegeniale pour pousser votre branche locale correctionserveur sur la branche branchegeniale sur le dépôt distant.

Note
Ne renseignez pas votre mot de passe à chaque fois

Si vous utilisez une URL en HTTPS, le serveur Git vous demandera votre nom d’utilisateur et votre mot de passe pour vous authentifier. Par défaut, vous devez entrer ces informations sur votre terminal et le serveur pourra alors déterminer si vous être autorisé à pousser.

Si vous ne voulez pas entrer ces informations à chaque fois que vous poussez, vous pouvez mettre en place un "cache d’identification" (credential cache). Son fonctionnement le plus simple consiste à garder ces informations en mémoire pour quelques minutes mais vous pouvez configurer ce délai en lançant la commande git config --global credential.helper cache.

Pour davantage d’informations sur les différentes options de cache d’identification disponibles, vous pouvez vous référer au chapitre Stockage des identifiants.

La prochaine fois qu’un de vos collègues récupère les données depuis le serveur, il récupérera, au sein de la branche distante origin/correctionserveur, une référence vers l’état de la branche correctionserveur sur le serveur :

$ git fetch origin
remote: Counting objects: 7, done.
remote: Compressing objects: 100% (2/2), done.
remote: Total 3 (delta 0), reused 3 (delta 0)
Unpacking objects: 100% (3/3), done.
From https://github.com/schacon/simplegit
 * [new branch]      correctionserveur    -> origin/correctionserveur

Il est important de noter que lorsque vous récupérez une nouvelle branche depuis un serveur distant, vous ne créez pas automatiquement une copie locale éditable. En d’autres termes, il n’y a pas de branche correctionserveur, seulement un pointeur sur la branche origin/correctionserveur qui n’est pas modifiable.

Pour fusionner ce travail dans votre branche de travail actuelle, vous pouvez lancer la commande git merge origin/correctionserveur. Si vous souhaitez créer votre propre branche correctionserveur pour pouvoir y travailler, vous pouvez faire qu’elle repose sur le pointeur distant :

$ git checkout -b correctionserveur origin/correctionserveur
Branch correctionserveur set up to track remote branch correctionserveur from origin.
Switched to a new branch 'correctionserveur'

Cette commande vous fournit une branche locale modifiable basée sur l’état actuel de origin/correctionserveur.

Suivre les branches

L’extraction d’une branche locale à partir d’une branche distante crée automatiquement ce qu’on appelle une "branche de suivi" (tracking branch) et la branche qu’elle suit est appelée "branche amont" (upstream branch). Les branches de suivi sont des branches locales qui sont en relation directe avec une branche distante. Si vous vous trouvez sur une branche de suivi et que vous tapez git push, Git sélectionne automatiquement le serveur vers lequel pousser vos modifications. De même, un git pull sur une de ces branches récupère toutes les références distantes et fusionne automatiquement la branche distante correspondante dans la branche actuelle.

Lorsque vous clonez un dépôt, il crée généralement automatiquement une branche master qui suit origin/master. C’est pourquoi les commandes git push et git pull fonctionnent directement sans autre configuration. Vous pouvez néanmoins créer d’autres branches de suivi si vous le souhaitez, qui suivront des branches sur d’autres dépôts distants ou ne suivront pas la branche master. Un cas d’utilisation simple est l’exemple précédent, en lançant git checkout -b [branche] [nomdistant]/[branche]. C’est une opération suffisamment courante pour que Git propose l’option abrégée --track :

$ git checkout --track origin/correctionserveur
Branch correctionserveur set up to track remote branch correctionserveur from origin.
Switched to a new branch 'correctionserveur'

Pour créer une branche locale avec un nom différent de celui de la branche distante, vous pouvez simplement utiliser la première version avec un nom différent de branche locale :

$ git checkout -b cs origin/correctionserveur
Branch cs set up to track remote branch correctionserveur from origin.
Switched to a new branch 'cs'

À présent, votre branche locale cs poussera vers et tirera automatiquement depuis origin/correctionserveur.

Si vous avez déjà une branche locale et que vous voulez l’associer à une branche distante que vous venez de récupérer ou que vous voulez changer la branche distante que vous suivez, vous pouvez ajouter l’option -u ou --set-upstream-to à la commande git branch à tout moment.

$ git branch -u origin/correctionserveur
Branch correctionserveur set up to track remote branch correctionserveur from origin.
Note
Raccourci vers upstream

Quand vous avez une branche de suivi configurée, vous pouvez faire référence à sa branche amont grâce au raccourci @{upstream} ou @{u}. Ainsi, si vous êtes sur la branche master et sa branche de suivi origin/master, vous pouvez utiliser quelque chose comme git merge @{u} au lieu de git merge origin/master si vous le souhaitez.

Si vous voulez voir quelles branches de suivi vous avez configurées, vous pouvez passer l’option -vv à git branch. Celle-ci va lister l’ensemble de vos branches locales avec quelques informations supplémentaires, y compris quelle est la branche suivie et si votre branche locale est devant, derrière ou les deux à la fois.

$ git branch -vv
  iss53     7e424c3 [origin/iss53: ahead 2] forgot the brackets
  master    1ae2a45 [origin/master] deploying index fix
* correctionserveur f8674d9 [equipe1/correction-serveur-ok: ahead 3, behind 1] this should do it
  test   5ea463a trying something new

Vous pouvez constater ici que votre branche iss53 suit origin/iss53 et est "devant de deux", ce qui signifie qu’il existe deux commits locaux qui n’ont pas été poussés au serveur. On peut aussi voir que la branche master suit origin/master et est à jour. On peut voir ensuite que notre branche correctionserveur suit la branche correction-serveur-ok sur notre serveur equipe1 et est "devant de trois" et "derrière de un", ce qui signifie qu’il existe un commit qui n’a pas été encore intégré localement et trois commits locaux qui n’ont pas été poussés. Finalement, on peut voir que notre branche test ne suit aucune branche distante.

Il est important de noter que ces nombres se basent uniquement sur l’état de votre branche distante la dernière fois qu’elle a été synchronisée depuis le serveur. Cette commande n’effectue aucune recherche sur les serveurs et ne travaille que sur les données locales qui ont été mises en cache depuis ces serveurs. Si vous voulez mettre complètement à jour ces nombres, vous devez préalablement synchroniser (fetch) toutes vos branches distantes depuis les serveurs. Vous pouvez le faire de cette façon : $ git fetch --all; git branch -vv.

Tirer une branche (Pulling)

Bien que la commande git fetch récupère l’ensemble des changements présents sur serveur et qui n’ont pas déjà été rapatriés localement, elle ne modifie en rien votre répertoire de travail. Cette commande récupère simplement les données pour vous et vous laisse les fusionner par vous-même. Cependant, il existe une commande appelée git pull qui consiste essentiellement en un git fetch immédiatement suivi par un git merge dans la plupart des cas. Si vous disposez d’une branche de suivi configurée comme illustré dans le chapitre précédent, soit par une configuration explicite soit en ayant laissé les commandes clone ou checkout les créer pour vous, git pull va examiner quel serveur et quelle branche votre branche courante suit actuellement, synchroniser depuis ce serveur et ensuite essayer de fusionner cette branche distante avec la vôtre.

Il est généralement préférable de simplement utiliser les commandes fetch et merge explicitement plutôt que de laisser faire la magie de git pull qui peut s’avérer source de confusion.

Suppression de branches distantes

Supposons que vous en avez terminé avec une branche distante - disons que vous et vos collaborateurs avez terminé une fonctionnalité et l’avez fusionnée dans la branche master du serveur distant (ou la branche correspondant à votre code stable). Vous pouvez effacer une branche distante en ajoutant l’option --delete à git push. Si vous souhaitez effacer votre branche correctionserveur du serveur, vous pouvez lancer ceci :

$ git push origin --delete correctionserveur
To https://github.com/schacon/simplegit
 - [deleted]         correctionserveur

En résumé, cela ne fait que supprimer le pointeur sur le serveur. Le serveur Git garde généralement les données pour un temps jusqu’à ce qu’un processus de nettoyage (garbage collection) passe. De cette manière, si une suppression accidentelle a eu lieu, les données sont souvent très facilement récupérables.