Ad – 728×90
🔀 Workflows

Feature Branch Workflow – The Standard Team Git Workflow

The Feature Branch Workflow (also called GitHub Flow) is the most widely adopted team Git workflow in 2026. The core idea is simple: main is always deployable, and all work — features, bug fixes, documentation — happens in dedicated branches merged via pull requests. If you're working on a team or contributing to open source, this is the workflow you need to master.

⏱️ 15 min read 🎯 Intermediate 📅 Updated 2026

What Is the Feature Branch Workflow?

The workflow has three non-negotiable rules:

  1. main is always deployable — every commit on main could theoretically be deployed to production right now
  2. No direct commits to main — all changes go through a branch and a pull request
  3. PRs require code review and CI checks before merging

Everything else — how you name branches, how many reviewers a PR needs, squash vs merge commits — is team convention built on top of these three rules.

Core Rules Explained

ℹ️
Why "main is always deployable" matters

When main is always deployable, you can respond to a production outage at any time. You don't need to find a "safe" point in history to roll back to — main IS the safe point. This discipline also catches integration problems early: when your feature branch is merged, any breakage is immediately visible and attributed to that specific merge.

Step-by-Step Workflow

Bash
# Step 1: Start from the latest main
git switch main
git pull origin main

# Step 2: Create a descriptive feature branch
git switch -c feature/user-profile-page

# Step 3: Work on the feature — commit early and often
git add src/pages/UserProfile.js
git commit -m "feat(profile): add user profile page skeleton"

git add src/pages/UserProfile.js src/api/users.js
git commit -m "feat(profile): connect profile page to users API"

git add src/pages/UserProfile.css
git commit -m "style(profile): add responsive layout for profile page"

# Step 4: Keep your branch up to date with main to avoid big conflicts
git fetch origin
git rebase origin/main  # or: git merge origin/main

# Step 5: Push your branch to the remote
git push -u origin feature/user-profile-page
# -u sets the upstream — future pushes only need: git push

# Step 6: Open a Pull Request on GitHub/GitLab
# - Write a clear PR title and description
# - Link to the related issue (#42)
# - Request reviewers
# CI/CD automatically runs tests on your branch

# Step 7: Address review comments
git add src/pages/UserProfile.js
git commit -m "fix(profile): address code review feedback"
git push

# Step 8: After PR is approved and CI passes — merge!
# (Done via GitHub/GitLab UI — squash merge or regular merge)

# Step 9: Clean up — delete the feature branch
git switch main
git pull origin main
git branch -d feature/user-profile-page
Ad – 336×280

Branch Naming Conventions

Consistent branch naming helps the whole team understand what's being worked on at a glance:

PrefixUsed forExample
feature/New featuresfeature/user-authentication
bugfix/Bug fixes in developmentbugfix/login-null-pointer
hotfix/Urgent production fixeshotfix/payment-crash-v2.1
chore/Maintenance, config, toolingchore/upgrade-dependencies
docs/Documentation only changesdocs/update-api-readme
refactor/Code refactoringrefactor/extract-auth-service
💡
Include the issue number in your branch name

Many teams include the issue/ticket number: feature/GH-42-user-profile or bugfix/JIRA-1234-fix-payment. This creates an instant link between the branch and the requirements/bug report, and GitHub automatically links commits to issues when the branch name contains the issue number.

The Pull Request Process

A good pull request makes the reviewer's job easy:

  • Title: short, imperative mood — "Add user profile page" (not "Added" or "Adding")
  • Description: what changed, why, how to test it, screenshots for UI changes
  • Link to issue: "Closes #42" in the description auto-closes the issue on merge
  • Small scope: a PR should do one thing — a 500-line PR is hard to review; ten 50-line PRs are much better
  • CI/CD must pass: never merge a red PR

Trunk-Based Development — The Even Simpler Version

Trunk-based development is a variation where feature branches are extremely short-lived (less than a day) or developers commit directly to main using feature flags to hide incomplete features from users:

JavaScript
// Feature flag pattern — incomplete feature is in main but hidden
if (featureFlags.isEnabled('new-dashboard')) {
  return <NewDashboard />;
}
return <OldDashboard />;

Workflow Comparison

AspectGit FlowFeature Branch (GitHub Flow)Trunk-Based
Permanent branchesmain + developmain onlymain only
Branch lifespanDays to weeksHours to daysHours or none
Release cadenceVersioned releasesContinuousContinuous (multiple/day)
ComplexityHighMediumLow
Best forVersioned softwareMost web teamsElite DevOps teams

📋 Summary

  • The three non-negotiable rules: main is always deployable, no direct commits to main, PRs require review + CI.
  • Workflow: pull main → create branch → work → push → open PR → review → merge → delete branch.
  • Use git push -u origin branch-name on first push to set upstream tracking.
  • Branch naming: use prefixes like feature/, bugfix/, hotfix/, chore/, docs/.
  • Good PRs: clear title, description, linked issue, small scope, passing CI.
  • Trunk-based development: same idea but with very short-lived branches + feature flags.
  • Feature Branch Workflow is the right default for most teams in 2026.

FAQ

Should I squash, merge, or rebase when merging a PR? +

Squash merge: all commits on the feature branch are squashed into one clean commit on main. Best for keeping main history linear and readable — especially when individual commits on the branch are messy WIP commits. Merge commit: preserves the full branch history with a merge commit. Useful when commits are well-crafted and you want to keep the context. Rebase: replays branch commits on top of main with no merge commit — cleanest history but rewrites commit hashes. Most teams default to squash merge for PRs, using the PR title as the commit message.

How do I keep my feature branch up to date with main? +

Two options: merge (git merge origin/main) — adds a merge commit to your branch preserving its history; or rebase (git rebase origin/main) — replays your commits on top of the latest main, resulting in a linear history. Rebase is generally preferred for feature branches to keep history clean, but it rewrites commit hashes which requires a force-push if you've already pushed the branch. For solo branches (only you), rebasing is usually the better choice.

What if my feature takes 2 weeks and main has moved a lot? +

Long-lived branches are a sign that the feature is too large. Consider breaking it into smaller pieces (each merged via a separate PR). If the feature must be long-lived, rebase onto main frequently (daily) to catch conflicts early while they're still small. Some teams use feature flags to merge incomplete features: the code is in main but hidden behind a flag, and the flag is enabled when the feature is done.

What is "draft pull request" and when should I use it? +

A draft PR on GitHub signals "I'm still working on this, not ready for review yet." It's useful for: getting early feedback on your approach, running CI on a work-in-progress, making your work visible to the team without triggering a review request. Convert the draft to a regular PR when it's ready for review by clicking "Ready for review". Draft PRs are a great habit — they increase team visibility and enable collaboration earlier in the development process.