Synchroniser un fork Git avec l'upstream : 3 méthodes sûres

Synchroniser un fork git avec l'upstream de 3 façons : pull en deux commandes, rebase pour un historique propre, bouton GitHub — et les correctifs qui marchent.

HUMANpar @mrsaynothing50d7 min de lecture

TL;DR : lance git fetch upstream && git merge upstream/main && git push origin main et ton fork est à jour. C'est tout le workflow « synchroniser un fork avec l'upstream » en une ligne — récupérer les changements du projet forké, puis les pousser vers ta copie. Si tu préfères un historique linéaire, remplace merge par git rebase upstream/main et force le push. Et si tu n'as jamais câblé le remote upstream du tout, commence par l'étape 1 plus bas : ce remote manquant est la cause numéro un d'un fork qui « refuse de se synchroniser ». Tout le reste — rebase, bouton de sync GitHub, branches divergées qui refusent de se pousser — n'est que du détail par-dessus ces trois commandes.

Que veut dire synchroniser un fork avec l'upstream ?

Un fork, c'est ta copie du dépôt de quelqu'un d'autre sur GitHub. L'original, c'est l'upstream ; ta copie, c'est l'origin. Les forks GitHub ne se mettent pas à jour tout seuls — quand les mainteneurs mergent une pull request, ta copie garde le code d'hier. Synchroniser un fork, c'est tirer les nouveaux commits de l'upstream dans ton fork pour que ta branche égale — ou contienne au minimum — l'état courant du projet.

Deux raisons d'y tenir. D'abord les contributions : chaque pull request ouverte depuis un fork périmé traîne du bruit en plus, et les mainteneurs te demanderont de mettre à jour avant de merger. Ensuite l'auto-hébergement ou l'étude : si tu fais tourner un fork en production ou si tu lis simplement le code, un fork d'un mois de retard, c'est un mois de corrections de bugs que tu n'as pas.

Comment synchroniser un fork avec l'upstream en ligne de commande ?

Trois étapes : déclarer l'upstream une fois, récupérer depuis lui, puis merger et pousser. Le câblage est permanent — les étapes 2 et 3 suffisent la prochaine fois.

Étape 1 — ajouter le remote upstream (une fois par clone).

# dans ton clone local du fork
git remote add upstream https://github.com/ORIGINAL_OWNER/REPO.git
git remote -v   # vérifie : origin -> ton fork, upstream -> l'original

La bonne URL se trouve sur la page du dépôt d'origine : le bouton vert Code. L'erreur classique consiste à pointer les deux remotes vers ton fork — là, une « synchro » ne fait silencieusement rien, parce que tu as récupéré depuis une copie périmée au même titre que la tienne.

Étape 2 — récupérer et merger la branche upstream.

git checkout main
git fetch upstream
git merge upstream/main
git push origin main

C'est la réponse standard à « synchroniser un fork git avec l'upstream en ligne de commande ». Un fast-forward est l'issue normale — ton main n'avait rien de neuf, il glisse simplement vers upstream/main et aucun commit de merge n'est créé.

Étape 3 — répéter à la demande. Rien à retenir au-delà de git fetch upstream && git merge upstream/main && git push origin main. Pour voir ton retard avant de merger, lance git rev-list --count main..upstream/main après le fetch.

Faut-il rebaser ou merger pour synchroniser un fork ?

Les deux arrivent au même code dans ton fork ; ils diffèrent par l'historique qu'ils laissent derrière eux. Choisis une politique par dépôt et tiens-la :

Méthode Commande Historique obtenu Idéal pour
Merge git merge upstream/main Un commit de merge en plus sur les branches divergées Branches de fonctionnalité avec des PR ouvertes — ne réécrit jamais rien
Rebase git rebase upstream/main Tes commits rejoués par-dessus, historique linéaire Garder le main du fork propre ; forks divergés à remettre d'aplomb
GitHub UI Bouton Sync branch / merge de PR Identique au merge Rattrapage rapide sans clone ouvert

La variante rebase de la synchro :

git fetch upstream
git rebase upstream/main
git push --force-with-lease origin main

Le force push est obligatoire parce que rebaser réécrit les IDs de commits — la branche distante de ton fork ne descend plus de ta branche locale. Préfère toujours --force-with-lease à --force : il refuse d'écraser le remote si quelqu'un (ou une autre de tes machines) a poussé entre-temps, ce qui rend la commande dangereuse sûre par défaut.

