Skip to content
X

Team Development Workflow - Complete GitHub Flow Guide

Working alone lets you move freely, but as soon as you join a team, rules become necessary. “Someone’s change broke my code,” or “I can’t tell which branch is up to date” — these problems are exactly what a team development workflow prevents.

This article explains the standard practices for working as a team on GitHub.

GitHub Flow is a simple branching strategy centered around the main branch. It avoids complex branch management and enables frequent releases.

1. Create a new branch from main
2. Commit changes on the branch
3. Open a Pull Request
4. Receive a code review
5. Merge into main
6. Deploy

Repeat this cycle. There are no complex rules.

Another well-known branching strategy is Git Flow. Here is a comparison of the two:

ComparisonGitHub FlowGit Flow
Number of branchesmain + feature branchesmain, develop, feature, release, hotfix — 5 types
ComplexitySimpleComplex
Release frequencyContinuous (suited for continuous deployment)Planned releases
Best forWeb services, SaaSLibraries and apps requiring versioned releases

GitHub Flow is recommended for most web service development. If your release process is complex and requires careful scheduling, consider Git Flow.


Branch names should make it immediately clear what work is being done on that branch. Consistent naming helps the entire team understand the state of the project at a glance.

PrefixPurposeExample
feature/New feature developmentfeature/user-authentication
fix/Bug fixesfix/login-button-not-responding
hotfix/Emergency fixes for productionhotfix/payment-error
chore/Tests, configuration, dependency updateschore/update-dependencies
docs/Documentation updatesdocs/api-reference
refactor/Refactoring (no behavior change)refactor/auth-module
RatingExampleReason
Goodfeature/add-search-functionClearly states what will be done
Goodfix/issue-42-null-pointerIssue number makes it easy to trace
BadtestContent is unclear
Badjohn-branchA person’s name tells you nothing about the content
BadfixDoes not say what is being fixed
Badnew featureSpaces in branch names can cause problems

Use lowercase letters, numbers, and hyphens in branch names. Avoid spaces and non-ASCII characters.


Commit messages are the history of your code changes. A good message conveys not just “what changed” but “why it changed.”

Conventional Commits is a specification for standardizing commit message formats.

Format: <type>(<scope>): <description>

TypeMeaningExample
featNew featurefeat: add user search functionality
fixBug fixfix: login button not responding
docsDocumentation changedocs: add setup instructions to README
styleCode formatting (no behavior change)style: fix indentation
refactorRefactoring (no behavior change)refactor: extract auth logic into function
testAdding or fixing teststest: add unit tests for login feature
choreBuild config, dependency updateschore: update eslint to v8
ciCI configuration changesci: fix GitHub Actions workflow
# Good example
feat(auth): add password reset feature

Added the ability for users to request a password reset link
by entering their email address.

Closes #78

# Bad examples
fix
update
asdfghjkl

Each commit should contain exactly one logical change. Combining “add login feature” and “change header design” in the same commit makes it difficult to track issues later.


The smaller a PR, the better. Large PRs overwhelm reviewers and lead to lower-quality reviews.

PR SizeApproximate Line CountReviewability
Small (ideal)Up to 200 linesEasy to review with full focus
Medium (acceptable)200–400 linesReviewable with careful reading
Large (caution)400+ linesCreates a significant burden on reviewers
## What Changed
- Added user search feature
- Added a component to display search results

## Why This Change
Addressing the user request in Issue #42.
Users lacked a way to search for other users by name.

## How to Test
1. Start the application
2. Type a name into the search bar in the header
3. Confirm that search results appear

## Screenshots
(Before) (After)

## Related Issue
Closes #42

Before opening a PR, review your own changes first. Looking at the diff in the “Files changed” tab often reveals typos or leftover debug code.


The purpose of code review is to improve code quality and share knowledge across the team. It is not about finding fault.

TypeStyleExample
Required change[must] or direct request[must] This has a SQL injection vulnerability
Suggestion[nit] or a question[nit] A more specific variable name might make this easier to read
QuestionAsk what/whyWhat scenario does this condition handle?
PraisePositive commentThis approach is clean and simple!
ActionMeaningWhen to Use
CommentComment onlyYou have questions or suggestions, but do not want to block the merge
ApproveApprovedReady to merge as-is or after minor fixes
Request changesChanges requiredMust be fixed before merging
  • Critique the code, not the person
  • Explain why something is a problem
  • Actively praise good code
  • Aim to respond within 24 hours
  • Do not take review comments personally
  • Reply “fixed” to let the reviewer know about changes
  • It is fine to discuss disagreements
  • You can merge once you receive an Approve

