Commit de code

This section is addressed to the mergers and to anyone interested in knowing how code gets committed into Django. The Lignes directrices pour les commits apply to all contributors, with or without commit rights.

If you’re a community member who wants to contribute code to Django, look at Travailler avec Git et GitHub instead.

Gestion des requêtes de contribution

Comme Django est hébergé sur GitHub, les correctifs sont fournis sous la forme de requêtes de contribution (« pull request »).

En commitant une requête de contribution, vérifiez que chaque commit individuel corresponde aux lignes de conduite présentées ci-dessous. On attend des contributeurs qu’ils fournissent les meilleurs requêtes de contribution possibles. En pratique, c’est aux fusionneurs, plus familiers avec les exigences de qualité des commits, que revient la décision de parachever eux-mêmes un commit pour qu’il satisfasse aux exigences posées.

Il peut être souhaitable de demander à Jenkins ou aux actions GitHub de tester la requête de contribution à l’aide d’un des constructeurs qui ne se lance pas automatiquement, tel que Oracle ou Selenium. Voir la page de Wiki CI pour plus d’instructions.

S’il se trouve que vous deviez fréquemment récupérer localement des requêtes de contribution, cet alias git vous sera utile :

[alias]
    pr = !sh -c \"git fetch upstream pull/${1}/head:pr/${1} && git checkout pr/${1}\"

Ajoutez-le à votre fichier ~/.gitconfig et définissez upstream à django/django. Vous pouvez alors exécuter git pr #### pour récupérer en local la requête de contribution correspondante.

À ce stade, vous pouvez travailler sur le code. Utilisez git rebase -i et git commit --amend pour vous assurer que les commits présentent le niveau de qualité requis. Quand vous êtes prêt :

$ # Pull in the latest changes from main.
$ git checkout main
$ git pull upstream main
$ # Rebase the pull request on main.
$ git checkout pr/####
$ git rebase main
$ git checkout main
$ # Merge the work as "fast-forward" to main to avoid a merge commit.
$ # (in practice, you can omit "--ff-only" since you just rebased)
$ git merge --ff-only pr/XXXX
$ # If you're not sure if you did things correctly, check that only the
$ # changes you expect will be pushed to upstream.
$ git push --dry-run upstream main
$ # Push!
$ git push upstream main
$ # Delete the pull request branch.
$ git branch -d pr/xxxx
...\> REM Pull in the latest changes from main.
...\> git checkout main
...\> git pull upstream main
...\> REM Rebase the pull request on main.
...\> git checkout pr/####
...\> git rebase main
...\> git checkout main
...\> REM Merge the work as "fast-forward" to main to avoid a merge commit.
...\> REM (in practice, you can omit "--ff-only" since you just rebased)
...\> git merge --ff-only pr/XXXX
...\> REM If you're not sure if you did things correctly, check that only the
...\> REM changes you expect will be pushed to upstream.
...\> git push --dry-run upstream main
...\> REM Push!
...\> git push upstream main
...\> REM Delete the pull request branch.
...\> git branch -d pr/xxxx

Poussez de force dans la branche après un « rebase » sur main, mais avant de fusionner et de pousser vers le dépôt amont. Cela permet d’harmoniser les empreintes de commit sur main et sur la branche ce qui va automatiquement fermer la requête de contribution.

