The GitHub Flow is the collaboration workflow that GitHub is built around. It is designed to be simple, repeatable, and safe — keeping the main branch always deployable while allowing any number of developers to work on separate changes simultaneously without stepping on each other's work.
The flow works whether you are collaborating with a small team in a shared repository or contributing to a large open source project through forks. The mechanism at its centre is the pull request — a formal proposal to merge a branch into another, with built-in tools for discussion, review, and approval.
The Eight Steps
1. Fork (if needed) or create a branch
2. Create a topic branch
3. Make commits
4. Push the branch to GitHub
5. Open a pull request
6. Discuss and iterate
7. Merge
8. Sync and clean up
Each step is deliberate. The flow ensures that no change reaches the main branch without having been reviewed.
Step 1 — Fork or Branch
How you start depends on your relationship to the repository:
- You have write access (you are a collaborator or it is your own repository): create a branch directly in the repository. No fork needed.
- You do not have write access (contributing to someone else's project): fork the repository first, then clone and branch from your fork.
Both paths converge at the same point — a branch with your changes that you will push to GitHub and open a pull request from.
Step 2 — Create a Topic Branch
Never work directly on main. Create a descriptively named branch for the specific change you are making:
git switch -c feature/dark-mode
git switch -c fix/login-redirect
git switch -c docs/update-readme
The branch name should communicate the purpose of the work at a glance. GitHub displays branch names prominently throughout the pull request interface — a clear name helps reviewers understand what they are looking at before they read a single line of code.
Step 3 — Make Commits
Work on your branch, committing regularly:
git add .
git commit -m "Add dark mode toggle to settings panel"
Each commit should be focused and its message should describe what changed and why. Frequent, small commits are preferable to one large commit at the end — they make the pull request easier to review and easier to revert if something goes wrong.
Step 4 — Push the Branch to GitHub
Push your branch to the remote repository (your fork or the shared repository):
git push -u origin feature/dark-mode
The -u flag sets up tracking so future pushes on this branch can use just git push. After pushing, GitHub detects the new branch and displays a prompt offering to open a pull request from it. You can push additional commits to the branch at any time — the pull request will update automatically.
Step 5 — Open a Pull Request
Go to GitHub and open a pull request from your branch. GitHub's interface guides you through:
- Base branch — the branch you want to merge into (usually
main). - Compare branch — your topic branch with the changes.
- Title — a concise summary of what the PR does.
- Description — an explanation of what changed, why it was needed, and any context a reviewer needs. Link to relevant issues.
A good pull request description answers three questions: what does this change do, why was it necessary, and how was it implemented? A PR with no description forces reviewers to reconstruct that context themselves.
Draft pull requests
If you are not ready for review but want to signal that work is in progress, open a draft pull request. Draft PRs trigger notifications but are clearly marked as not ready for review. Convert them to ready when the work is complete.
Step 6 — Discuss and Iterate
Once a pull request is open, the review process begins. Reviewers can:
- Leave comments on specific lines of code.
- Leave general comments on the PR as a whole.
- Request changes — marking the PR as needing more work before it can be merged.
- Approve — signalling that the changes are ready.
You respond to feedback by making additional commits to the same branch and pushing them. The pull request updates automatically — there is no need to close and reopen it. Every commit added to the branch appears in the PR timeline, and reviewers can see exactly what changed in response to their feedback.
The discussion continues until the reviewer is satisfied or the PR is closed without merging.
Step 7 — Merge
Once the pull request is approved and any required status checks (automated tests, CI) have passed, it is ready to merge. GitHub offers three merge strategies:
| Strategy | What It Does | When to Use |
|---|---|---|
| Merge commit | Creates a merge commit joining the two branches | When you want to preserve the full history of the branch |
| Squash and merge | Combines all commits from the branch into one commit on main | When the branch has messy intermediate commits and you want a clean history |
| Rebase and merge | Replays the branch's commits onto main without a merge commit | When you want a linear history without a merge commit |
After merging, GitHub offers to delete the branch — do this. The branch has served its purpose. Keeping merged branches around clutters the branch list and can cause confusion.
Step 8 — Sync and Clean Up
After the merge, update your local main to reflect the merge:
git switch main
git pull origin main
If you were working from a fork, also sync your fork with the upstream:
git fetch upstream
git merge upstream/main
git push origin main
Delete the local branch:
git branch -d feature/dark-mode
The cycle is complete. Your change is in main and the working environment is clean for the next piece of work.
The Flow for Open Source Contributions
When contributing to a project you don't own, the flow includes the fork step:
# 1. Fork on GitHub (click the Fork button)
# 2. Clone your fork
git clone git@github.com:your-username/project.git
cd project
# 3. Add the original as upstream
git remote add upstream https://github.com/original-owner/project.git
# 4. Create a topic branch
git switch -c fix/broken-link
# 5. Make changes and commit
git commit -a -m "Fix broken documentation link"
# 6. Push to your fork
git push -u origin fix/broken-link
# 7. Open a pull request on GitHub
# (from your fork's branch to the original repository's main)
# 8. After merge, sync your fork
git fetch upstream
git switch main
git merge upstream/main
git push origin main
git branch -d fix/broken-link
Why the GitHub Flow Works
The flow's simplicity is its strength. A few rules — always branch, never push directly to main, always review before merging — create a shared standard that scales from a two-person team to a project with thousands of contributors. Everyone follows the same steps, so the overhead of coordination is low and the history of main stays clean and meaningful.
The pull request is not just a merge mechanism — it is a conversation. The review process catches bugs, improves code quality, spreads knowledge across the team, and creates a permanent record of why changes were made. Even on solo projects, opening pull requests from branches (rather than pushing directly to main) creates a habit of reviewing your own work before it becomes permanent.