Tutoriel

git push : comment envoyer ses modifications vers un dépôt distant

Mis à jour: · Skillaria.Top

git push envoie les commits locaux de la branche courante vers le dépôt distant et y déplace le pointeur de la branche. La première fois, on publie la branche avec git push -u origin nom-de-branche, ensuite git push suffit. Si le serveur contient des commits d'autres personnes, il faut d'abord les récupérer avec git pull plutôt que de forcer le push.

Ce que fait git push

La commande git push prend les commits de votre branche locale qui ne sont pas encore sur le serveur, les transmet au dépôt distant (en général nommé origin) et y déplace le pointeur de la branche sur votre dernier commit. Les fichiers du répertoire de travail et les modifications non commitées ne partent nulle part : seul l'historique, c'est-à-dire les commits, est envoyé.

Il faut bien comprendre que push n'est pas une « synchronisation ». Il fonctionne dans un seul sens : du dépôt local vers le dépôt distant. Pour récupérer les changements des autres, il faut git fetch ou git pull. Confondre ces deux sens est à l'origine de presque tous les problèmes que les débutants soumettent à leur mentor.

Autre règle de Git : par défaut, un push n'est accepté qu'en « avance rapide » (fast-forward). Le serveur accepte vos commits s'ils prolongent l'historique déjà présent sur le serveur. Si quelqu'un a poussé ses commits avant vous, votre push sera refusé — et c'est une protection, pas un bug.

Syntaxe de la commande

git push [<remote>] [<branche-locale>[:<branche-distante>]]

Si vous lancez git push sans argument, Git prend la branche courante et l'envoie vers la branche définie comme upstream (branche suivie). La forme explicite est utile quand l'upstream n'est pas encore configuré ou que vous voulez publier la branche sous un autre nom :

git push origin main                  # envoyer la main locale vers origin/main
git push origin feature/login         # envoyer la branche feature/login
git push origin fix:hotfix-123        # envoyer la branche locale fix sous le nom hotfix-123 sur le serveur
git push origin HEAD                  # envoyer la branche courante sous le même nom

Comment faire son premier push

Le parcours type d'un nouveau projet jusqu'au code sur GitHub ou GitLab ressemble à ceci. Vous créez d'abord un dépôt vide sur le serveur, puis vous y reliez le dépôt local et envoyez la branche.

git init
git add .
git commit -m "Premier commit"
git branch -M main
git remote add origin git@github.com:user/project.git
git push -u origin main

L'option -u (forme longue --set-upstream) associe la branche locale main à la branche distante origin/main. Ensuite, dans cette branche, il suffit d'écrire git push et git pull, et git status indique de combien de commits vous êtes en avance ou en retard sur le serveur.

Pour vérifier où pointe le remote, utilisez git remote -v. Si l'adresse est fausse, corrigez-la avec git remote set-url origin <nouvelle-adresse> au lieu de supprimer et recréer le dépôt.

Comment pousser une nouvelle branche

Vous avez créé une branche pour une tâche, fait des commits et tapé git push. Git répond :

fatal: The current branch feature/login has no upstream branch.
To push the current branch and set the remote as upstream, use

    git push --set-upstream origin feature/login

Ce n'est pas une erreur mais une indication : la branche n'a pas encore d'équivalent sur le serveur. Exécutez la commande proposée ou sa forme courte git push -u origin feature/login. Pour que Git le fasse automatiquement pour toutes les nouvelles branches, activez ce réglage (disponible depuis Git 2.37) :

git config --global push.autoSetupRemote true

Pourquoi git push est refusé : rejected, non-fast-forward

La situation la plus fréquente en équipe :

! [rejected]        main -> main (fetch first)
error: failed to push some refs to 'github.com:user/project.git'
hint: Updates were rejected because the remote contains work that you do
hint: not have locally.

Un collègue a poussé ses commits avant vous. Votre historique et celui du serveur ont divergé, et si Git acceptait votre push, les commits du collègue seraient perdus. La bonne solution consiste à récupérer d'abord ses changements et à y intégrer les vôtres :

git pull --rebase       # récupérer les commits des autres et rejouer les vôtres par-dessus
# en cas de conflit : corriger les fichiers, git add, git rebase --continue
git push

