- History stays clean
- Merge conflicts are rare (and small when they happen)
- Production is always stable
- Work-in-progress is easy to manage
Goals
Stable Main
main is always deployable and production-readyShort-lived Branches
Every change goes through a short-lived branch
Clear Communication
Branch names and commits tell you what changed and why
Minimal Conflicts
Conflicts minimized through small branches and frequent syncs
Branch Types
We keep it simple and modern:main– production-ready, stable codedev(optional, for larger teams) – integration branch, where feature branches are merged before going tomainfeature/*,fix/*,chore/*– topic branches for actual work
Solo or Small Team
Just use
main + feature/* branches. Merge feature/* → main via pull requests (even if it’s just you).mainfeature/*branches
Larger Collaborator Team
Use a three-tier approach:
feature/* → dev → (when stable) → mainmain(production)dev(integration)feature/*(work branches)
Branch Naming Rules
Use clear, structured names that match your commit prefixes:Feature Branches
Feature Branches
feature/rn-sdk-uploadfeature/flutter-auth-supportfeature/user-profile-endpoint
Fix Branches
Fix Branches
fix/login-null-crashfix/api-timeout-errorfix/sdk-type-definitions
Chore Branches
Chore Branches
chore/update-depschore/regenerate-sdkchore/cleanup-old-files
Refactor Branches
Refactor Branches
refactor/api-client-structurerefactor/auth-flow-logicrefactor/database-queries
Hotfix Branches
Hotfix Branches
hotfix/handle-500-error-in-prodhotfix/critical-security-patchhotfix/payment-gateway-issue
Complete Workflow
Step 1: Create a New Feature Branch
Merge Strategy
Squash & Merge (Recommended)
All commits in
feature/* are squashed into one commit on main.mainhistory stays clean (one commit per feature)- Small, readable Git log
- Easier to revert a feature if needed
Rebase & Merge (Alternative)
Keeps individual commits from the feature branch, but rewrites history to be linear. Good if you have very clean small commits.
When to Branch
✅ Create a branch when...
✅ Create a branch when...
- You’re working on anything that will take more than ~30–60 minutes
- You’re adding a feature, fixing a bug, or doing a refactor
- You’re experimenting, but might want to keep or scrap the work later
❌ Don't commit directly to main unless...
❌ Don't commit directly to main unless...
- It’s an ultra-trivial change (e.g., fixing a typo in README)
- And even then—it’s often better to still use a branch + PR for consistency
Minimizing Merge Conflicts
1. Keep Branches Short-lived
2. Sync with Main Regularly
On your feature branch, do this often:Rebasing keeps history linear and clean
3. Avoid “Big Bang” Changes
❌ Don't Do This
Combine formatting + huge refactor + new features in one branch
✅ Do This Instead
Run formatter in separate
chore/formatting branch and merge it first4. Own Specific Areas
If two people keep editing the same files, conflicts are inevitable. Coordinate ownership:
- SDK core client → one owner at a time
- Auth flows → one owner at a time
- Huge config files → modify carefully and incrementally
Command Cheat Sheet
Start New Work
Start New Work
Add & Commit
Add & Commit
Sync with Main
Sync with Main
Push and Open PR
Push and Open PR
After PR Merge
After PR Merge
Handling Merge Conflicts
When conflicts occur duringgit rebase origin/main or merge:
Example: SDK Change Workflow
Scenario: You add a new endpoint to your API and then regenerate the React Native SDK.
Backend Repository
SDK Repository
Do’s and Don’ts
✅ Do
- Use short-lived feature branches
- Use clear, structured branch names
- Use Conventional Commits
- Sync with
mainfrequently - Use squash merges for clean history
❌ Don't
- Work on
mainfor real changes - Keep branches alive for weeks
- Combine unrelated changes in one PR
- Ignore merge conflicts until the end
- Skip code reviews (even solo)
TL;DR Workflow
Commit with convention
Follow this workflow and your repositories will stay clean, predictable, and conflict-light.