Chapitre 4 sur 5

Tutoriel Git : travailler en équipe avec les branches

vérifié le 7 septembre 2026 · 10 min

Réponse rapide

Créez une branche avec git switch -c nom, travaillez, puis fusionnez-la avec git merge depuis la branche de destination. En cas de conflit, Git insère des marqueurs dans le fichier : écrivez le bon contenu, supprimez les marqueurs, puis git add et git commit. git merge --abort annule tout à n’importe quel moment.

Une branche est une ligne de développement parallèle. Elle vous permet de travailler sur une fonctionnalité sans toucher à la version stable, et à votre collègue d’en faire autant de son côté. Ce chapitre couvre le cycle complet : créer une branche, la fusionner, résoudre un conflit à la main, et choisir entre merge et rebase.

git switch plutôt que git checkout

Historiquement, git checkout servait à tout : changer de branche, en créer une, restaurer un fichier, se placer sur un commit précis. Cette accumulation de rôles est la première source de confusion chez les débutants, et une source d’accidents chez les autres.

Git 2.23, sorti en août 2019, a scindé la commande en deux : git switch pour se déplacer entre les branches, git restore pour annuler des modifications. Elles ont été marquées expérimentales à leur sortie, elles ne le sont plus dans la documentation officielle. Ce chapitre les utilise, et donne systématiquement l’équivalent en checkout, que vous croiserez encore longtemps dans les tutoriels et sur Stack Overflow.

Intention Commande moderne Ancienne forme
Changer de branche git switch nom git checkout nom
Créer une branche et s’y placer git switch -c nom git checkout -b nom
Revenir à la branche précédente git switch - git checkout -
Annuler la modification d’un fichier git restore fichier git checkout -- fichier
Sortir un fichier de l’index git restore --staged fichier git reset HEAD fichier

Créer une branche et y travailler

bash
git switch -c feature/panier
Sortie réelle · git switch -c
Switched to a new branch 'feature/panier'

La branche part du commit sur lequel vous étiez. Vous pouvez maintenant modifier, ajouter et committer normalement : rien de tout cela n’apparaîtra sur main tant que vous ne l’aurez pas fusionné.

Sur les noms de branches, aucune règle n’est imposée par Git, mais les préfixes feature/, fix/ et hotfix/ sont une convention répandue et les interfaces des hébergeurs les regroupent visuellement.

Pour voir où vous en êtes :

bash
git branch              # les branches locales
git branch -vv          # avec le dernier commit et la branche distante suivie
git branch -a           # locales et distantes
git switch -            # revenir à la branche précédente

Pour publier la branche et la rendre visible à l’équipe :

bash
git push -u origin feature/panier

Récupérer la branche d’un collègue

Dans l’autre sens, git fetch met à jour votre connaissance du serveur sans rien modifier dans vos branches :

bash
git fetch origin feature/collegue   # une branche précise
git fetch --all                     # tous les dépôts distants
git branch -r                       # ce que vous connaissez du serveur
Sortie réelle · git branch -r après un fetch
  origin/HEAD -> origin/main
  origin/feature/collegue
  origin/main

Il ne reste plus qu’à basculer dessus. Git crée automatiquement la branche locale et la relie à celle du serveur :

bash
git switch feature/collegue
Sortie réelle · git switch sur une branche distante
branch 'feature/collegue' set up to track 'origin/feature/collegue'.
Switched to a new branch 'feature/collegue'

Quand Git refuse de changer de branche

C’est l’une des premières erreurs que vous rencontrerez :

Sortie réelle · git switch avec des modifications non committées
error: Your local changes to the following files would be overwritten by checkout:
	index.html
Please commit your changes or stash them before you switch branches.
Aborting

Git protège votre travail : le fichier que vous avez modifié n’a pas le même contenu sur l’autre branche, et changer de branche l’écraserait. Trois solutions, par ordre de préférence.

Committer, si le travail est cohérent. C’est presque toujours la bonne réponse, un commit imparfait sur une branche de travail ne coûte rien et se corrige plus tard avec les commandes d’annulation vues au chapitre précédent.

Mettre de côté, si le travail est à moitié fait :

bash
git stash          # met les modifications de côté
git switch main    # …vous faites ce que vous aviez à faire…
git switch -
git stash pop      # récupère les modifications
Sortie réelle · git stash
Saved working directory and index state WIP on main: 6d495d9 Page d accueil

Jeter, avec git restore ., si les modifications ne valaient rien. Sans retour possible.

Fusionner une branche

Une fois la fonctionnalité terminée, placez-vous sur la branche de destination et fusionnez :

bash
git switch main
git merge feature/panier

