Une compilation de documentations   { en , fr }

Utilisation de base des branches sous Git

Étiquette:
Créé en:
Auteur:
Xavier Béguin
Version en anglais : Basic use of branches in Git

Afficher la liste des branches existantes

Utilisez simplement git branch sans option pour obtenir la liste des branches existantes dans votre projet Git (c'est la même chose que d'utiliser git branch --list).

$ git branch
  devel
* master

Afficher la branche en cours d'utilisation

Dans l'affichage produit par la commande git branch ci-dessus, la branche marquée d'un astérisque (et affichée en vert dans un terminal) est la branche dans laquelle vous vous trouvez actuellement :

  devel
* master

Pour afficher uniquement la branche en cours, utilisez l'option --show-current :

$ git branch --show-current
master

Sous Git, la branche en cours est rendue spéciale par deux points :

  • le marqueur spécial HEAD pointe vers elle (il se comporte essentiellement comme un nom de branch) ;
  • les fichiers du répertoire de travail sont dans le même état que dans le dernier instantané de cette branche.

Créer une branche

Créer une branche est aussi facile que d'appeler git branch avec le nom de votre nouvelle branche. Cet exemple va créer une branche appelée mabranche :

git branch mabranche

La création d'une nouvelle branche ne change pas la branche en cours. Elle ne fait que déclarer un nouveau pointeur dans le répertoire Git de votre projet qui pointe vers le dernier instantané de la branche en cours.

Basculer vers une autre branche

Pour basculer la branche en cours vers une autre branche, utilisez la commande git checkout avec le nom de la branche ciblée (mabranche dans cet exemple) :

git checkout mabranche

La bascule vers une autre branche va modifier le répertoire de travail de votre projet Git et modifier ses fichiers pour refléter l'état des fichiers tels qu'ils sont dans le dernier instantané de la branche que vous extrayez.

L'autre effet du changement de la branche en cours, hormis le changement des fichiers dans le répertoire de travail, est que le pointeur spécial HEAD va pointer vers la branche extraite (puisqu'il pointe toujours vers l'instantané dont les fichiers apparaissent dans le repértoire de travail).

Puisque Git change les fichiers de votre répertoire de travail, si vous avez des changements qui n'ont pas été enregistrés dans un instantané (commit en anglais) ou dans votre zone de préparation (aussi appelé index, ou encore staging area en anglais), Git ne saura pas quoi en faire. Par défaut, Git refusera alors d'extraire la branche demandée. Vous devrez donc soit enregistrer les changements dans un instantané, soit les mettre de côté avant d'extraire la branche (par exemple à l'aide de la commande git stash).

Créer une nouvelle branche et basculer vers elle

Pour créer une nouvelle branche et basculer immédiatement vers elle, utilisez la commande git checkout -b :

git checkout -b manouvellebranche

C'est la même chose que d'utiliser les deux commandes suivantes séquentiellement :

git branch manouvellebranche
git checkout manouvellebranche

Supprimer une branche

Si vous êtes sûr que vous n'aurez plus besoin d'une branche, vous pouvez la supprimer en utlisant git branch -d :

git branch -d mabranche

La suppression d'une branche qui n'a pas été totlament fusionnée dans une autre peut vous faire perdre des modifications introduites dans des instantanés de cette branche. Git refusera alors par défaut de supprimer la branche qui n'a pas été totalement fusionnée (à moins que vous n'utilisiez l'option -D, à vos risques et périls).

Renommer une branche

Si vous avez besoin de renommer une branche, utilisez git branch -m :

git branch -m vieillebranche nouvellebranche

Si vous ne précisez pas le nom de la branche à renommer, c'est la branche en cours qui sera renommée :

git branch -m nouvellebranche

Fusionner des branches

La fusion de branches est particulièrement facile et efficace sous Git. Pour fusionner une branche appelée mabranche dans la branche en cours, utilisez simplement :

git merge mabranche

En fonction de certaines subtilités (voir ci-dessous), la fusion utilisera soit la stratégie par avance rapide (fast-forward en anglais), soit la stratégie de la fusion à trois sources (three-way merge en anglais). Seule cette dernière produira un instantané appelé instantané de fusion (merge commit en anglais).

De plus, les conflits entre les changements introduits dans les deux branches ne peuvent parfois être pas être résolus automatiquement. Ceci est appelé un conflit de fusion (merge conflict en anglais) qui doit être géré manuellement (voir ci-dessous également).

Fusion par avance rapide

Si le dernier instantané de la branche en cours est un ancêtre direct du dernier instantané de la branche que vous voulez fusionner, Git utilisera la stratégie de l'avance rapide (fast-forward en anglais) pour fusionner les branches, qui consiste à simplement avancer le pointeur de la branche.

Pour illustrer ce type de fusion visuellement, supposez que vous avez une branche master avec trois instantanés A, B et C et une branche mabranche avec deux instantanés supplémentaires D et E: la stratégie d'avance rapide ne peut être appliquée que si le dernier instantané de master, C, fait également partrie de mabranch, comme dans ce shéma:

A---B---C master
         \
          D---E mabranche

Après la fusion, la configuration des instantanés ressemblerait à cela:

A---B---C---D---E master
                ^
                |
             mabranche