Si une requête de contribution ne doit pas être fusionnée avec plusieurs commits différents, il est possible d’utiliser le bouton «Squash and merge» du site Web. Modifiez le message de commit afin qu’il corresponde aux :ref:lignes directrices <committing-guidelines>` et enlevez le numéro de la requête de contribution qui est automatiquement ajouté à la première ligne du message.

Lorsque vous réécrivez l’historique des commits dans une requête de contribution, l’objectif est de rendre l’historique des commits de Django le plus propre possible:

  • Si un correctif a été effectué sur plusieurs commits, réécrivez-le en un seul. Par exemple, si un commit ajoute du code et qu’un second ne fait qu’améliorer son écriture, ces commits devraient être compressés en un seul avant d’être fusionné dans le projet.

  • Regroupez les changements de façon logique dans plusieurs commits. Si vous faites des changements cosmétiques en même temps que des modifications de code dans un autre fichier, le faire en deux commits distincts aide à relire l’historique des changements.

  • Évitez les fusions de branches amont dans les requêtes de contribution.

  • Les tests et la documentation devraient être validés et ne pas émettre d’avertissements ou d’erreurs après chaque commit.

  • Les petits correctifs triviaux devraient être fait dans un seul commit. Les contributions plus importantes peuvent être fait en plusieurs commits si cela est plus claire.

Conformément au concept « pratique vaut mieux que pureté », c’est à chaque fusionneur de décider de la manipulation d’historique nécessaire pour une requête de contribution. Les points essentiels sont l’engagement de la communauté, le travail bien fait et un historique de commit utilisable.

Lignes directrices pour les commits

These guidelines apply to all commits to Django’s Git repository, whether submitted by a contributor via a pull request or landed directly by a merger:

  • Ne modifiez jamais l’historique publié des branches django/django en poussant (push) de force. Si vous devez absolument le faire (par exemple pour des raisons de sécurité), discutez d’abord de la situation avec l’équipe principale.

  • Pour toute modification moyenne à importante, où « moyenne à importante » dépend de votre jugement, présentez la situation sur le forum Django avant de procéder au changement.

    SI vous exposez quelque chose et que personne ne répond, ne considérez pas que cela signifie que votre idée est géniale et qu’elle doit être mise en œuvre immédiatement car personne ne la contestée. Tout le monde n’a pas toujours beaucoup de temps pour lire immédiatement les discussions, il se peut donc que vous deviez attendre un certain nombre de jours avant d’obtenir une réponse.

  • Write detailed commit messages in the past tense, not present tense, and end the subject line with a period.

    • Correct: « Fixed Unicode bug in RSS API. »

    • Incorrect: « Fixes Unicode bug in RSS API. » (present tense)

    • Incorrect: « Fixing Unicode bug in RSS API. » (« -ing » form)

    • Incorrect: « Fixed Unicode bug in RSS API » (missing trailing period)

    The commit message should be in lines of 72 chars maximum. There should be a subject line, separated by a blank line and then paragraphs of 72 char lines. The limits are soft. For the subject line, shorter is better.

    In the body of the commit message more detail is better than less, and should explain why the change was made, not what was changed or how. The code itself shows what changed; the commit message should provide the context and reasoning that the code cannot.

    Credit the contributors in the commit message: « Thanks A for the report and B for review. » Use git’s Co-Authored-By as appropriate, including anyone whose earlier work the change builds on.

    Par exemple :

    Fixed #18307 -- Added git workflow guidelines.
    
    Refactored the Django's documentation to remove mentions of SVN
    specific tasks. Added guidelines of how to use Git, GitHub, and
    how to use pull request together with Trac instead.
    
    Thanks to Full Name for the report, and to Reviewer for reviews.
    
  • Limitez les commits à la plus petite granularité qui garde du sens. Cela signifie qu’il est préférable d’avoir plusieurs petits commits fréquents plutôt que de gros commits ponctuels. Par exemple, si l’implémentation de la fonctionnalité X requiert une petite modification à la bibliothèque Y, alors faites le commit de la fonctionnalité X séparément. Cela aide grandement toutes les personnes qui suivent vos modifications.

  • Separate bug fixes from feature changes. Bugfixes may need to be backported.

  • Si un commit ferme un ticket dans le système de suivi de Django, commencez le message de commit par le texte « Fixed #xxxxx », où « xxxxx » est le numéro du ticket résolu par le commit. Example : « Fixed #123 – Added whizbang feature. ». Nous avons adapté Trac pour que tout message de commit respectant ce format ferme automatiquement le ticket référencé et écrive un message sur le ticket contenant le message de commit complet.

    Pour les curieux, nous utilisons un greffon Trac pour cela.

Note

Notez que l’intégration Trac ne sait pas tout sur les requêtes de contribution. AInsi si vous essayez de fermer une requête de contribution avec la phrase « closes #400 » dans le message de commit, GitHub fermera la requête, mais le greffon Trac ne fermera pas le ticket ayant le même numéro dans Trac.

  • Si votre commit fait référence à un ticket dans le suivi des tickets de Django mais ne résoud pas le ticket, incluez l’expression « Refs #xxxxx », où « xxxxx » est le numéro de ticket référencé par votre commit. Cela enverra automatiquement un commentaire dans le ticket concerné.

Backports

Bug fix backports to stable branches are done exclusively by mergers, following the Versions prises en charge. A backport consists of cherry-picking a commit from main onto the target stable/A.B.x branch.

A backport commit must include two things beyond the original commit message:

  • A prefix [A.B.x] on the subject line, where A.B.x is the name of the stable/A.B.x branch being targeted.

  • A suffix Backport of <sha> from main. line in the commit body, pointing to the original commit hash.

Par exemple :

[1.3.x] Fixed #17028 -- Changed diveintopython.org -> diveintopython.net.

Backport of 80c0cbf1c97047daed2c5b41b296bbc56fe1d7e3 from main.

If the backport also fixes a regression, add a line identifying the commit that introduced it:

Regression in 6ecccad711b52f9273b1acb07a57d3f806e93928.

There are three ways to do a backport, depending on your workflow:

Option 1: fully manual

Cherry-pick the commit onto the stable branch, then amend the commit message to add the required prefix and backport note:

git cherry-pick <sha>
git commit --amend

If the cherry-pick produces conflicts, resolve them, stage the changes, then run git cherry-pick --continue before amending. This option requires no setup but relies entirely on remembering to format the message correctly.

Option 2: using the helper script in the repo

The scripts/backport.sh Bash script automates the cherry-pick and rewrites the commit message with the correct prefix and backport note. Run it from the target stable branch:

bash scripts/backport.sh <sha>

This is straightforward for clean cherry-picks, but if conflicts are produced, you will need to resolve them manually and add the prefix and backport note to the commit message yourself.

Option 3: using the prepare-commit-msg git hook

The scripts/prepare_commit_msg.py Python script can be installed as a prepare-commit-msg git hook. It automatically adds the [A.B.x] prefix to the subject line, appends Backport of <sha> from main. to the commit body, and ensures the subject line ends with a period, even when the cherry-pick produces conflicts. To install it, create an executable file .git/hooks/prepare-commit-msg containing:

#!/bin/sh
exec python scripts/prepare_commit_msg.py "$@"

Once installed, a plain git cherry-pick <sha> on a stable branch is sufficient; the hook handles the message formatting in all cases.

Annulation de commits

Personne n’est parfait ; des erreurs seront forcément commises.

Mais faites tout votre possible pour que de telles erreurs ne se produisent pas. Le fait d’avoir une politique d’annulation ne vous enlève pas la responsabilité de viser la plus haute qualité possible. Sérieusement, vérifiez votre travail autant de fois que nécessaire ou faites-le vérifier par un autre fusionneur avant de procéder au commit !

Lorsqu’un commit fautif est découvert, veuillez suivre les directives suivantes :

  • Si possible, faites faire l’annulation d’un commit par son auteur.

  • N’annulez pas les modifications d’un autre auteur sans la permission de celui-ci.

  • Utilisez git revert – ce qui va produire un commit d’annulation, le commit original faisant toujours partie de l’historique des commits.

  • Si l’auteur d’origine ne peut pas être contacté (dans un espace de temps raisonnable, un à deux jours) et que le problème est sérieux (bogue de plantage, échecs de tests majeurs, etc.), demandez sur le forum Django s’il y a des oppositions puis procédez à l’annulation s’il n’y en a pas.

  • Si le problème est mineur (par ex. un commit de fonctionnalité après le gel des fonctionnalités), attendez encore un peu.

  • S’il y a désaccord entre le fusionneur et celui qui propose l’annulation, il s’agit de résoudre le conflit sur le forum Django. Si aucun accord n’est trouvé, la décision doit alors être soumise à un vote.

  • Si le commit a introduit une vulnérabilité de sécurité confirmée et révélée, le commit peut être immédiatement annulé sans obtenir de permission supplémentaire.

  • Le mainteneur de la branche versionnée peut annuler des commits de cette branche sans demander de permission si un commit casse cette branche versionnée.

  • Si vous avez poussé par erreur une branche de travail vers django/django, supprimez-la. Par exemple, si vous avez écrit : git push upstream feature_antigravity, procédez à la commande inverse : git push upstream :feature_antigravity.