Keep It Simple
Small teams don't need the complexity of Git Flow or the overhead of trunk-based development with feature flags. You need something that gets out of your way. Here's a workflow that has worked for my teams: main + short-lived feature branches.
The Core Rules
-
One permanent branch:
main. It's always deployable. Protect it with branch rules: require pull request reviews, status checks, and no direct pushes. -
Feature branches: Branch off
main, name themfeature/short-descriptionor justusername/description. Keep them short-lived (1-2 days max). - Pull requests: Every branch merges via PR. This triggers CI, code review, and a final sanity check.
-
Rebase before merge: Keep history linear. Rebase your feature branch onto
mainbefore merging.
Example Workflow
# Start a new feature
git checkout main
git pull
git checkout -b feature/add-login
# Work, commit, push
git add .
git commit -m "Add login form"
git push -u origin feature/add-login
# Open a PR on GitHub/GitLab/Bitbucket
# After review, rebase and merge
git checkout main
git pull
git rebase main feature/add-login # or: git checkout feature/add-login && git rebase main
git checkout main
git merge feature/add-login
git push
Why This Works
- No long-lived branches: Avoids the pain of merge conflicts from branches that drifted too far.
-
Simple mental model: Developers only need to think about
mainand their current branch. -
Easy rollbacks: If something breaks, revert the merge commit on
main. Since history is linear, reverts are clean. -
CI/CD friendly: Every push to
maincan trigger deployment. No staging branches needed unless your deployment process requires them.
Hotfixes
For urgent fixes, branch off main, fix, PR, merge. Then rebase any in-progress feature branches onto the new main.
git checkout main
git pull
git checkout -b hotfix/critical-bug
# fix, commit, push, PR
# after merge, rebase your feature branch
git checkout feature/in-progress
git rebase main
Avoiding Common Pitfalls
-
Don't merge
maininto your feature branch: Instead, rebase. Merging creates unnecessary merge commits and makes history messy. - Keep branches small: If a feature takes more than two days, split it. Large branches are hard to review and merge.
- Communicate: Let the team know when you're about to rebase or force-push (though with rebase before merge, force-pushing shouldn't be needed if you never push a rebased branch).
When to Level Up
This simple workflow can take a team of 2-10 developers a long way. When you start facing frequent conflicts, release coordination issues, or need multiple environments, consider adding:
- A
developbranch for integration testing (but beware: it adds complexity). - Release branches for versioning.
- Feature flags to merge incomplete features into
mainwithout deploying them.
But for most small teams, the overhead isn't worth it. Start simple, and only add complexity when the pain is real.
Summary
- One permanent branch:
main. - Short-lived feature branches, rebased before merge.
- PR-based code review and CI.
- Hotfixes follow the same pattern.
This workflow keeps your Git history clean, your deployments predictable, and your team focused on building features instead of fighting with Git.
Top comments (0)