Les templates de Pull Request
💡 Sujet
Un template de Pull Request est un simple fichier Markdown versionné dans le dépôt : GitHub le recopie automatiquement dans la description de toutes les nouvelles PR. L'intérêt n'est pas cosmétique — c'est un formulaire imposé au moment où l'auteur a encore le contexte en tête, pour que le relecteur reçoive ce dont il a besoin (le quoi, le pourquoi, comment tester) sans avoir à le réclamer en commentaire.
📁 Où poser le fichier
Un seul fichier, trois emplacements possibles, au choix :
.github/pull_request_template.md ← le plus courant, range les fichiers de config ensemble
pull_request_template.md ← à la racine, visible de tous
docs/pull_request_template.md ← avec la documentationLe nom du fichier est insensible à la casse : pull_request_template.md et
PULL_REQUEST_TEMPLATE.md fonctionnent tous les deux. L'extension peut être .md ou aucune
extension du tout ; .md est le seul choix raisonnable puisque le contenu est rendu en Markdown.
Si plusieurs emplacements contiennent un template, .github/ l'emporte sur la racine, qui l'emporte
sur docs/. Autant n'en garder qu'un.
Le fichier est pris en compte dès qu'il est mergé sur la branche par défaut. Rien à activer dans les réglages du dépôt.
✍️ À quoi ressemble un template
Rien d'imposé : c'est du Markdown libre. La structure qui marche tient en quatre blocs.
## Description
<!-- Que fait cette PR, et pourquoi ? -->
Closes #
## Type de changement
- [ ] Correction de bug
- [ ] Nouvelle fonctionnalité
- [ ] Changement cassant (breaking change)
- [ ] Documentation
## Comment tester
1.
2.
## Checklist
- [ ] Les tests passent en local
- [ ] La documentation est à jour
- [ ] J'ai relu mon propre diffDeux mécaniques Markdown font tout le travail :
- [ ]produit une vraie case à cocher, cliquable directement dans la PR une fois celle-ci ouverte. C'est ce qui transforme un pavé de texte en to-do list vivante pour l'auteur et le relecteur.<!-- ... -->est un commentaire HTML : il est invisible dans le rendu de la description. C'est l'endroit où mettre les consignes destinées à l'auteur du PR sans polluer le résultat final.
Le Closes # laissé volontairement incomplet est un rappel : Closes #42 dans la description
ferme automatiquement l'issue 42 à la fusion de la PR.
🧵 Plusieurs templates : le dossier PULL_REQUEST_TEMPLATE/
Pour proposer plusieurs formulaires (un pour les correctifs, un pour les releases, un pour les mises à jour de dépendances), il faut un dossier au lieu d'un fichier :
.github/PULL_REQUEST_TEMPLATE/
├── bugfix.md
├── feature.md
└── release.mdLe piège : contrairement aux templates d'issue, GitHub n'affiche aucun sélecteur. Ouvrir une PR
normalement ne propose rien du tout — le dossier semble ignoré. Le seul moyen de choisir un template
est le paramètre d'URL template :
https://github.com/husur/til/compare/main...ma-branche?expand=1&template=bugfix.mdexpand=1ouvre directement le formulaire de création de PR au lieu de la vue de comparaison.template=bugfix.mdsélectionne le fichier, avec son extension.
D'où la pratique habituelle : garder un pull_request_template.md classique comme cas par défaut,
mettre les variantes dans le dossier, et publier les URL toutes faites dans le CONTRIBUTING.md.
D'autres paramètres se cumulent sur la même URL : title=, body=, labels=, assignees=,
milestone=, projects=.
🏢 Un template par défaut pour toute une organisation
Un fichier pull_request_template.md placé dans le dépôt spécial .github d'une organisation (ou
d'un compte perso) sert de valeur par défaut à tous les dépôts qui n'ont pas le leur.
mon-orga/.github/.github/pull_request_template.mdLe premier .github est le nom du dépôt, le second le dossier à l'intérieur. Ces fichiers de
« community health » par défaut ne sont jamais fusionnés avec ceux du dépôt : dès qu'un dépôt
possède son propre template, il écrase entièrement celui de l'organisation.
⚠️ Les cas où le template ne s'applique pas
C'est là que les surprises arrivent.
- L'API REST/GraphQL ignore le template. Un
POST /repos/{owner}/{repo}/pullscrée la PR avec lebodyfourni, un point c'est tout. Les PR ouvertes par un bot, un script ou une Action n'auront donc jamais le formulaire — Dependabot, par exemple, rédige toujours sa propre description. gh pr create, en revanche, respecte le template : la CLI le charge pour préremplir le corps, et propose un choix quand plusieurs templates existent. Sauf si on passe--bodyou--fill, qui court-circuitent tout.- Le template remplace le message de commit. Sans template, GitHub préremplit la description d'une PR à un seul commit avec le corps de ce commit. Avec un template, c'est le template qui gagne, et le message de commit est perdu.
- Pas de front-matter YAML. Les blocs
---avecname:,about:,labels:fonctionnent pour les issues, pas pour les PR : ici ils s'afficheraient tels quels dans la description. Et les « issue forms » (les formulaires YAML avec de vrais champs) n'ont aucun équivalent côté Pull Request — le template de PR reste du Markdown brut recopié. - Rien n'est obligatoire. L'auteur peut vider intégralement la description. Pour rendre une case à cocher bloquante, il faut une Action de CI qui relit le corps de la PR et échoue.
🧩 Résumé
- 📄 Un
pull_request_template.mddans.github/, à la racine ou dansdocs/, et toute nouvelle PR démarre préremplie — aucun réglage à activer. - ☑️
- [ ]devient une case cliquable,<!-- -->un commentaire invisible pour guider l'auteur. - 🧵 Plusieurs templates → dossier
PULL_REQUEST_TEMPLATE/, mais aucun sélecteur : il faut l'URL...?expand=1&template=bugfix.md. - 🏢 Le dépôt
.githubd'une organisation fournit un template par défaut, écrasé (jamais fusionné) par celui du dépôt. - 🤖 L'API ignore le template,
gh pr createle respecte. - ⚠️ Sur une PR à un seul commit, le template écrase le préremplissage par le message de commit.
- 🚫 Ni front-matter YAML ni champs de formulaire côté PR, et rien n'empêche de tout effacer : l'obligation ne peut venir que de la CI.