Au lieu de --rebase, vous pouvez faire un git pull classique — un commit de merge sera alors créé. Les deux options sont correctes ; la plupart des équipes préfèrent rebase pour leurs commits locaux afin de garder un historique linéaire. L'essentiel est de ne pas « régler » le refus avec --force.

git push --force et --force-with-lease

Le push forcé est nécessaire quand vous avez volontairement réécrit l'historique de votre branche : git commit --amend, git rebase ou fusion de commits avant la revue. Un push normal refusera cette branche, car les anciens commits du serveur ne sont plus les ancêtres des nouveaux.

git push --force-with-lease

--force-with-lease n'écrase la branche sur le serveur que si elle se trouve encore là où votre Git local l'a vue pour la dernière fois (d'après la référence origin/<branche>). Si un collègue a poussé entre-temps, la commande échoue et vous n'effacez pas son travail. Le simple --force (-f) ne fait pas cette vérification et écrase tout sans rien dire.

Subtilité : si vous lancez git fetch juste avant, la référence origin/<branche> est mise à jour et la protection ne joue plus — Git considère que vous avez « vu » les commits des autres. Ne faites donc pas de fetch juste avant un force push sans regarder ce qui est arrivé.

CommandeEffetQuand l'utiliser
git pushFast-forward uniquementToujours, par défaut
git push --force-with-leaseÉcrasement avec vérificationVotre propre branche après un rebase ou un amend
git push --forceÉcrasement sans vérificationPresque jamais ; jamais sur une branche partagée

On ne force jamais le push sur les branches partagées (main, develop) : tous ceux qui ont récupéré l'ancien historique se retrouveraient avec un historique divergent de celui du serveur. En général, ces branches sont en plus protégées dans les paramètres du dépôt, et le serveur renvoie protected branch hook declined.

Comment pousser des tags

Un git push classique n'envoie pas les tags. Il faut les transmettre explicitement :

git tag -a v1.2.0 -m "Version 1.2.0"
git push origin v1.2.0          # un seul tag
git push --tags                 # tous les tags locaux
git push --follow-tags          # les commits et les tags annotés qui pointent dessus

--follow-tags est plus pratique que --tags : il n'envoie pas les tags légers locaux créés par erreur, uniquement les tags annotés accessibles depuis les commits envoyés.

Comment supprimer une branche distante

La suppression passe elle aussi par push :

git push origin --delete feature/login
# ancienne syntaxe, même effet :
git push origin :feature/login

La branche locale reste en place ; supprimez-la avec git branch -d feature/login. Chez vos collègues, la référence origin/feature/login subsistera tant qu'ils n'auront pas lancé git fetch --prune.

Options utiles de git push

OptionRôle
-u, --set-upstreamMémoriser la branche distante comme upstream
-n, --dry-runMontrer ce qui serait envoyé, sans rien envoyer
--allEnvoyer toutes les branches locales
--tags / --follow-tagsEnvoyer les tags
-d, --deleteSupprimer une branche ou un tag sur le serveur
--force-with-leaseRéécriture d'historique sécurisée
-v, --verboseSortie détaillée
--no-verifyIgnorer le hook pre-push (en connaissance de cause)

Erreurs fréquentes avec git push et leurs solutions

Permission denied (publickey)

Le serveur n'a pas accepté votre clé SSH. Vérifiez que la clé existe (ls ~/.ssh), que sa partie publique est ajoutée à votre compte et que la connexion fonctionne : ssh -T git@github.com. Si le remote est en HTTPS, Git demandera un identifiant et un token, pas une clé — regardez git remote -v.

Authentication failed en HTTPS

GitHub et beaucoup d'autres services n'acceptent plus depuis longtemps le mot de passe du compte en HTTPS. Il faut un token d'accès personnel ou passer à SSH. Un credential helper permet de mémoriser le token : git config --global credential.helper store (stockage en clair) ou le gestionnaire d'identifiants de votre système.

src refspec main does not match any

Vous n'avez pas de branche portant ce nom. Le plus souvent, aucun commit n'a encore été fait dans le dépôt vide, ou la branche s'appelle master. Vérifiez avec git branch et faites un commit, ou renommez la branche : git branch -M main.

Everything up-to-date alors qu'il y a des changements

Vous avez oublié de committer. git push envoie des commits, pas des fichiers. Lancez git status, puis git add et git commit. Autre possibilité : vous n'êtes pas sur la branche que vous vous attendez à voir sur le serveur.

Fichier trop volumineux

Les services limitent la taille des fichiers (100 Mo sur GitHub). Si un tel fichier est déjà dans l'historique, le supprimer dans un nouveau commit ne suffit pas : il faut réécrire l'historique ou le retirer des commits pas encore envoyés (git reset --soft, puis nouveau commit). Pour les gros fichiers binaires, on utilise Git LFS.

Le cycle de travail avec git push

  1. git switch -c feature/x — une branche pour la tâche.
  2. Des commits en petites étapes logiques.
  3. git fetch et git rebase origin/main — récupérer la branche principale à jour.
  4. git push -u origin feature/x — publier la branche.
  5. Ouvrir une pull request ; après la revue, commits supplémentaires et git push classique.
  6. Si vous avez dû réécrire l'historique — git push --force-with-lease.

Avant d'envoyer, il est utile de voir exactement ce qui partira sur le serveur : git log origin/main..HEAD --oneline affiche les commits qui n'y sont pas encore.

Ce qu'il faut configurer une fois pour toutes

Quelques réglages globaux évitent la plupart des surprises au moment du push. push.default détermine ce qu'envoie git push sans argument. La valeur par défaut des versions récentes est simple : seule la branche courante est envoyée, et uniquement vers la branche upstream de même nom. Inutile en général d'y toucher, mais vérifiez qu'il ne reste pas un matching dans une vieille configuration, qui envoie d'un coup toutes les branches de même nom.

git config --global push.default simple
git config --global push.autoSetupRemote true
git config --global push.followTags true
git config --global pull.rebase true

push.followTags fait de --follow-tags le comportement par défaut, et pull.rebase évite les commits de merge superflus quand le push est refusé et qu'il faut d'abord récupérer les changements des autres.

Le hook pre-push

Le fichier .git/hooks/pre-push s'exécute avant l'envoi. S'il se termine avec un code non nul, le push n'a pas lieu. Les équipes y lancent souvent les tests ou le linter pour qu'aucun code cassé ne parte sur le serveur. Ne contournez ce hook avec --no-verify que si vous savez précisément pourquoi il échoue.

En résumé

git push publie vos commits dans le dépôt distant et ne fonctionne que dans un sens. Faites le premier envoi d'une branche avec -u, en cas de refus récupérez d'abord les changements des autres avec pull, et n'envoyez l'historique réécrit de votre branche qu'avec --force-with-lease. Le travail avec les dépôts distants, push, pull et les clés SSH est abordé en pratique dans le cours Git.

Questions fréquentes

git push envoie-t-il les modifications non commitées ?

Non. Push ne transmet que des commits ; les modifications du répertoire de travail et de l'index restent en local tant que vous ne les avez pas commitées.

Comment annuler un git push ?

Sur votre propre branche, vous pouvez annuler le commit en local (git reset) puis l'envoyer avec git push --force-with-lease. Sur une branche partagée, il est plus sûr de créer un commit inverse avec git revert et de faire un push normal.

Peut-on pousser un seul commit ?

Oui, en indiquant son hash : git push origin abc1234:main envoie tout l'historique jusqu'à ce commit inclus, mais pas les commits plus récents. On ne peut pas envoyer un commit sans ses ancêtres.

Quelle différence entre git push et git push origin main ?

Sans argument, Git utilise l'upstream configuré de la branche courante, alors que la forme explicite indique directement le remote et la branche et fonctionne même sans upstream configuré.

Comment pousser vers deux dépôts à la fois ?

Ajoutez un second remote et poussez vers chacun par son nom, ou ajoutez deux adresses de push à origin avec git remote set-url --add --push origin adresse (à faire pour les deux adresses, y compris l'originale, sinon le push n'ira que vers la seconde).

Apprenez ce sujet en vidéo

Ce sujet est traité en détail avec de la pratique dans le cours « Git de zéro à développeur confirmé ».

Voir le cours