Lifecycle of a pull request#

Introduction#

CPython uses a workflow based on pull requests. What this means is that you create a branch in Git, make your changes, push those changes to your fork on GitHub (origin), and then create a pull request against the official CPython repository (upstream).

Quick guide#

Clear communication is key to contributing to any project, especially an Open Source project like CPython.

Here is a quick overview of how you can contribute to CPython:

  1. Create an issue that describes your change [*]

  2. Create a new branch in Git from the main branch

  3. Work on changes (e.g. fix a bug or add a new feature)

  4. Run tests and make patchcheck

  5. Commit and push changes to your GitHub fork

  6. Create Pull Request on GitHub to merge a branch from your fork

  7. Make sure the continuous integration checks on your Pull Request are green (i.e. successful)

  8. Review and address comments on your Pull Request

  9. When your changes are merged, you can delete the PR branch

  10. Celebrate contributing to CPython! :)

Note

In order to keep the commit history intact, please avoid squashing or amending history and then force-pushing to the PR. Reviewers often want to look at individual commits.

Step-by-step guide#

You should have already set up your system, got the source code, and built Python.

  • Update data from your upstream repository:

    git fetch upstream
    
  • Create a new branch in your local clone from the main branch in the upstream repository:

    git checkout -b <branch-name> upstream/main
    

    Note

    Almost all changes to Python, including bug fixes, should first be made against the main branch. See here for more details.

  • Make changes to the code, and use git status and git diff to see them.

    (Learn more about Making good PRs)

  • Make sure the changes are fine and don’t cause any test failure:

    make patchcheck
    ./python -m test
    

    (Learn more about patchcheck and about Running and writing tests)

  • Once you are satisfied with the changes, add the files and commit them:

    git add <filenames>
    git commit -m '<message>'
    

    (Learn more about Making good commits)

  • Then push your work to your GitHub fork:

    git push origin <branch-name>
    
  • Finally go on https://github.com/<your-username>/cpython: you will see a box with the branch you just pushed and a green button that allows you to create a pull request against the official CPython repository.

  • When people start adding review comments, you can address them by switching to your branch, making more changes, committing them, and pushing them to automatically update your PR:

    git switch <branch-name>
    # make changes and run tests
    git add <filenames>
    git commit -m '<message>'
    git push origin <branch-name>
    
    • If a core developer reviewing your PR pushed one or more commits to your PR branch, then after checking out your branch and before editing, run:

      git pull origin <branch-name>  # pull = fetch + merge
      

      If you have made local changes that have not been pushed to your fork and there are merge conflicts, Git will warn you about this and enter conflict resolution mode. See Resolving merge conflicts below.

  • If time passes and there are merge conflicts with the main branch, GitHub will show a warning to this end and you may be asked to address this. Merge the changes from the main branch while resolving the conflicts locally:

    git switch <branch-name>
    git pull upstream main  # pull = fetch + merge
    # resolve conflicts: see "Resolving Merge Conflicts" below
    git push origin <branch-name>
    
  • After your PR has been accepted and merged, you can delete the branch:

    git branch -D <branch-name>  # delete local branch
    git push origin -d <branch-name>  # delete remote branch
    

Resolving merge conflicts#

When merging changes from different branches (or variants of a branch on different repos), the two branches may contain incompatible changes to one or more files. These are called “merge conflicts” and need to be manually resolved as follows:

  1. Check which files have merge conflicts:

    git status
    
  2. Edit the affected files and bring them to their intended final state. Make sure to remove the special “conflict markers” inserted by Git.

  3. Commit the affected files:

    git add <filenames>
    git merge --continue
    

When running the final command, Git may open an editor for writing a commit message. It is usually okay to leave that as-is and close the editor.

See the merge command’s documentation for a detailed technical explanation.

Making good PRs#

When creating a pull request for submission, there are several things that you should do to help ensure that your pull request is accepted.

  1. Make your change against the right version of Python. In general all changes are made against the main branch first. This includes bug fixes. After the change is merged there, it will be ported back to older maintenance releases as well. That way we ensure all affected versions are handled. Therefore, basing a new change directly on a maintenance branch is only used in specific circumstances, for instance when that change does not apply to main or the change requires a different approach in an older Python version compared to main.

  2. Make sure to follow Python’s style guidelines. For Python code you should follow PEP 8, and for C code you should follow PEP 7. If you have one or two discrepancies those can be fixed by the core developer who merges your pull request. But if you have systematic deviations from the style guides your pull request will be put on hold until you fix the formatting issues.

    Note

    Pull requests with only code formatting changes are usually rejected. On the other hand, fixes for typos and grammar errors in documents and docstrings are welcome.

  3. Be aware of backwards-compatibility considerations. While the core developer who eventually handles your pull request will make the final call on whether something is acceptable, thinking about backwards-compatibility early will help prevent having your pull request rejected on these grounds. Put yourself in the shoes of someone whose code will be broken by the change(s) introduced by the pull request. It is quite likely that any change made will break someone’s code, so you need to have a good reason to make a change as you will be forcing someone to update their code. (This obviously does not apply to new classes or functions; new arguments should be optional and have default values which maintain the existing behavior.) If in doubt, have a look at PEP 387 or discuss the issue with experienced developers.

  4. Make sure you have proper tests to verify your pull request works as expected. Pull requests will not be accepted without the proper tests!

  5. Make sure all tests pass. The entire test suite needs to run