Quand les deux branches ont modifié des fichiers différents, Git fusionne tout seul et n’a rien à vous demander. Le cas intéressant est l’autre.

Résoudre un conflit

Voici la situation reproduite pour ce chapitre. Sur feature/panier, la deuxième ligne de index.html a été remplacée par un message de panier vide. Sur main, la première ligne a été modifiée pour ajouter le nom de la marque. Les deux branches ont touché le même fichier.

Sortie réelle · git merge feature/panier
Auto-merging index.html
CONFLICT (content): Merge conflict in index.html
Automatic merge failed; fix conflicts and then commit the result.

Rien n’est cassé. Git a fusionné ce qu’il pouvait et vous laisse trancher le reste. Première chose à faire, demander où vous en êtes :

bash
git status
Sortie réelle · git status pendant un conflit
On branch main
Your branch is ahead of 'origin/main' by 1 commit.
  (use "git push" to publish your local commits)

You have unmerged paths.
  (fix conflicts and run "git commit")
  (use "git merge --abort" to abort the merge)

Unmerged paths:
  (use "git add <file>..." to mark resolution)
	both modified:   index.html

no changes added to commit (use "git add" and/or "git commit -a")

Pour n’obtenir que la liste des fichiers à traiter :

bash
git diff --name-only --diff-filter=U

Ouvrez le fichier. Git y a inséré des marqueurs :

index.html pendant le conflit
<<<<<<< HEAD
<h1>Boutique Gekkode</h1>
<p>Bienvenue sur la boutique.</p>
=======
<h1>Boutique</h1>
<p>Votre panier est vide.</p>
>>>>>>> feature/panier

La lecture est mécanique. Entre <<<<<<< HEAD et ======= se trouve la version de la branche où vous êtes, ici main. Entre ======= et >>>>>>> se trouve la version de la branche que vous fusionnez.

À vous d’écrire le résultat correct. Ce n’est pas forcément l’une ou l’autre : ici, les deux modifications sont bonnes et doivent coexister.

index.html après résolution
<h1>Boutique Gekkode</h1>
<p>Votre panier est vide.</p>

Supprimez les trois marqueurs, ils ne doivent pas rester dans le fichier. Puis signalez à Git que c’est réglé, et terminez la fusion :

bash
git add index.html
git commit -m "Fusionne feature/panier dans main"
Sortie réelle · git log --oneline --graph après la fusion
*   0899b0c Fusionne feature/panier dans main
|  
| * aacf4c0 Panier : message quand le panier est vide
* | 11ff16b Ajoute le nom de la marque au titre
|/  
* 6d495d9 Page d accueil

Le commit de fusion a deux parents, ce que le graphe rend visible.

Tout annuler et repartir de zéro

Si le conflit vous dépasse, vous n’êtes obligé à rien :

bash
git merge --abort

Le dépôt revient exactement à son état d’avant la commande merge. Rien n’est perdu, vous pouvez recommencer plus tard ou en discuter avec l’auteur de l’autre branche.

merge ou rebase

Les deux intègrent le travail d’une branche dans une autre, mais pas de la même façon.

git merge crée un commit de fusion qui relie les deux historiques. L’historique conserve la trace exacte de ce qui s’est passé, y compris le fait que deux branches ont existé en parallèle. Le graphe est fidèle, mais il se ramifie.

git rebase rejoue vos commits par-dessus la branche cible, comme si vous aviez travaillé à partir de sa dernière version. L’historique reste une ligne droite, plus facile à lire, mais il est réécrit : vos commits changent d’identifiant.

bash
git switch feature/panier
git rebase main

Un rebase peut rencontrer les mêmes conflits qu’une fusion, commit par commit. La résolution est identique, seule la commande pour continuer diffère :

Sortie réelle · conflit pendant un rebase
Auto-merging index.html
CONFLICT (content): Merge conflict in index.html
error: could not apply 4937109... Promo
hint: Resolve all conflicts manually, mark them as resolved with
hint: "git add/rm <conflicted_files>", then run "git rebase --continue".
hint: You can instead skip this commit: run "git rebase --skip".
hint: To abort and get back to the state before "git rebase", run "git rebase --abort".
hint: Disable this message with "git config set advice.mergeConflict false"
Could not apply 4937109... Promo
bash
git add index.html
git rebase --continue
# ou, pour tout annuler
git rebase --abort

La règle d’or tient en une phrase : ne rebasez jamais une branche que d’autres personnes ont déjà récupérée. Réécrire un historique partagé oblige vos collègues à réparer le leur à la main. Sur votre propre branche de travail, avant de la proposer, le rebase est en revanche parfaitement légitime et donne un historique bien plus lisible.

