Git Workflows That Scale With Your Team
- ShiftQuality Contributor
- Jan 16
- 4 min read
Git is flexible enough to support almost any workflow. This is a feature and a curse. A solo developer pushing directly to main works fine. A twenty-person team doing the same thing produces a main branch that's broken half the time.
The right Git workflow depends on your team size, deployment frequency, and risk tolerance. There's no universally correct answer — but there are workflows that clearly don't fit certain team sizes, and choosing the wrong one creates friction that compounds every day.
Solo Developer: Keep It Simple
If you're the only person working on the code, you don't need a branching strategy. You need version history and the ability to undo mistakes.
What works:
Commit directly to main
Commit often (small, focused commits rather than end-of-day dumps)
Use branches when experimenting on something risky ("Can I refactor this without breaking everything?")
Tag releases so you can roll back to known-good states
What you don't need: Pull requests, code review, branch protection, release branches. These are coordination tools for multiple people. With one person, they're ceremony without value.
Small Team (2-5 People): Feature Branches
The moment a second person joins, you need coordination. Feature branches provide it.
The workflow:
Create a branch from main for each feature or fix
Work on the branch, committing as you go
Open a pull request when the work is ready
Someone reviews the PR (not the author)
Merge to main after approval
Delete the feature branch
git checkout -b feature/add-search
# ... work, commit, push ...
git push -u origin feature/add-search
# Open PR, get review, merge
Branch naming: Use a consistent convention. feature/description, fix/description, chore/description. The prefix communicates intent. The description communicates scope.
PR size: Keep pull requests small — ideally under 400 lines of changed code. Large PRs get rubber-stamped because reviewing 2,000 lines is exhausting. Small PRs get meaningful review.
Code review: For small teams, every PR gets reviewed by one person. The reviewer isn't gatekeeping — they're catching mistakes the author is too close to see and spreading knowledge of the codebase across the team.
Medium Team (5-15 People): Branch Protection + CI
With more people, you need guardrails to prevent bad code from reaching main.
Branch protection rules:
Main branch requires a PR (no direct pushes)
PRs require at least one approval
CI checks must pass before merging
Branches must be up to date with main before merging
CI integration: Automated tests run on every PR. Linting, type checking, unit tests, integration tests — whatever your suite includes. The PR can't be merged until CI passes. This prevents "it worked on my machine" from becoming "it broke in production."
Merge strategy choices:
Merge commit: Creates a merge commit that preserves the full branch history. The main branch history shows when branches were merged. Good for traceability.
Squash and merge: Combines all branch commits into a single commit on main. Produces a clean main history where each commit represents a complete feature. Good for readability.
Rebase and merge: Replays branch commits on top of main. Produces a linear history without merge commits. Good for those who want a clean linear log.
Recommendation for most teams: Squash and merge. Each PR becomes one commit on main, the commit message describes the feature, and the main branch history reads like a changelog.
Trunk-Based Development: Continuous Integration
For teams that deploy frequently (multiple times per day), trunk-based development minimizes the overhead of branches.
The workflow:
Everyone commits to main (or to very short-lived branches that are merged within hours)
Feature flags gate incomplete work
CI runs on every commit
Deployment happens automatically when CI passes
Why it works: Long-lived branches accumulate merge conflicts and diverge from main. The longer a branch lives, the harder the merge. Trunk-based development eliminates this by keeping all work close to main at all times.
Why it's scary: Everyone's code goes to main quickly, which means broken code reaches main quickly. This requires strong CI (tests that catch real problems), feature flags (incomplete features are hidden from users), and a culture of small, incremental changes.
When to use it: Teams with strong CI, comprehensive tests, and the infrastructure for feature flags. If your test suite takes 30 minutes and catches most issues, trunk-based development can work. If your test suite takes 5 minutes and misses a lot, feature branches provide a safety buffer that trunk-based development doesn't.
Git Flow: When You Need Release Control
Git Flow (the Gitflow workflow by Vincent Driessen) uses multiple long-lived branches: main (production), develop (integration), feature branches, release branches, and hotfix branches.
When it fits: Software with versioned releases — mobile apps, desktop software, libraries, anything where "v2.3.1" means something. Environments where releases are planned, tested, and deployed on a schedule.
When it doesn't fit: Web applications deployed continuously. SaaS products. Anything where "the latest commit on main is production." Git Flow's overhead (multiple long-lived branches, release branches, hotfix branches) is unnecessary when you deploy every merge.
The honest take: Git Flow was designed in 2010 for a different era of software delivery. For most web-based teams deploying continuously, it's too complex. Feature branches with squash merge and CI are simpler and sufficient.
The Practices That Matter More Than the Workflow
Regardless of which workflow you choose:
Commit messages should explain why, not what. The diff shows what changed. The commit message should explain why. "Fix payment processing for international orders" is useful. "Update payment.js" is not.
Never commit secrets. No API keys, passwords, or connection strings in Git. Use .gitignore for .env files. If a secret is accidentally committed, rotating it is mandatory — removing it from Git history doesn't remove it from anyone who cloned the repo.
Pull frequently. The longer you work without pulling changes from main, the harder the merge. Pull daily at minimum. Rebase your branch on main regularly to keep conflicts small.
Delete merged branches. A repository with 200 stale branches is confusing. After a branch is merged, delete it. The commits are preserved in main's history.
Key Takeaway
Solo developers push to main. Small teams use feature branches with pull requests. Medium teams add branch protection and CI requirements. High-frequency deployment teams consider trunk-based development. Git Flow is for versioned release schedules, not continuous deployment. Regardless of workflow: keep branches short-lived, PRs small, commit messages meaningful, and secrets out of the repository.



Comments