Skip to content

Branching strategy

Projects should follow a simple flow focused on keeping main stable and validating changes in dev first.

Branch naming

Use clear, consistent branch names that describe the work. The format is:

<type>/<short-description>

Types

  • feature/ – New functionality
  • fix/ – Bug fixes
  • docs/ – Documentation updates
  • refactor/ – Code restructuring without behavior changes
  • test/ – Test additions or improvements
  • chore/ – Maintenance, dependency updates

Examples

  • feature/user-authentication
  • fix/payment-timeout-issue
  • docs/api-endpoints
  • refactor/cache-logic
  • test/payment-flow-coverage
  • chore/upgrade-dependencies

Use lowercase, hyphens for spaces, and keep it concise but descriptive.

Workflow

1. Branch off dev

Create a feature or fix branch from dev. This ensures you start from the latest development code and isolate your changes. Use a descriptive branch name like feature/user-auth or fix/api-timeout.

git checkout dev
git pull
git checkout -b feature/your-feature-name

2. Make changes

Implement your feature or fix in small, focused commits. Each commit should represent a complete, working change. Keep commits atomic so they're easy to review and revert if needed.

3. Open a PR to dev

Push your branch and submit a pull request to dev. This triggers code review and CI checks. Include a clear description of what changed and why.

git push -u origin feature/your-feature-name

4. Merge using squash

Once approved, use squash merge to condense all your commits into a single commit on dev. This keeps the development branch clean and linear, making it easier to track features and releases.

5. Test on dev

Let your changes live in dev for a testing period. This allows QA and other team members to validate the feature in a shared environment before it reaches production.

6. Promote to main

When ready, open a PR from dev to main. This is your release promotion. Use a clear description mentioning what features/fixes are included.

7. Merge with a merge commit

Use a merge commit (not squash) to preserve the full history from dev. This creates a meaningful release record in main and makes it easy to track what was released and when.

Quick commands

# Ensure dev is up to date
git checkout dev
git pull

# Create a feature branch from dev
git checkout -b feature/short-topic

# Push and open a PR to dev
git push -u origin feature/short-topic

FAQ

Why branch off dev instead of main?

Branching from dev ensures you're working with the latest development changes and allows for proper testing before reaching production.

Why use squash merges into dev?

Squash merges keep the dev branch history clean and focused on features rather than individual commits, making it easier to manage.

Why use merge commits into main?

Merge commits preserve the full context of changes promoted to production, providing a clear record of what was released.

What if I need to hotfix something in production?

Create a hotfix/ branch from main, apply the fix, and open a PR back to both main and dev to ensure the fix is included in future releases.

git checkout main
git pull
git checkout -b hotfix/urgent-fix

Apply your fix, then:

git push -u origin hotfix/urgent-fix

Open PRs to both main and dev.

Can I work on multiple features within the same branch?

No, keep branches focused on a single feature or fix to simplify reviews and merges.

Is there any exception to this strategy?

Yes, in rare cases where multiple features are tightly coupled and must be developed together, you might use a single branch. However, this should be avoided if possible to maintain clarity and ease of review.