Le cas quotidien : quelqu’un a poussé avant vous

Vous voulez pousser, et Git refuse :

Sortie réelle · git push refusé
To /root/o.git
 ! [rejected]        main -> main (fetch first)
error: failed to push some refs to '/root/o.git'
hint: Updates were rejected because the remote contains work that you do not

Le serveur a des commits que vous n’avez pas. Vous devez les intégrer d’abord. Et là, sur un dépôt neuf, Git vous pose une question au lieu d’agir :

Sortie réelle · git pull sans stratégie configurée
hint: You have divergent branches and need to specify how to reconcile them.
hint: You can do so by running one of the following commands sometime before
hint: your next pull:
hint:
hint:   git config pull.rebase false  # merge
hint:   git config pull.rebase true   # rebase
hint:   git config pull.ff only       # fast-forward only
hint:

Git refuse de choisir à votre place depuis la version 2.27. Répondez une bonne fois pour toutes, comme proposé au chapitre d’installation :

bash
git config --global pull.rebase true

Le déroulé devient alors celui-ci :

bash
git pull --rebase
git push
Sortie réelle · git pull --rebase puis git log
From /root/o
   622a60b..38b7dc5  main       -> origin/main
Rebasing (1/1)Successfully rebased and updated refs/heads/main.

* 5b45117 Ajoute app.js
* 38b7dc5 Ajoute la doc
* 622a60b Depart

Votre commit a été replacé au-dessus de celui du collègue et l’historique est resté linéaire, sans commit de fusion parasite. C’est le réglage à recommander à une équipe qui débute.

Une mise en garde pour finir : ne cherchez jamais à débloquer un push refusé avec git push --force. Cette commande écrase le travail présent sur le serveur. Si vous devez vraiment forcer, après un rebase de votre propre branche, utilisez git push --force-with-lease, qui refuse d’écraser des commits que vous n’aviez pas vus.

Faire le ménage

Une branche fusionnée n’a plus de raison d’exister. Si elle a été publiée avec -u, poussez d’abord ses derniers commits : Git refuse de supprimer une branche locale en avance sur sa branche distante, même fusionnée dans main.

bash
git push origin feature/panier
git branch -d feature/panier
Sortie réelle · suppression d'une branche fusionnée
Deleted branch feature/panier (was bc2203a).

Sans ce push préalable, le message est explicite :

Sortie réelle · branche locale en avance sur origin
warning: not deleting branch 'feature/panier' that is not yet merged to
         'refs/remotes/origin/feature/panier', even though it is merged to HEAD
error: the branch 'feature/panier' is not fully merged
hint: If you are sure you want to delete it, run 'git branch -D feature/panier'
hint: Disable this message with "git config set advice.forceDeleteBranch false"

Si la branche n’a pas été fusionnée, Git vous arrête, ce qui est un filet de sécurité utile :

Sortie réelle · suppression d'une branche non fusionnée
error: the branch 'feature/promo' is not fully merged
hint: If you are sure you want to delete it, run 'git branch -D feature/promo'
hint: Disable this message with "git config set advice.forceDeleteBranch false"

Pour supprimer aussi la branche sur le serveur, et nettoyer les références locales devenues obsolètes :

bash
git push origin --delete feature/panier
git fetch --prune

git fetch récupère l’état du serveur sans rien fusionner dans vos branches, contrairement à git pull. L’option --prune supprime au passage les branches distantes qui n’existent plus, celles que vos collègues ont fusionnées et effacées.

Vous savez collaborer. Le dernier chapitre traite de l’organisation : quel modèle de branches adopter selon votre équipe.

Erreurs fréquentes

Your local changes would be overwritten by checkout Committez vos modifications, ou mettez-les de côté avec git stash, avant de changer de branche.
You have divergent branches Depuis Git 2.27, git pull refuse de choisir seul entre fusion et rebase. Réglez la question avec git config --global pull.rebase true.
! [rejected] non-fast-forward Le serveur a des commits que vous n’avez pas. Intégrez-les avec git pull --rebase. N’utilisez jamais git push --force pour passer outre : il écrase le travail des autres.
Marqueurs de conflit oubliés Les lignes commençant par <<<<<<<, ======= et >>>>>>> doivent disparaître du fichier avant le git add.
Rebase d’une branche partagée Réécrire un historique que d’autres ont déjà récupéré les oblige à réparer le leur. Ne rebasez que vos propres branches non publiées.
Newsletter

Les nouveaux tests, tutoriels et projets, par e-mail.

Tests reproductibles, code versionné, résultats datés. Jamais de spam.