The biggest source of Git chaos on teams isn't Git itself — it's not agreeing on a strategy. Here's the workflow we use across our own development team and client projects.
1Choose One Branching Strategy and Stick to It
Two approaches cover the vast majority of teams:
Trunk-based development — short-lived feature branches merged into main frequently (daily or every few days), often behind feature flags. Best for teams that deploy continuously.
GitFlow — separate main, develop, feature/*, release/*, and hotfix/* branches. Best for teams with scheduled releases (e.g. versioned software, client sign-off cycles).
main branch that's always deployable, short feature branches, and frequent merges.
2Branch Naming Conventions
Consistent naming makes it obvious what a branch does before anyone opens it:
feature/pos-inventory-sync
fix/checkout-total-rounding-bug
hotfix/login-session-expiry
chore/update-composer-dependencies
Prefix by type (feature, fix, hotfix, chore, refactor), then a short kebab-case description. Include a ticket number if you use a tracker:
feature/JT-142-pos-inventory-sync
3Commit Message Conventions
Adopt Conventional Commits — it makes history readable and enables automated changelogs:
feat: add barcode scanning to POS checkout
fix: correct VAT calculation on discounted items
refactor: extract invoice PDF generation into a service class
docs: update API authentication guide
chore: bump laravel/framework to ^13.0
Rules that matter more than the format itself:
- One logical change per commit — don't bundle a bug fix with an unrelated feature
- Write the message in the imperative mood ("add" not "added")
- The first line should be understandable without opening the diff
4Pull Requests and Code Review
- Keep PRs small — under ~400 lines of diff when possible. Large PRs get rubber-stamped, not reviewed.
- Write a PR description that explains why, not just what — the diff already shows what changed.
- Require at least one approval before merging to
main, even on small teams. - Use draft PRs for work-in-progress so teammates know what's not ready for review yet.
5Keeping Branches in Sync
Rebase your feature branch on main regularly instead of letting it drift for weeks:
git fetch origin
git rebase origin/main
This surfaces conflicts early, in small pieces, instead of one massive conflict resolution when you finally try to merge.
6Handling Merge Conflicts
Most conflicts happen because a branch lived too long. When one does occur:
git status # see which files conflict
# resolve conflict markers in each file
git add <resolved-file>
git rebase --continue # if rebasing
# or
git commit # if merging
main.
7Protecting Your Main Branch
On GitHub/GitLab/Bitbucket, enable branch protection on main:
- Require pull request reviews before merging
- Require status checks (tests, linting) to pass before merging
- Disallow force-pushes to
main - Restrict who can merge directly
This one setting change prevents the most common "someone pushed straight to main and broke production" incident.
Setting up Git workflows or CI/CD for your team?
We help teams build reliable development processes as part of our software development services.
Get Free Quote →8Frequently Asked Questions
GitFlow or trunk-based development — which should my team use?
If you deploy continuously and have a small-to-mid-size team, trunk-based development with short feature branches is simpler and faster. If you ship versioned releases with QA sign-off cycles, GitFlow's structure is worth the extra overhead.
How often should I merge my feature branch?
As often as the feature is in a working, reviewable state — ideally every 1–3 days. Long-lived branches are the single biggest cause of painful merge conflicts.
Should junior developers be allowed to merge to main?
Yes, once branch protection requires at least one senior review and passing tests. The protection rules should enforce quality — not developer seniority.