git fetch ou git pull : quelle différence et lequel choisir
git fetch se contente de télécharger les nouveaux commits du serveur et de mettre à jour les branches distantes du type origin/main, sans toucher à vos fichiers ni à vos branches. git pull fait la même chose puis intègre immédiatement les modifications dans la branche courante, par merge ou par rebase. Fetch est toujours sans risque ; pull est pratique quand vous êtes prêt à accepter tout de suite les modifications des autres.
La réponse courte
git fetch télécharge les nouveaux commits du serveur et met à jour les références des branches distantes (origin/main, origin/feature-x), mais ne modifie ni votre branche courante ni les fichiers de votre répertoire de travail. git pull, c'est git fetch suivi de l'intégration immédiate de ce qui a été téléchargé dans la branche courante : par merge (par défaut) ou par rebase.
D'où une règle pratique : fetch peut être lancé à tout moment, il ne casse rien. Pull modifie votre branche et peut se terminer par un conflit ; mieux vaut donc le lancer avec un répertoire de travail propre et en sachant ce qui va arriver.
Où vivent les branches distantes
Pour que la différence devienne évidente, il faut comprendre qu'un dépôt local contient deux types de branches. Les branches locales — main, feature-x — c'est vous qui les faites avancer avec vos commits. Les branches de suivi distantes — origin/main — sont des marque-pages : « voilà à quoi ressemblait le serveur lors de la dernière synchronisation ». Impossible de les déplacer à la main ; seules les échanges avec le serveur les mettent à jour : fetch, pull et push.
git branch -a
* main
remotes/origin/HEAD -> origin/main
remotes/origin/main
remotes/origin/feature-x
git status compare votre branche avec le marque-page origin/main, et non avec le serveur réel. Le message « Your branch is up to date with 'origin/main' » peut donc mentir : si vous n'avez pas fait de fetch depuis longtemps, Git ignore tout simplement les nouveaux commits de vos collègues.
Ce que fait git fetch
$ git fetch
remote: Enumerating objects: 7, done.
remote: Counting objects: 100% (7/7), done.
Unpacking objects: 100% (4/4), done.
From github.com:team/project
3f2a1c9..8b7d4e2 main -> origin/main
La dernière ligne dit l'essentiel : la référence origin/main est passée de 3f2a1c9 à 8b7d4e2. Votre main n'a pas bougé. Vous pouvez maintenant examiner tranquillement ce qui est arrivé :
git status # Your branch is behind 'origin/main' by 2 commits
git log main..origin/main --oneline # les commits que vous n'avez pas
git diff main origin/main # ce qui va changer dans les fichiers
Variantes utiles de fetch :
git fetch --all— récupérer les modifications de tous les remotes (utile si vous avezoriginetupstreampour un fork) ;git fetch --prune(-p) — supprimer les marque-pages locaux des branches qui n'existent plus sur le serveur ;git fetch origin main— ne récupérer qu'une seule branche ;git fetch --tags— récupérer en plus tous les tags.
Pour que le nettoyage se fasse systématiquement, activez-le une fois pour toutes : git config --global fetch.prune true.
Ce que fait git pull
git pull enchaîne deux étapes. D'abord un fetch de la branche upstream de la branche courante, puis l'intégration de origin/<branche> dans votre branche. Littéralement, cela équivaut à :
git fetch origin
git merge origin/main # ou git rebase origin/main avec pull --rebase
Le résultat dépend de la façon dont les historiques ont divergé :
- vous n'avez pas de nouveaux commits — c'est un fast-forward, la branche avance simplement ;
- il y a de nouveaux commits chez vous et sur le serveur — avec merge, un commit de fusion est créé ; avec rebase, vos commits sont rejoués par-dessus ceux du serveur ;
- les mêmes lignes ont été modifiées des deux côtés — c'est un conflit à résoudre à la main.
Comparatif git fetch / git pull
| git fetch | git pull | |
|---|---|---|
| Télécharge les commits | Oui | Oui |
| Met à jour origin/* | Oui | Oui |
| Modifie la branche courante | Non | Oui |
| Modifie les fichiers du répertoire de travail | Non | Oui |
| Peut provoquer un conflit | Non | Oui |
| Exige un répertoire de travail propre | Non | De préférence |
| Touche les autres branches | Met à jour tous les marque-pages suivis | N'intègre que dans la branche courante |
| Quand l'utiliser | Voir ce qui a changé ; avant un rebase ; dans les scripts | Rattraper rapidement le serveur sur sa branche |
git pull : merge ou rebase ?
Depuis Git 2.27, en cas d'historique divergent et sans configuration explicite, pull affiche un avertissement ; dans les versions récentes, au lieu d'un merge silencieux, il s'arrête avec l'erreur « Need to specify how to reconcile divergent branches ». Git vous demande de choisir une stratégie une fois pour toutes :
git config --global pull.rebase false # merge (l'ancien comportement par défaut)
git config --global pull.rebase true # rebase
git config --global pull.ff only # fast-forward uniquement, sinon refus
Merge conserve l'historique tel quel et ajoute un commit « Merge branch 'main' of github.com:... ». Si vous faites un pull chaque jour dans une branche contenant des commits locaux, l'historique se remplit de ces fusions techniques.
Rebase rejoue vos commits non poussés par-dessus ceux, tout frais, du serveur. L'historique reste linéaire, et les conflits se résolvent un commit à la fois. Pour des commits locaux non publiés, c'est généralement le meilleur choix. Le rebase n'est dangereux que pour des commits déjà poussés sur lesquels d'autres s'appuient.
ff only est le mode le plus strict : pull ne fonctionne que si vous n'avez aucun commit à vous. Si l'historique a divergé, c'est vous qui décidez explicitement quoi faire. Beaucoup de développeurs expérimentés le choisissent pour les branches principales.
Si votre répertoire de travail contient des modifications non commitées et qu'un pull est nécessaire tout de suite, git pull --rebase --autostash est utile : Git met les modifications de côté, fait le rebase puis les remet en place.
Scénario type : fetch, examiner, intégrer
L'approche « fetch d'abord » vous donne le contrôle sur ce qui entre dans votre branche. Elle est particulièrement utile avant d'ouvrir une pull request et après une longue pause.
git fetch
git log --oneline --graph HEAD origin/main # comment les branches ont divergé
git rebase origin/main # ou git merge origin/main
git push
Autre cas fréquent : mettre à jour votre branche de fonctionnalité avec la main fraîche, sans vous placer dessus :
git switch feature-x
git fetch
git rebase origin/main
Pull ne convient pas ici : un git pull dans la branche de fonctionnalité récupère les modifications de son propre upstream (origin/feature-x), pas de la branche principale. On peut bien sûr écrire git pull --rebase origin main, mais la variante avec fetch est plus lisible.
Synchroniser avec le serveur : garder sa branche à jour
Quand on parle de « git sync », on entend généralement le cycle « récupérer le travail des autres — envoyer le sien ». Git pur n'a pas de commande sync (le bouton Sync existe dans les IDE et clients graphiques, et fait en interne un pull puis un push). À la main, un cycle fiable ressemble à ceci :
git status— vérifier que tout est commité ou mis de côté avecgit stash;git pull --rebase— récupérer les modifications et replacer vos commits au-dessus ;- résoudre les conflits éventuels : corriger les fichiers,
git add,git rebase --continue; - lancer les tests ;
git push.
Pour synchroniser un fork avec le dépôt d'origine :
git remote add upstream https://github.com/original/project.git
git fetch upstream
git switch main
git merge --ff-only upstream/main
git push origin main
Problèmes fréquents avec git pull
Your local changes would be overwritten by merge
Pull veut modifier des fichiers que vous êtes en train d'éditer sans les avoir commités. Options : commiter, mettre de côté (git stash, puis pull et git stash pop) ou utiliser --autostash. Inutile de supprimer vos modifications pour pouvoir faire un pull.
Conflit après un pull
Git s'arrête et liste les fichiers en conflit dans git status. Ouvrez-les, choisissez la bonne version entre les marqueurs <<<<<<< et >>>>>>>, puis git add et git commit (avec merge) ou git rebase --continue (avec rebase). Vous changez d'avis ? git merge --abort ou git rebase --abort remettent tout dans l'état d'avant le pull.
There is no tracking information for the current branch
La branche n'a pas d'upstream configuré, et Git ne sait pas d'où tirer. Précisez-le explicitement : git pull origin main, ou configurez le lien une fois : git branch --set-upstream-to=origin/main.
refusing to merge unrelated histories
Les dépôts local et distant ont été créés indépendamment, par exemple quand un README a été ajouté lors de la création du dépôt sur le serveur. Si vous êtes sûr de vouloir les réunir : git pull origin main --allow-unrelated-histories.
Pull raté : comment revenir en arrière
Si le merge consécutif au pull est déjà terminé et que le résultat ne vous convient pas, ramenez la branche à son état antérieur : git reset --hard ORIG_HEAD. Cette commande supprime les modifications non commitées, vérifiez donc d'abord git status. En dernier recours, l'ancienne position de la branche se retrouve dans git reflog.
Que choisir
- Vous voulez savoir ce qu'il y a de nouveau sans rien modifier —
git fetch. - Vous travaillez sur votre branche et voulez simplement rattraper le serveur —
git pull --rebase(ou pull avecpull.rebase trueconfiguré). - Vous mettez à jour la branche principale sans commits à vous —
git pull --ff-only. - Vous devez intégrer
maindans une branche de fonctionnalité —git fetch, puisgit rebase origin/mainougit merge origin/main. - Vous écrivez un script ou une CI — fetch et des commandes explicites, sans pull.
À quoi cela ressemble sur le graphe des commits
Imaginez que vous et un collègue êtes partis du commit C. Vous avez fait en local le commit D, et votre collègue a poussé E sur le serveur. Après git fetch, votre dépôt connaît les deux lignes : main pointe vers D, origin/main vers E, et leur ancêtre commun est C.
D <- main (HEAD)
/
A---B---C
\
E <- origin/main
Tout dépend ensuite du mode d'intégration. git merge origin/main crée un commit M à deux parents, D et E. git rebase origin/main recopie D au-dessus de E sous la forme d'un nouveau commit D' avec un autre hash, et l'historique devient une ligne droite. git pull exécute simplement ces mêmes étapes automatiquement, sans pause entre elles. Or c'est précisément cette pause — la possibilité de regarder le graphe avant d'intégrer — qui fait tout l'intérêt d'un fetch séparé.
Fetch et pull dans les IDE
Dans VS Code, IntelliJ IDEA et les autres éditeurs, les boutons portent des noms différents, mais cachent les mêmes commandes. « Fetch » correspond à git fetch, « Pull » ou « Update Project » à un pull avec la stratégie choisie dans les paramètres (merge ou rebase), « Sync Changes » à un pull suivi d'un push. Avant de cliquer sur Sync dans une branche partagée, mieux vaut savoir quelle stratégie est configurée, sinon des commits de fusion apparaîtront à l'improviste dans l'historique. Beaucoup d'IDE font aussi un fetch périodique en arrière-plan, si bien que le compteur de commits entrants dans la barre d'état est généralement à jour.
En résumé
git fetch met à jour ce que vous savez du serveur, git pull applique en plus ce savoir à la branche courante. Fetch est sans risque à tout moment ; pull est pratique mais modifie la branche et peut amener un conflit : configurez sa stratégie une fois pour toutes et gardez un répertoire de travail propre. La différence entre push, pull et fetch, le travail avec les remotes et GitHub sont mis en pratique dans le cours Git.
Questions fréquentes
Faut-il faire git fetch avant git pull ?
Non, pull exécute lui-même un fetch en première étape. Un fetch séparé est utile quand vous voulez d'abord examiner les modifications avant de décider comment les intégrer.
git fetch peut-il supprimer mes modifications ?
Non. Fetch ne modifie que les références distantes du type origin/main et ne touche ni aux branches locales, ni à l'index, ni au répertoire de travail.
git pull met-il à jour toutes les branches ?
Non, pull n'intègre les modifications que dans la branche courante. Les marque-pages origin/* des autres branches sont mis à jour grâce au fetch, mais les branches locales elles-mêmes ne bougent pas.
À quelle fréquence faire git fetch ?
Avant de commencer à travailler, avant de créer une pull request et avant un push. Beaucoup d'IDE font un fetch automatique en arrière-plan, et c'est sans danger.
Qu'est-ce que FETCH_HEAD ?
Une référence technique dans laquelle fetch enregistre ce qu'il vient de télécharger. Par exemple, après git fetch origin main, vous pouvez lancer git merge FETCH_HEAD.
Ce sujet est traité en détail avec de la pratique dans le cours « Git de zéro à développeur confirmé ».
Voir le cours