Branch protection rules prevent accidental or unauthorized changes to the main branch. Rules like “no merge without a review” or “no merge if tests fail” are automatically enforced.

Go to “Settings” → “Branches” → “Add branch protection rule.” Enter main in the “Branch name pattern” field and configure the following settings.

SettingDescriptionRecommendation
Require a pull request before mergingA PR is required to mergeEnable
Required number of approvalsMinimum number of ApprovalsAt least 1
Dismiss stale pull request approvals when new commits are pushedNew commits reset existing ApprovalsEnable
Require status checks to pass before mergingCI tests must passEnable
Require branches to be up to date before mergingBranch must be up to date before mergingEnable
Do not allow bypassing the above settingsAdministrators cannot bypass rulesConsider enabling
Allow force pushesPermit force pushesDisable

CODEOWNERS is a mechanism that automatically assigns the right people as reviewers when files they own are changed.

# Format: <pattern> <GitHub username or team>

# Assign @alice to all file changes
* @alice

# frontend/ changes require review from @bob and @carol
frontend/ @bob @carol

# Core backend logic is owned by @backend-team
src/core/ @myorg/backend-team

# Documentation changes go to @docs-team
*.md @myorg/docs-team

# Security-sensitive files always require @security-team review
.github/workflows/ @myorg/security-team

When combined with the “Require review from Code Owners” branch protection setting, important files are guaranteed to be reviewed by their designated owners.


When merging a PR, GitHub offers three options. Agree on one as a team to keep your history readable.

Merge StrategyCharacteristicsBest For
Merge commitAll commits are preserved; a merge commit is createdWhen you want to retain the full history of every change
Squash and mergeAll commits on the branch are squashed into oneWhen you want a clean, readable history on main
Rebase and mergeNo merge commit; creates a linear historyWhen you want to keep main history perfectly linear

“Squash and merge” is recommended for beginner teams. It keeps work-in-progress commits (like “WIP” or “fix typo”) off main, resulting in a cleaner history.


A Milestone is a feature for grouping Issues and PRs toward a specific release or deadline.

Create one at “Issues” → “Milestones” → “New milestone.” Set a title (e.g., v1.0.0 Release) and a due date, then attach related Issues to the milestone.

A progress percentage is displayed, giving you an at-a-glance view of how much work remains before the release.

Good release notes include the following:

## v1.2.0 (2026-03-21)

### New Features
- Added user search (#42)
- Dark mode support (#55)

### Bug Fixes
- Fixed login button not responding in certain environments (#61)
- Fixed profile image not displaying correctly (#63)

### Breaking Changes
- Minimum supported Node.js version is now v18

These are practices to avoid in team development.

# Never do this
git push origin main

Direct pushes to main are forbidden. Always create a branch and merge through a PR. Branch protection rules can physically prevent this.

A PR with over 1,000 lines is practically impossible to review effectively. Split features into smaller, separate PRs.

Skipping a review because you are “in a hurry” is dangerous. Many production incidents originate from unreviewed changes.

Pull the latest main changes into your branch and resolve any conflicts before opening a PR.

Messages like “fix,” “update,” or “asdf” make it impossible to understand what changed later.

Do not use git push --force on branches shared with others. It can overwrite teammates’ commits. If unavoidable, use --force-with-lease and notify your team in advance.


Q. Should I choose GitHub Flow or Git Flow?

Section titled “Q. Should I choose GitHub Flow or Git Flow?”

GitHub Flow is recommended for most web service development. Git Flow has many branches to manage and a steeper learning curve. Start with GitHub Flow, and consider Git Flow only if you need to maintain multiple versions simultaneously.

Q. Is it okay to write commit messages in a language other than English?

Section titled “Q. Is it okay to write commit messages in a language other than English?”

As long as your team agrees, any language is fine. However, English is the standard for open source projects and international teams. The Conventional Commits format (feat:, fix:, etc.) can be used regardless of language.

Q. What should I do when reviewers disagree?

Section titled “Q. What should I do when reviewers disagree?”

Try to resolve the disagreement through written discussion first. If that does not work, discuss it verbally or in a meeting. Keep the focus on the shared goal of improving code quality, not on personal opinions.

Q. I set up branch protection rules and now no one can merge.

Section titled “Q. I set up branch protection rules and now no one can merge.”

If “Require approvals” is set to 1 or more and no one has Approved the PR, merging is blocked. Have another team member Approve the PR. If you are a solo developer, set the required number of approvals to 0 or adjust the branch protection settings accordingly.

Q. Does squash and merge delete my commit history?

Section titled “Q. Does squash and merge delete my commit history?”

The original branch still exists unless you delete it. The individual commits will no longer appear in main’s history, but you can still view them on the original branch or from the PR page.