GitHub Flow Best Practices
GitHub Flow is a lightweight, branch-based workflow that enables teams to deploy frequently. This guide covers proven best practices for branch naming, pull request size, code reviews, and building a productive collaboration culture.
GitHub Flow is a simple, branch-based workflow that supports teams that deploy frequently. It has only a few core rules: Anything in the main branch is always deployable. To work on something new, create a descriptive branch off main. Push that branch to GitHub and open a pull request to start discussion. After review and passing tests, merge the branch into main. Deploy immediately after merging.
Unlike Git Flow (which uses develop, release, and hotfix branches), GitHub Flow keeps things simple. This works well for teams practicing continuous delivery where features are deployed as soon as they're ready. The entire workflow revolves around pull requests, which serve as the center for code review, discussion, and automation.
Consistent branch naming helps team members understand the purpose of each branch at a glance. A good branch name is descriptive, follows a consistent pattern, and includes context about what work is being done.
Recommended naming patterns: Use prefixes to indicate the type of work. For features: feature/login-page or feature/user-authentication. For bug fixes: fix/header-alignment or fix/null-pointer-exception. For hotfixes (urgent production fixes): hotfix/payment-processing. For documentation: docs/api-update. For experiments or exploratory work: experiment/new-algorithm or draft/wip-feature.
Include ticket numbers: If your team uses issue tracking, include the ticket number: feature/42-add-search-bar or fix/123-login-error. This makes it easy to trace branches back to requirements. Keep branch names concise but descriptive—use hyphens to separate words, not spaces or underscores.
# Good branch names
feature/user-profile-avatar
fix/login-button-alignment
hotfix/security-patch-2.1.0
docs/readme-update
experiment/caching-strategy
# With ticket numbers
feature/123-add-pagination
fix/456-api-timeout
hotfix/789-session-expiry
# Avoid these
fix (too vague)
my_changes (no context)
test (ambiguous)
PR size is one of the most important factors in effective code review. Research shows that review effectiveness drops significantly when PRs exceed 400 lines. Larger PRs lead to superficial reviews, missed bugs, and longer cycle times.
Aim for 200-400 lines per PR. This is the sweet spot—small enough to review thoroughly, large enough to be meaningful. Break down work into logical chunks. A single feature might be split into multiple PRs: first add data models, then implement business logic, then create the UI, and finally wire everything together.
One logical change per PR. Avoid mixing refactoring with new features. Keep bug fixes separate from feature work. If you're both fixing a bug and improving performance, that's probably two PRs. The reviewer should be able to understand the complete change in one sitting (15-20 minutes).
A good PR description answers three questions: What changed? Why did it change? How was it tested? Write descriptions that help reviewers understand context without digging through code.
Use a template. Many teams use a PR template in .github/pull_request_template.md that includes sections for description, related issues, testing performed, and screenshots (for UI changes). This ensures consistency across all PRs.
Link to issues. Include Fixes #123 to automatically close linked issues when the PR merges. This keeps your project management in sync with your code.
# .github/pull_request_template.md
## Description
[Describe the changes in this pull request]
## Related Issue
Fixes #(issue number)
## Type of Change
- [ ] Bug fix
- [ ] New feature
- [ ] Breaking change
- [ ] Documentation update
## Testing Performed
- [ ] Unit tests added/updated
- [ ] Manual testing performed
## Screenshots (if applicable)
[Add screenshots for UI changes]
Review within 24 hours. Stale PRs accumulate context loss and frustration. Make PR review a priority—it's part of everyone's job, not just the author's. Set team expectations that PRs should be reviewed within one business day.
Be kind and constructive. Comment on the code, not the person. Use phrases like "What do you think about..." instead of "This is wrong." Ask clarifying questions. Suggest solutions, not just problems.
Distinguish between blocking and non-blocking feedback. Use "nit:" or "optional:" for style preferences or non-critical suggestions. This signals that the author can choose to accept or ignore the feedback. Reserve "request changes" for actual blocking issues.
Explain why. Don't just say "change this." Explain why the change would improve the code. "This would be more readable because..." or "This pattern prevents a common bug when..." helps the author learn.
Don't take it personally. Feedback is about the code, not about you. Everyone receives feedback—it's how code gets better. Say "Thanks for the catch!" and move on.
Push back respectfully. If you disagree, explain your reasoning with examples or data. A comment like "I considered that approach, but it would cause X problem because..." is productive. Avoid defensive responses.
Apply suggestions quickly. When a reviewer suggests a specific change, use GitHub's "Commit suggestion" button. It applies the change with one click and credits the reviewer as co-author.
Request re-review after changes. Use the "Re-request review" button to notify reviewers that you've addressed their feedback. Don't assume they'll see your pushes.
Automation reduces the cognitive load on human reviewers. Use GitHub Actions to run automated checks on every PR. These should include: linters (code style), unit tests (functionality), integration tests (end-to-end), security scanning (SAST), and dependency checks (Dependabot).
Require passing status checks before merging. Configure branch protection to block merging until all required checks pass. This ensures that broken tests never reach main.
Use GitHub's built-in features. Enable "Automatically delete head branches" after merging to keep the branch list clean. Enable "Allow squash merging" to keep history linear. Enable "Require linear history" to prevent merge commits on main.
# Example CI checks required before merge
Required status checks:
- CI / tests
- CI / lint
- CodeQL / security-scan
# Branch protection settings
- Require a pull request before merging
- Require status checks to pass
- Require branches to be up to date
- Require linear history
- 50-200 lines: Ideal. Quick to review, low cognitive load, high review quality.
- 200-400 lines: Acceptable. Still manageable, but review quality begins to decline.
- 400-1000 lines: Problematic. Reviewers will skim, missing subtle bugs.
- 1000+ lines: Unacceptable. Split into multiple PRs.
- Does the code work as expected? (Run it locally if possible)
- Are there tests covering the changes?
- Is the code readable and maintainable?
- Does it follow the team's coding standards?
- Are there any security concerns?
- Is error handling appropriate?
- Are comments/documentation updated?
- Is the performance appropriate?
Long-lived branches. Branches that live for weeks accumulate massive changes and conflicts. Merge to main at least every 2-3 days, or use feature flags to hide incomplete work.
Giants PRs. Don't open a 3000-line PR that does ten different things. The review will be superficial, and merging will be painful. Split into logical chunks.
No automated checks. Relying on humans to catch formatting errors and test failures wastes everyone's time. Automate everything that can be automated.
Bikeshedding. Don't spend hours arguing about naming conventions or formatting. Use automated formatters (Prettier, Black) to eliminate style debates.
Ignoring PRs. Stale PRs accumulate technical debt. Set a team policy: reviewers respond within 24 hours, authors address feedback within 48 hours.
A healthy code review culture doesn't happen by accident. It requires intentional practice. Start by praising good work in reviews—"This approach is elegant!" or "Great catch on that edge case." Specific praise reinforces good practices.
Rotate reviewers. Don't let the same people review all PRs. Spread knowledge across the team. Newer team members should review as well—it's a great way to learn the codebase.
Celebrate good reviews. Acknowledge thorough, helpful reviews in team meetings or retrospectives. This reinforces the behavior you want to see.
Have a style guide. Most review friction comes from subjective preferences. A written style guide with examples eliminates endless debates about naming, formatting, and structure.
GitHub Flow is simple, but following best practices makes it effective. Small PRs, timely reviews, and a positive culture lead to faster shipping and better code.