Dans cette illustration, après la fusion, master et mabranche pointent toutes les deux, vers le même instantané E.

Voici ci-dessous un exemple d'affichage produit par une fusion par avance rapide (tiré du chapitre 3.2 du Pro Git Book):

$ git checkout master
$ git merge hotfix
Updating f42c576..3a0874c
Fast-forward
 index.html | 2 ++
 1 file changed, 2 insertions(+)

Fusion à trois sources

Si l'instantané de la branche dans laquelle vous êtes actuellement n'est pas un ancêtre direct de la branche que vous fusionnez (en d'autres termes, si l'instantané auquel les historiques des deux branches se rejoignent n'est pas le dernier instantané de la branche en cours), Git devra utiliser la stratégie de la fusion à trois sources (three-way merge en anglais) : il va créer un nouvel instantané appelé un instantané de fusion (merge commit en anglais) qui est particulier par le fait qu'il aura plus d'un parent.

Cette stratégie est utilisée lorsqu'une fusion par avance rapide n'est pas possible, comme c'est le cas dans l'exemple illustré ci-dessous :

A---B---C master
     \
      D---E mabranche

Selon la fusion à trois sources, un nouvel instantané F est créé pour résoudre la fusion de mabranche dans master. La configuration résultante des instantanés ressemblerait à ceci (F est un instantané de fusion) :

A---B---C---F master
     \     /
      D---E mabranche

Voici un exemple d'affichage d'une fusion à trois sources (tirée du chapitre 3.2 du Pro Git Book :

$ git checkout master
Switched to branch 'master'
$ git merge iss53
Merge made by the 'recursive' strategy.
index.html |    1 +
1 file changed, 1 insertion(+)

Git ouvrira par défaut votre éditeur pour vous permettre d'éditer le message de validation par défaut utilisé pour les instantanés de fusion (qui dirait simplement Merge branch 'iss53' dans l'exemple ci-dessus).

Git offre la possibilité de forcer la création d'un instantané de fusion dans tous les cas (même lorsque la stratégie d'avance rapide est possible) grâce à l'option --no-ff de git merge.

À l'inverse, l'option --ff-only peut être utilisée pour refuser d'effectuer une fusion à trois sources : si la fusion ne peut pas être effectuée par avance rapide, git merge refusera d'effectuer la fusion et terminera sur une erreur.

Par défaut, git merge utilise l'option --ff qui effectue la fusion par une avance rapide lorsque c'est possible et crée un instantané de fusion uniquement quand ce n'est pas le cas.

Ces options sont présentées dans la page de manuel de git-merge.

Conflits de fusion

Pour finir, si les branches à fusionner ont modifié d'une manière différente la même partie d'un fichier, Git ne pourra pas décider seul de la version à conserver : il s'agit d'un conflit de fusion (merge conflict en anglais) qui doit être résolu manuellement.

Dans ce cas, Git va mettre la fusion en pause et vous avertir avec un message indiquant qu'un ou plusieurs conflits sont survenus et que vous devez les corriger. La commande git status montrera alors également le ou les fichiers en conflit (désigné par le nom de unmerged paths, littéralement « chemins non fusionnés » en anglais).

Voici un exemple de ce que Git afficherait lorsqu'une fusion résulte en un conflit (exemple encore une fois tiré du chapitre 3.2 du Pro Git Book) :

$ git merge iss53
Auto-merging index.html
CONFLICT (content): Merge conflict in index.html
Automatic merge failed; fix conflicts and then commit the result.

Et voilà ci-dessous un exemple de résultat de git status montrant le fichier en conflit (index.html, ici):

$ git status
On branch master
All conflicts fixed but you are still merging.
  (use "git commit" to conclude merge)

Changes to be committed:

    modified:   index.html

Dans un tel cas, vous devrez:

  • éditer le ou les fichiers en conflit pour choisir quelle version des contenus entrant en conflit vous voulez conserver. Git vous montrera dans chaque fichier les deux versions en utilisant des marqueurs comme dans cet example (toujours tiré du Git Pro Book) :
    <<<<<<< HEAD:index.html
    <div id="footer">contact : email.support@github.com</div>
    =======
    <div id="footer">
     please contact us at support@github.com
    </div>
    >>>>>>> iss53:index.html
    
    Le contenu du haut, entre <<<<<<< et =======, représente les modifications issues de HEAD (c'est à dire la branche en cours), et celui du bas, entre ======= et >>>>>>>, celles issues de la branche que vous fusionez (iss53 dans cet exemple). Vous devez supprimer les marqueurs et ne conserver que le contenu tel que vous voulez le garder (que vous pouvez bien entendu adapter à partir d'une des versions des branches) ;
  • une fois le ou les fichiers en conflit modifié et enregistrés, utilisez git add pour marquer les fichiers comme résolus ;
  • créez un instantané de fusion. Git proposera un message de validation par défaut (en anglais commit message) indiquant la branche fusionnée et le ou les fichiers qui étaient en conflit. Vous pouvez le modifier pour expliquer les choix que vous avez faits. Voici un tel message correspondant à l'exemple donné plus haut :
    Merge branch 'iss53'
    
    Conflicts:
      index.html
    

Une fois l'instantané de fusion enregistré, la fusion est terminée.