Une règle à se faire tatouer au poignet : ne rebase jamais une branche qui porte une pull request ouverte, sauf à savoir exactement ce que tu fais — le rebase change les IDs de commits, ce qui peut détacher une PR ouverte de ses commits. Synchronise main en merge (ou rebase-la avant de commencer du nouveau travail), et tiens les branches de PR hors de tout ça.

Pourquoi mon fork refuse-t-il de se synchroniser ?

Les quatre suspects habituels, dans l'ordre où ils apparaissent dans les vrais terminaux :

  1. Pas de remote upstream — git remote -v ne montre que origin. Symptôme : git fetch upstream échoue avec 'upstream' does not appear to be a git repository. Correctif : l'étape 1 ci-dessus.
  2. Tu as fetché sans merger — le fetch met à jour upstream/main dans ton dépôt local mais ne touche aucune branche de travail. Symptôme : git log a l'air vieux après un fetch réussi. Correctif : git merge upstream/main.
  3. Historiques divergés — tu as commité sur le main de ton fork, et l'upstream a bougé aussi. git pull se plaint alors d'histoires sans rapport ou force un merge. Correctif, si tu veux que l'upstream gagne : git reset --hard upstream/main (jette tes commits locaux restés sur main — vérifie git stash list ou sauvegarde avec une branche d'abord ; si le mauvais reset est déjà fait, la voie de récupération est la même que dans Git : annuler le dernier commit : git reflog connaît toujours l'ancienne pointe).
  4. Push rejeté en non-fast-forward après un rebase — tu as rebasé mais poussé normalement. Correctif : git push --force-with-lease origin main.

Un cinquième cas, rare : le dépôt upstream a été renommé ou supprimé, et même l'URL de l'étape 1 renvoie 404. GitHub redirige les dépôts renommés, donc un échec franc signifie en général suppression ou passage en privé — plus rien à quoi synchroniser.

Peut-on synchroniser un fork depuis le site GitHub ?

Oui. Sur la page de ton fork, le sélecteur de branche affiche un bouton Sync fork dès que ta branche est en retard ; un clic tire l'upstream. En dessous, la même chose se fait en pull request : ouvre une PR de upstream/main vers le main de ton fork et merge-la.

Les limites du bouton disent quand repasser au CLI : il ne fait que fast-forward ou merge — pas de rebase, et il refuse net quand les branches ont divergé, en t'invitant à abandonner des commits ou à passer en ligne de commande. Il ne synchronise que la branche par défaut. Au-delà d'un simple rattrapage, les trois commandes ci-dessus restent l'outil.

À quelle fréquence synchroniser ton fork ?

Avant chaque nouveau travail, c'est la réponse honnête : branche depuis un main frais, et aucune PR que tu ouvres ne commence par « c'est basé sur une version d'il y a trois semaines ». Pour les forks que tu alimentes activement, une synchro quotidienne ou par session de main coûte quelques secondes. Pour un fork que tu ne fais que lire ou déployer, synchronise quand l'upstream livre quelque chose qui t'intéresse — abonne-toi au flux des releases du dépôt d'origine et synchronise à chaque release. La synchro ne coûte rien justement parce qu'elle est routinière ; un fork à six mois de retard a souvent besoin de chirurgie plutôt que d'un merge, et c'est ainsi que « synchronise mon fork » devient un après-midi entier.

L'anti-sèche

# setup initial (une fois)
git remote add upstream https://github.com/ORIGINAL_OWNER/REPO.git

# synchro courante (politique merge)
git fetch upstream && git merge upstream/main && git push origin main

# synchro courante (politique rebase, historique linéaire)
git fetch upstream && git rebase upstream/main && git push --force-with-lease origin main

# quel est mon retard ?
git fetch upstream && git rev-list --count main..upstream/main

# divergé au-delà du rattrapage — aligner main sur l'upstream (destructif)
git fetch upstream && git reset --hard upstream/main && git push --force-with-lease origin main

Garde la routine à deux commandes dans ta mémoire musculaire et le fork divergé restera une curiosité qu'on lit, pas un problème qu'on répare. Si ton ménage git s'étend aux serveurs, le mémo journalctl couvre l'autre moitié du travail : garder l'historique d'une machine lisible.