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
:
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) :
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
:
C'est la même chose que d'utiliser les deux commandes suivantes séquentiellement :
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
:
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
:
Si vous ne précisez pas le nom de la branche à renommer, c'est la branche en cours qui sera renommée :
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 :
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) :
Le contenu du haut, entre<<<<<<< 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
<<<<<<<
et=======
, représente les modifications issues deHEAD
(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.