Aller au contenu

Git : branches et fusions

Une branche est une ligne de développement indépendante : elle permet de travailler sur une fonctionnalité sans toucher à main.

Fenêtre de terminal
git branch # liste les branches locales (* = courante)
git branch -a # locales et distantes
git branch -vv # avec le dernier commit et la branche distante suivie
git switch -c fonction-recherche # crée la branche et s'y place
git switch main # change de branche
git switch - # retour à la branche précédente
git branch fonction-b # crée sans changer
git branch -m ancien nouveau # renomme

git switch est la commande moderne ; git checkout fait la même chose et reste disponible.

Fenêtre de terminal
git switch -c fonction-recherche
# modifications…
git add -p
git commit -m "feat(search): add search endpoint"
git log --oneline --graph --all
Fenêtre de terminal
git switch main
git merge fonction-recherche # intègre la branche dans main
git merge --no-ff fonction-recherche # force un commit de fusion (garde la trace de la branche)
git branch -d fonction-recherche # supprime la branche fusionnée
Type de fusion Résultat
Fast-forward main n’a pas avancé : Git déplace simplement le pointeur, historique linéaire
Commit de fusion Les deux branches ont avancé : Git crée un commit à deux parents

Quand deux branches modifient les mêmes lignes, git merge s’arrête :

CONFLICT (content): Merge conflict in fichier.txt
Automatic merge failed; fix conflicts and then commit the result.

Le fichier contient des marqueurs :

<<<<<<< HEAD
version de la branche courante
=======
version de la branche fusionnée
>>>>>>> fonction-recherche
Fenêtre de terminal
git status # liste les fichiers en conflit
# éditer le fichier : garder la bonne version, supprimer les marqueurs
git add fichier.txt # marquer comme résolu
git commit # termine la fusion
git merge --abort # ou annuler la fusion et revenir à l'état d'avant

Pour les cas complexes : git mergetool, ou git checkout --ours fichier / git checkout --theirs fichier pour choisir une version entière.

rebase rejoue les commits d’une branche au-dessus d’une autre, pour un historique linéaire :

Fenêtre de terminal
git switch fonction-recherche
git rebase main # rejoue les commits de la branche sur le dernier main
git rebase --continue # après résolution d'un conflit
git rebase --abort # annule

Rebase interactif, pour réécrire les derniers commits (regrouper, renommer, supprimer) :

Fenêtre de terminal
git rebase -i HEAD~3
Fenêtre de terminal
git switch main
git cherry-pick a1b2c3d # copie ce commit sur la branche courante
git cherry-pick a1b2c3d..e4f5g6h # une série de commits
Fenêtre de terminal
git tag # liste
git tag v1.0.0 # tag léger
git tag -a v1.0.0 -m "Version 1.0.0" # tag annoté (recommandé : date, auteur, message)
git show v1.0.0
git tag -d v1.0.0 # supprime localement
git switch --detach v1.0.0 # se place sur cette version (lecture)

L’envoi des tags vers un serveur est décrit dans Dépôts distants.

  1. main contient toujours du code qui fonctionne.
  2. Chaque fonctionnalité ou correction est développée dans sa branche (feat/…, fix/…).
  3. La branche est poussée, relue (demande de fusion sur le serveur), puis fusionnée dans main.
  4. La branche est supprimée.
Fenêtre de terminal
git switch main && git pull
git switch -c fix/erreur-connexion
# … commits …
git push -u origin fix/erreur-connexion
Fenêtre de terminal
git log main..fonction-recherche --oneline # commits présents sur la branche et pas sur main
git diff main...fonction-recherche # modifications apportées par la branche
git branch --merged # branches déjà fusionnées dans la branche courante
git branch --no-merged