Maîtrise des pull requests : exploitez pleinement vos capacités de récupération !

Nicola Paolucci
Nicola Paolucci
Retour à la liste

Aujourd'hui, pour apporter des corrections à un projet, il suffit de faire un fork (le fork est une copie distante complète du projet que vous pouvez hacker), de sélectionner le fichier à modifier, d'appuyer sur Edit, puis de faire des commits de vos corrections.

Et qu'en est-il si vous vous trouvez à l'extrémité de réception d'une pull request ? Une interface Web améliorée est pratique et répond souvent à tous vos besoins. Cliquez sur le bouton Approve (Approuver), puis Merge (Faire un merge). Vous avez alors terminé.

Approbations de pull requests

Mais ce n'est pas toujours le cas ! Il arrive fréquemment qu'il soit nécessaire de télécharger les changements inclus localement dans une pull request, d'exécuter quelques tests et de voir le résultat dans votre IDE pour les comprendre.

En théorie, les étapes nécessaires au chargement – c'est-à-dire fetch et checkout – des pull requests de vos collègues ou de vos contributeurs sont très simples, mais elles le seront encore plus avec quelques conseils et astuces supplémentaires.

Laissez-moi vous aider à mieux comprendre les fonctionnalités que Git vous propose pour gérer facilement les pull requests à partir de la ligne de commande.

Avant de commencer : ajouter le statut et le nom de branche dans l'invite shell

I am always surprised by how many people have a bare command prompt that doesn't show the git branch they are on or whether they have modified/uncommitted files in their working directory. If you thought - Hey that's me! - allow me to help you and blow your mind at the same time!

Rendez-vous service et installez un module comme Liquid Prompt, qui vous indiquera efficacement le statut de votre répertoire de travail Git (et qui prendra aussi en charge tout autre logiciel de contrôle de version) :

Liquid prompt

(La capture d'écran ci-dessus vous montre mon invite, qui m'indique que je suis sur la branche newbranch, que j'ai ajouté 5 lignes aux fichiers que je tracke dans mon répertoire de travail et que j'en ai supprimé 0)

Tout le monde travaille dans le même dépôt

Si votre équipe et vous-même travaillez sur le même dépôt, le checkout des pull requests est très simple ; il vous suffit de lancer un fetch et un checkout de la branche à partir de laquelle la pull request a été faite :

  • Récupérez toutes les branches qui ont été publiées sur votre dépôt partagé :
git fetch origin
  • Créer une branche locale qui tracke la branche distante qui vous intéresse :
git checkout -b PRJ-1234 origin/PRJ-1234
  • Now you can diff, merge, test your heart out of this:
git diff master
./run-tests.sh
  • Lorsque vous êtes satisfait, revenez simplement à l'interface Web et indiquez votre feedback ou approuvez le changement.

Contributeurs travaillant dans leurs propres forks

The process changes a bit when some of the contributors work in separate forks. In this case you can fetch the remote branch where the contribution or feature was committed:

  • Ajoutez d'abord le remote du contributeur :
git remote add jsmith http://bitbucket.org/jsmith/coolproject.git
  • Collect all the latest updates from origin first, your main repository:
git checkout master
git fetch origin
git merge master
  • Récupérez toutes les branches qui ont été publiées sur le fork du contributeur :
git fetch jsmith
  • Créer une branche locale qui tracke la branche distante qui vous intéresse :
git checkout -b jsmith-PRJ-1234 jsmith/PRJ-1234
  • Now you can diff, merge, test your heart out of this:
git diff master
./run-tests.sh

Réduire la charge de travail en utilisant des réfs de pull request

La solution ci-dessus fonctionne, mais différents éléments peuvent vous compliquer la vie :

  • Que se passe-t-il si vous avez de nombreux collaborateurs et que chacun a ses propres forks ? Ce n'est pas pratique d'ajouter leurs forks et de les gérer individuellement.
  • Que faire si vous n'avez accès qu'à certains forks et que vous ne pouvez pas faire un checkout de la branche source ?

La solution aux deux problèmes exposés ci-dessus consiste à utiliser les réfs des pull requests fournies par certains serveurs Git. La procédure que je vais vous montrer est prise en charge par certains serveurs Git et varie légèrement suivant celui que vous utilisez. Dans les lignes qui suivent, je vous expliquerai comment fetcher toutes les pull requests sur Stash (à présent connu sous le nom de Bitbucket Server) et Github.

N'ayez pas peur des refspecs

La première condition est de vous familiariser avec les refspecs. Les refspecs ne sont pas bien méchants ; ils ne vont pas vous manger ! Il s'agit simplement de mappages des branches distantes vers des références locales. En d'autres termes, c'est une manière directe de dire à Git que « cette branche distante (ou cette plage de branches distantes) devrait être mappée vers ces noms en local, dans cet espace de noms. »

