Most Git workflow advice online is written for teams of 50. If you are 3 to 8 developers shipping to production several times a week, GitFlow is ceremony you do not need, and pure trunk-based development can feel reckless. Here is the middle ground my teams have settled on.
The shape of it
One long-lived branch: main. It is always deployable. Everything else is a short-lived branch that lives hours to two days, merges via pull request, and gets deleted.
main ──●──●────●────●──●──●──▶
\ / \ /
●──●──● ●──●
feature fix
No develop. No release/* unless you genuinely ship versioned artifacts. The fewer branches that must stay in sync, the fewer merge conflicts you will ever resolve.
Branch naming
Use a prefix that maps to your tracker. It costs nothing and makes git branch readable:
git switch -c feat/invite-teammates
git switch -c fix/webhook-timeout
git switch -c chore/bump-node
feat/, fix/, and chore/ cover 95% of real work.
Keep branches short
This is the single rule that matters most. A branch open for a week is a branch that will conflict. Break work into slices you can merge independently. If a feature needs a database migration, a backend endpoint, and a UI, merge the migration first, then the endpoint, then the UI. Each PR should be reviewable in under 20 minutes.
Rebase, do not merge, when syncing
While your branch is open, keep it current with main by rebasing:
git fetch origin
git rebase origin/main
This keeps history linear and makes review diffs honest. If you have already pushed and someone else pulled your branch, use --force-with-lease instead of --force so you do not clobber their work:
git push --force-with-lease
When the PR is approved, merge into main. Pick one strategy and never debate it again. We squash merge, so main gets one commit per PR with a clean message. If you prefer merge commits, that is fine too. Consistency beats correctness here.
Protect main, but lightly
On GitHub or GitLab, require:
- At least one approving review
- Passing CI
- Branch up to date before merge
That is it. Do not require two reviewers on a team of four. Do not require signed commits on day one. Every gate you add slows the loop, and small teams win by keeping the loop fast.
Write commits that help future you
Use Conventional Commits so changelogs and semantic versioning can be automated later:
feat: add teammate invite flow
Sends an email with a signed token. Token expires in 24h.
Squash merges mean the PR title becomes the commit, so enforce the same convention on PR titles.
Tag releases
When you deploy, tag it:
git tag -a v1.4.0 -m "Add teammate invites"
git push origin v1.4.0
Tags are your rollback anchors. When something breaks at 2am, git checkout v1.3.2 beats scrolling through 400 commits.
Hotfixes
Branch off main, fix, PR, merge, deploy, tag. No special hotfix branch. The process is identical to any other change, which means nobody has to remember a different procedure under pressure.
What to skip
-
developbranch: it just delays integration - Long-lived feature branches: they rot
- Release branches: only worth it if you ship binaries with backports
- Strict GitFlow: built for scheduled releases, not continuous deploys
The daily loop
git switch main && git pull
git switch -c feat/something
git commit -am "feat: something"
git fetch origin && git rebase origin/main
git push -u origin feat/something
# open PR, get review, squash merge, delete branch
That is the whole workflow. The best process for a small team is the one nobody has to think about. Keep branches short, keep main green, and spend your energy on the product instead of on Git.
For the commands themselves, the official Git reference is still the best source.
Top comments (1)
Some comments may only be visible to logged-in visitors. Sign in to view all comments.