Case Study: How Open Source Projects Use Git
The Scenario
You've learned Git basics — init, add, commit, branch, merge. But how do these commands scale when thousands of developers across dozens of countries contribute to the same project simultaneously? Let's look at three of the most successful open-source Python projects and see how they use Git to coordinate massive collaboration.
CPython: The Language Itself
CPython is the reference implementation of Python — the interpreter you installed in Chapter 2. Its Git repository on GitHub has more than 130,000 commits spanning more than three decades of development (the history was imported from older version control systems when the project moved to Git and GitHub). A core team of developers and thousands of occasional contributors keep it running.
How They Branch
CPython maintains multiple active branches simultaneously:
main— the development branch for the next feature release3.13,3.14, and so on — maintenance branches for released versions. The newest ones receive bug fixes; older ones get only security patches until they reach end of life.
When a developer finds a bug that also affects Python 3.14, the fix still goes into main first. After it's reviewed and merged, a core developer adds a label such as needs backport to 3.14, and a bot named miss-islington cherry-picks the fix (copies that one commit) onto the maintenance branch as a new pull request. Released versions get the fix without being destabilized by the new features piling up on main.
How They Handle Contributions
CPython uses the fork-and-pull-request model:
- A contributor forks the CPython repository on GitHub
- They create a branch in their fork (e.g.,
fix-urllib-timeout) - They make changes, write tests, and commit
- They open a pull request against the main CPython repo, with a title that starts with the issue number (
gh-NNNNN: ...) - Core developers review the code — often multiple rounds of feedback
- Automated tests run on every pull request (Windows, macOS, Linux)
- A core developer merges the PR after approval
What We Can Learn
CPython's CONTRIBUTING.rst file on GitHub is short. Mostly it points you to the Python Developer's Guide (devguide.python.org), a whole website about how to contribute. Among other things, the guide tells you to:
- Link your pull request to an issue by starting its title with gh- and the issue number
- Write the first line of each commit message in the imperative ("Make the spam module more spammy"), with no period at the end
- Run the test suite and make patchcheck before submitting
- Follow PEP 8 for Python code and PEP 7 for C code
- Add a NEWS entry describing most user-visible changes
Even the world's most experienced Python developers follow these conventions. The lesson: conventions aren't bureaucracy — they're how hundreds of people work together without chaos.
Django: The Web Framework
Django is one of the most popular web frameworks in any language. Its Git repository has nearly 35,000 commits from thousands of contributors.
Commit Message Discipline
Django has famously strict commit message standards. Its committing guidelines say:
- If a commit fixes a ticket in Django's issue tracker, the message starts with Fixed # and the ticket number; if it's related to a ticket without closing it, it uses Refs #
- Messages are written in the past tense ("Fixed," "Added"), and the subject line ends with a period
- Lines stay within about 72 characters, with a blank line between the subject and any further explanation
Here are real Django commit messages:
Fixed #37405 -- Fixed crash if sort_keys option is used with YAML serializer.
Refs #37065 -- Added missing await in method_decorator example.
Fixed #37381 -- Corrected execute_wrapper() module reference in docs.
Notice the pattern: Fixed #XXXXX -- Description or Refs #XXXXX -- Description. Anyone reading the history can jump from a commit to the ticket that explains why it was needed.
Wait, past tense? Didn't Section 25.9 tell you to use the imperative ("Fix," not "Fixed")? It did, and the imperative is the more common convention: Git's own project and CPython both use it. Django simply chose differently. The real rule is follow the convention of the project you're working in. Consistency within one history matters far more than which style wins.
The Release Branch Strategy
Django uses a disciplined release process:
main ──────────────────────────────────────────────────────►
│ │ │
└── stable/5.2.x └── stable/6.0.x └── stable/6.1.x
(long-term (previous (current
support) release) release)
Each stable/A.B.x branch is split off from main when that release's features are frozen. New features only ever go to main. Bug fixes are also merged into main first and then backported (cherry-picked) onto the stable branches that still need them. Security fixes are applied to main and every supported release branch, and shipped as coordinated releases.
What We Can Learn
Django proves that commit message discipline pays dividends. When a user reports a bug, developers can search the commit history for related changes, understand the original reasoning, and fix the problem without introducing new bugs. Sloppy commit messages like "fix stuff" make this archaeology impossible.
Requests: Small Project, Big Impact
The requests library ("HTTP for Humans") is one of the most-downloaded Python packages, with billions of downloads. Despite its massive user base, the project has a relatively small team of maintainers.
Simplicity at Scale
Requests uses a simpler Git workflow than CPython or Django:
main— current development- Feature branches — for each change
- Tags — to mark releases (e.g.,
v2.31.0)
The project's CONTRIBUTING.md points you to a longer Contributor's Guide and then lists a few blunt rules for pull requests:
- Search first, so you don't open a duplicate pull request
- Include tests that fail without your change, so the bug can't quietly return
- Run the test suite locally before submitting
- Write commit messages that explain why the change was made, not just which issue it fixes
The Human Side of Git
One lesson from the requests project is that Git is as much about communication as it is about code. Pull request descriptions, commit messages, and code review comments are all forms of written communication. The projects that thrive are the ones where contributors write clearly, respond respectfully, and assume good intent.
The library's tagline, "HTTP for Humans," sums up what Kenneth Reitz built it for: a pleasant experience for the developers who use it. The same idea applies to the people who contribute to it, and clear Git practices are a big part of that experience.
Common Patterns Across All Three Projects
Despite their differences in size and scope, these projects share several Git practices:
| Practice | CPython | Django | Requests |
|---|---|---|---|
| Fork + PR workflow | Yes | Yes | Yes |
| Named release branches | Yes (3.14) |
Yes (stable/6.0.x) |
No (tags only) |
| Required automated tests on PRs | Yes | Yes | Yes |
| Commit message standards | Yes | Strict | Moderate |
| Code review before merge | Yes | Yes | Yes |
.gitignore maintained |
Yes | Yes | Yes |
Contributing guide (CONTRIBUTING file) |
Yes | Yes | Yes |
The Contribution Funnel
All three projects follow a pattern called the "contribution funnel":
- Issue — someone reports a bug or proposes a feature
- Discussion — the community discusses whether and how to address it
- Fork + Branch — a contributor creates a branch to work on the solution
- Pull Request — the work is submitted for review
- Review — maintainers examine the code, tests, documentation
- Revision — the contributor addresses feedback (often multiple rounds)
- Merge — a maintainer merges the approved PR
- Release — the change ships in the next version
Steps 3-6 rely entirely on Git. Without version control, this workflow would be impossible.
Discussion Questions
-
Why do all three projects require contributors to create branches rather than committing directly to
main? What would happen if 50 developers all committed tomainat the same time? -
Django commit messages reference a ticket number (
Fixed #...orRefs #...) whenever the change relates to a ticket. What advantages does this create? Can you think of any downsides? -
The contribution funnel shows that getting code merged into a major project involves much more than writing the code. Why is code review so important? What kinds of problems does it catch that automated tests might miss?
-
If you wanted to make your first contribution to an open-source project, which of these three projects would you choose to start with? Why? What would you look for in a project to decide if it's beginner-friendly?
-
Think about the role of
.gitignoreandCONTRIBUTING.mdin these projects. How do these non-code files contribute to the project's success?
Mini-Project
Choose a small open-source Python project on GitHub (look for projects with the "good first issue" label). Without submitting anything, practice the contribution workflow:
- Fork the repository on GitHub
- Clone your fork to your local machine
- Create a feature branch with a descriptive name
- Read the project's
CONTRIBUTING.md(if it has one) - Look at the last 10 commit messages — do they follow a pattern?
- Look at the most recent pull request — what did the review process look like?
- Write a brief report (in a text file in your local clone) summarizing the project's Git conventions and what you'd need to do to contribute
Don't worry about actually making code changes — this exercise is about understanding the workflow and conventions.