Par exemple, une commande comme :

git fetch +refs/heads/master:refs/remotes/origin/master

Va mapper la branche master distante située sur votre remote origin vers une branche origin/master locale. Ainsi, vous pourrez saisir :

git checkout origin/master

Vous vous référez toujours à cette branche distante. Le signe « plus » (+) de la définition permet d'ordonner à Git de mettre à jour la référence, même si ce n'est pas en fast-forward.

Pour télécharger toutes les pull requests, nous effectuons un mapping afin d'indiquer comment le remote stocke les PR HEAD et nous les mappons vers un espace de noms local pour nous y référer facilement.

So provided you have an origin (or upstream) remote defined, here's what to do.

Remarque : comme l'ont très justement noté des développeurs Stash (à présent connu sous le nom de Bitbucket Server), les réfs que je vais vous présenter ci-dessous sont considérées comme non documentées et privées, et peuvent changer à tout moment.

Télécharger toutes les pull requests : Stash

  • Faites un fork d'un dépôt.
  • Clonez votre fork en local :
git clone git@stash.atlassian.com:durdn/tis.git
  • Ajoutez le dépôt d'origine upstream comme upstream.
git remote add upstream git@stash.atlassian.com:tpettersen/tis.git
  • Obtenez les derniers heads du mainteneur « upstream »
git fetch upstream
  • Ajoutez le refspec qui va mapper les heads des pull requests distantes vers un espace de noms pr local. Pour ce faire, vous pouvez utiliser la commande config :
git config --add remote.origin.fetch '+refs/pull-requests/*/from:refs/remotes/origin/pr/*'
  • If you look in .git/config the fetch entries become:
[remote "upstream"]
    url = git@stash.atlassian.com:docker/libswarm.git
    fetch = +refs/heads/*:refs/remotes/upstream/*
    fetch = +refs/pull-requests/*/from:refs/remotes/upstream/pr/*
  • Now you can fetch all pull requests branches easily:
$ git fetch upstream
remote: Counting objects: 417, done.
remote: Compressing objects: 100% (274/274), done.
remote: Total 417 (delta 226), reused 277 (delta 128)
Receiving objects: 100% (417/417), 105.28 KiB | 0 bytes/s, done.
Resolving deltas: 100% (226/226), done.
From stash.atlassian.com:docker/libswarm
* [new ref] refs/pull-requests/10/from-> upstream/pr/10
[...]
* [new ref] refs/pull-requests/100/from -> upstream/pr/100
* [new ref] refs/pull-requests/101/from -> upstream/pr/101
[...]
* [new ref] refs/pull-requests/109/from -> upstream/pr/109
* [new ref] refs/pull-requests/110/from -> upstream/pr/110
[...]
  • Maintenant, pour basculer vers une pull request particulière, vous pouvez simplement :
git checkout pr/102

Télécharger toutes les pull requests : Github

If the forks or upstreams are on Github it works exactly as above but the config command changes to:

git config --add remote.origin.fetch '+refs/pull//head:refs/remotes/origin/pr/'

And the remote in .git/config will change to include an additional fetch configuration to map the PR heads to a local name space called pr:

[remote "upstream"]
url = git@github.com:docker/libswarm.git
fetch = +refs/heads/*:refs/remotes/upstream/*
fetch = +refs/pull/*/head:refs/remotes/upstream/pr/*

Fetcher une PR unique avec des réfs

Si vous ne souhaitez pas configurer des entrées fetch dans votre .git/config et que vous voulez accéder rapidement à une pull request, une seule commande vous le permettra :

  • Checkout a single PR in Stash:
git fetch refs/pull-requests/your-pr-number/from:local-branch-name
  • Faire un checkout d'une pull request unique sur Github :
git fetch refs/pull/your-pr-number/head:local-branch-name

And if you find yourself using the above a lot you can streamline the process by creating a git alias:

# For Stash
git config alias.spr '!sh -c "git fetch origin pull-requests/${1}/from:pr/${1}" -'
# For Github
git config alias.gpr '!sh -c "git fetch origin pull/${1}/head:pr/${1}" -'

With that alias configured we can fetch a pull request with a simple (thanks inuit):

git spr 100

Conclusions

Hope you found this useful! In the end keeping tabs on the work of your peers or contributors is easy once you create a couple of simple aliases or add the proper refspecs to your .git/config. Happy to answer any questions you might have on Twitter at @durdn or @AtlDevtools.

Prêt à découvrir Git ?

Essayez ce tutoriel interactif.

Démarrez maintenant