git push est une des commandes Git utilisée quotidiennement, il convient donc de bien la connaître, pour en maîtriser la puissance et éviter les écueils.

Voici quelques conseils éviter les mauvaises surprises.

La version longue c’est long… mais c’est bon (mais c’est long)

Tout le monde connaît le fameux « push-pull » pour se synchroniser avec le dépôt principal, mais « git push<CR> » n’est pas la vraie commande, c’est un raccourci. Nous allons donc voir la vraie forme, ce qui vous permettra à la fois de mieux comprendre ce que vous faîtes… et d’utiliser les autres possibilités de cet outil.

Oubliez « git push --force … »

L’option --force de git push force l’envoi de la référence, permettant d’écraser des branches distantes.

Cependant, cette option s’applique à tous les arguments de la commande… ainsi qu’aux arguments implicites (dans le cas d’un appel sans arguments).

Par exemple, je suis en train de travailler sur une branche perso (feature/bla), pendant que d’autres continuent de mettre à jour la branche principale (master). Je veux corriger le dernier commit pushé sur cette branche, donc je fais « git push -f » pour y envoyer mon nouveau historique. Problème : cette commande a de fortes chances (cela dépend de la configuration) de push votre branche ainsi que master. Mon ancienne version de master est envoyée de force sur le serveur, supprimant ainsi les commits pushés par mes collègues.

Utilisez la syntaxe +branch à la place, elle est plus puissante et donne plus de contrôle.

Dans mon exemple, si j’avais utilisé « git push origin master +feature/bla » alors seule la branche feature/bla aurait été poussée en force, permettant à Git de prévenir des éventuels cafouillages avec master.

De plus cette syntaxe oblige à nommer les branches à pusher… évitant le problème montré par mon exemple : l’inclusion d’une branche non désirée.

Supprimez les branches distantes à l’aide « git push <remote> :<ref> »

Pour comprendre cette commande il faut connaître la forme complète de git push.

Voici un exemple : la commande « git push origin master » est un raccourci pour « git push origin master:master »1. On spécifie la branche locale ainsi que la branche distante dans laquelle on pousse.

La commande « git push <remote> :<ref> » consiste donc à pousser rien dans une branche distante… Il s’agit donc d’un effacement (à l’instar des « mv <truc> /dev/null » et Cie.

Utilisez le mode « simple » de git-push

Lorsque vous appelez git push sans fournir d’argument (volontairement ou non), le comportement adopté dépend de la configuration.

Voici les différents modes (actuels) :

  • nothing
  • On ne fait rien (force à spécifier le dépôt et les références)

  • matching

  • pousse les branches locales qui ont le même nom que des branches distantes — Valeur par défaut de Git 1.x

  • upstream

  • pousse la branche actuelle sur sa branche trackée

  • simple

  • pour la branche actuelle sur sa branche trackée à condition que les deux aient le même nom — Ce sera le mode par défaut de Git 2.x

  • current

  • pousse la branche actuelle sur la branche distante du même nom

Je vous conseille vivement d’opter dès maintenant pour la valeur simple. Pour ceci vous pouvez utiliser la commande suivante :

git config --global push.default simple

Voici un exemple d’erreur possible avec la valeur upstream :

# Ici la branche master track la branche master du dépôt origin
git checkout master
# On renomme master en develop, cela n'affecte pas le tracking
git branch -m develop
# La branche develop sera poussée dans master
git push  # ⚠ ⇔ git push origin develop:master

J’ai parlé plusieurs fois de « tracking » dans cette section. Si vous ne savez pas ce que c’est, alors raison de plus pour utiliser le mode simple ! Mais ne vous en faites pas, j’en parlerai plus tard.

Sur ce, je vous laisse vous amuser, et reviendrai vous ennuyer plus tard pour vous parler de git pull.


  1. Plus précisément : « git push origin refs/heads/master:refs/heads/master », mais on ne va pas chipotter.