On this page

Branching Workflows

A branch is cheap in Git, but how a team uses branches decides whether work flows smoothly or ends up in merge-conflict pain. This page covers three things: how to use a feature branch, which team strategy to pick, and how to name branches so everyone can read them.

Feature branches

Feature branches and short-lived branches.

A feature branch is a branch you create for one piece of work: a new feature, a bug fix, or a small cleanup. You do the work there, and merge it back into the main branch when it is done.

1main: A --- B ----------------------- E (merge)
2 \ /
3feature/login-page: C --- D --------------

Why Use a Feature Branch?

  • main stays stable. Half-finished code never lands on the shared branch.
  • You work in isolation. Your experiments do not break anyone else.
  • Review happens before merging. A pull request lets teammates read the change and run tests first.
  • It is easy to throw away. If the idea fails, delete the branch. Nothing else is affected.

Because a branch is only a pointer to a commit, creating one is instant and free.

The Everyday Workflow

git switch main
git pull # start from the latest main
git switch -c feature/login-page # create the branch and move to it
# ...edit files...
git add .
git commit -m "Add login form"
git push -u origin feature/login-page # share the branch, then open a pull request
# After the pull request is merged:
git switch main
git pull
git branch -d feature/login-page # delete the local branch
git push origin --delete feature/login-page # delete the remote branch (GitHub can do this for you)

Why Short-Lived Matters

A feature branch should live a short time: usually hours to a couple of days, not weeks.

The reason is drift. While your branch sits there, everyone else keeps committing to main. The longer you wait, the further apart the two sides get.

1Long-lived branch (3 weeks):
2
3main: A --- B --- C --- D --- E --- F --- G --- H (8 new commits from others)
4 \
5feature: X --- Y --- Z --- ...
6 Merge day: many conflicts, a huge review, high risk.
7
8Short-lived branch (1 day):
9
10main: A --- B
11 \
12feature: X
13 Merge day: tiny change, few conflicts, easy review.
Long-lived branchShort-lived branch
Many merge conflictsFew or no conflicts
Huge pull request, hard to reviewSmall pull request, fast to review
Bugs appear late, at merge timeBugs appear early
Others cannot see or build on your workWork is shared quickly

How to keep branches short:

  • Break big tasks into small pieces. Merge each piece on its own.
  • One branch, one purpose. Do not mix a bug fix with a refactor.
  • Merge often. Aim for pull requests that can be reviewed in minutes.
  • Hide unfinished work behind a feature flag, so you can merge it without users seeing it.

Keeping Your Branch Up to Date

If main moved while you worked, bring those changes into your branch before you merge. Do this often, so each update is small.

git fetch origin
git rebase origin/main # replay my commits on top of the latest main (straight history)
# or
git merge origin/main # add a merge commit (keeps history as it happened)
# After a rebase, the branch history changed, so push safely:
git push --force-with-lease

Rule: Only rebase a branch that you alone use. Never rebase a branch that others have pulled.

How the Branch Gets Merged

Most platforms give three options for finishing a pull request.

OptionWhat happensResult on main
Merge commitKeeps all branch commits and adds one merge commitFull history, with branch shape
Squash and mergeCombines all branch commits into one commitClean history, one commit per feature
Rebase and mergeReplays each branch commit on top of mainStraight line, no merge commit

For short-lived branches, squash and merge is a popular choice. Your messy "wip" and "fix typo" commits become one clear commit.

Feature Flags: Merge Early, Release Later

Sometimes a feature takes longer than a few days. Instead of keeping a long branch, merge small pieces early and hide the unfinished feature behind a flag that is turned off.

public Receipt checkout(Cart cart) {
if (featureFlags.isEnabled("new-checkout")) {
return newCheckout(cart); // unfinished code, off for real users
}
return oldCheckout(cart); // current behavior
}

The code is merged and deployed, but nobody sees it until the flag is switched on. This keeps branches short and keeps main safe.

Team strategies

GitHub Flow, trunk-based development, and Git Flow. Know when each fits. Trunk-based development is commonly chosen by teams that practice CI/CD (continuous integration and continuous delivery).

A branching strategy is a set of team rules: which branches exist, where work starts, and how it reaches production. The three common ones differ mainly in how many long-lived branches they use and how often they release.

GitHub Flow

The simplest strategy. There is one long-lived branch: main. It is always ready to deploy.

1main: A ---------------------- D (merge, then deploy)
2 \ /
3feature/login: B --- C -------------
4 |
5 Pull request: review + automated tests

The steps:

  1. Branch from main with a clear name.
  2. Commit your work and push the branch.
  3. Open a pull request. Teammates review it and the tests run.
  4. Merge into main once it is approved and the tests pass.
  5. Deploy from main, then delete the branch.

Rules:

  • Anything on main is deployable.
  • Never commit directly to main. Use pull requests.
  • Merge often and keep branches small.

Fits: web apps and services that deploy often, and small to medium teams.

Trunk-Based Development

Everyone works on one shared branch, called the trunk (usually main). Work is merged very often, at least once a day per developer.

1main: o---o---o---o---o---o---o---o---o (small commits, every day)
2 \ / \ / \ /
3 o o o (short branches: under 1 or 2 days)

Developers either commit straight to the trunk (small, trusted teams) or use very short-lived branches that merge within a day or two.

What makes it work:

  • Small changes. Big work is split into tiny steps.
  • Feature flags. Unfinished features are merged but switched off.
  • Strong automated tests. Every merge runs a CI pipeline, so a broken trunk is noticed and fixed within minutes.
  • Fast reviews. Small pull requests are reviewed quickly, or code is written in pairs.

Releasing: you release from the trunk, often straight through CI/CD. Some teams cut a short release branch or a tag at release time for stability.

Why teams like it: work is integrated constantly, so there are no giant merges. Releases are small and frequent, which makes bugs easier to find.

Fits: teams with good tests and CI/CD that deploy many times a week or day.

How is it different from GitHub Flow? They are close. If you use GitHub Flow with branches that live only a day or two and merge many times a day, you are basically doing trunk-based development. The difference is the emphasis: trunk-based insists on very short branches and feature flags.

Git Flow

A strategy built for planned, versioned releases. It uses two long-lived branches and three kinds of short-lived branches.

BranchCreated fromMerged intoHow long it lives
main--Forever. Holds released code, tagged with versions
developmain-Forever. The next release being built
feature/*developdevelopDays to weeks
release/*developmain and developUntil the release ships
hotfix/*mainmain and developHours to days

The flow:

  1. Developers build features on feature/* branches and merge them into develop.
  2. When enough is ready, create release/1.4.0 from develop. Only bug fixes are allowed there.
  3. When the release is ready, merge it into main, tag it (v1.4.0), and merge it back into develop.
  4. A bug found in production? Create hotfix/1.4.1 from main, fix it, then merge it into both main and develop.
# Start a release
git switch develop
git switch -c release/1.4.0
# ...only bug fixes and version bumps here...
# Ship it
git switch main
git merge --no-ff release/1.4.0
git tag v1.4.0
# Bring the fixes back into develop
git switch develop
git merge --no-ff release/1.4.0
git branch -d release/1.4.0

Fits: software with versions and scheduled releases, such as mobile apps, desktop software, and libraries, and products that must support several versions at once.

Drawbacks:

  • It is complex, with many branches to track.
  • develop and feature/* branches can live for a long time, which leads to big merges.
  • It is slow for continuous delivery, where you want to release many times a day.

Comparison

GitHub FlowTrunk-BasedGit Flow
Long-lived branchesmainmain (the trunk)main and develop
Branch lifetimeShort (days)Very short (hours to 1 or 2 days)Features can last weeks
Release styleDeploy from mainDeploy from trunk, oftenPlanned release branches
Feature flags needed?SometimesYes, usuallyRarely
Needs strong CI/tests?YesYes, essentialHelpful
ComplexityLowLowHigh
Best forWeb apps, small teamsTeams practicing CI/CDVersioned software

How to Choose

  • Do you release many times a week and have good tests? Choose trunk-based, or GitHub Flow with very short branches.
  • Do you want a simple setup for a web app with pull requests? Choose GitHub Flow.
  • Do you ship numbered versions on a schedule, or support old versions? Choose Git Flow.

Rule of thumb: use the simplest strategy that fits your release process. Do not add develop and release/* branches unless you really need them.

Naming conventions

Prefixes such as feature/, fix/, hotfix/, and release/.

A good branch name tells you what kind of work it is and what it is about, without opening it. A common format is:

1type/short-description
2type/ticket-id-short-description

Common Prefixes

PrefixUsed forExample
feature/A new featurefeature/login-page
fix/A bug fix (some teams use bugfix/)fix/null-pointer-in-cart
hotfix/An urgent fix for productionhotfix/payment-timeout
release/Preparing a release, often with a versionrelease/1.4.0
chore/Maintenance: dependencies, config, cleanupchore/update-dependencies
docs/Documentation onlydocs/api-guide
refactor/Code cleanup with no change in behaviorrefactor/split-order-service
test/Adding or fixing teststest/cart-edge-cases

The first four (feature/, fix/, hotfix/, release/) are the ones to know well. The others are optional extras that many teams add.

Naming Rules

  • Use lowercase letters.
  • Use hyphens (-) between words, not spaces or underscores.
  • Keep it short and clear: a few words that describe the work.
  • Add the ticket ID if you use a tracker, so the branch links to the task.
  • Do not use spaces or special characters like ~, ^, :, ?, *, or [.
  • Do not put your name or the date in the branch name. The commit already records them.

Good and bad examples:

BadGoodWhy
my-branchfeature/user-profileSays nothing about the work
Fix Login Bugfix/login-redirectSpaces and capital letters
feature/AddTheNewLoginPagefeature/login-pageToo long, mixed case
akash-workfeature/PROJ-142-search-filterNamed after a person, not the task
testtest/cart-edge-casesToo vague

With a Ticket ID

git switch -c feature/PROJ-142-search-filter
git switch -c fix/PROJ-188-cart-total-rounding
git switch -c hotfix/PROJ-201-payment-timeout
git switch -c release/1.4.0

Many trackers (like Jira) and platforms can link a branch to its ticket automatically when the ticket ID is in the name.

Slashes Make Folders (and One Trap)

The / in a name acts like a folder. Many Git tools use it to group branches together, so feature/* shows up as one group.

There is one trap: you cannot have both a branch named feature and a branch named feature/login. Git stores each branch as a file, and feature cannot be both a file and a folder.

Prefixes Match the Strategy

StrategyPrefixes you will mostly see
GitHub Flowfeature/, fix/, and the other type prefixes
Trunk-basedShort names with the same prefixes, merged within a day or two
Git Flowfeature/, release/, hotfix/, plus the develop branch

Enforce the Rule

A rule that nobody checks soon gets ignored. You can check names automatically, for example in a CI step, so a wrong name fails early.

BRANCH=$(git rev-parse --abbrev-ref HEAD)
PATTERN="^(feature|fix|hotfix|release|chore|docs|refactor|test)/[a-z0-9._-]+$"
if ! echo "$BRANCH" | grep -Eq "$PATTERN"; then
echo "Invalid branch name: $BRANCH"
echo "Use: type/short-description, for example feature/login-page"
exit 1
fi

Your Git host's branch protection rules can also protect main and release/* branches, so nobody pushes to them directly.

Summary

  • A feature branch holds one piece of work, so main stays stable.
  • Short-lived is better. Long branches drift away from main and cause big, risky merges. Keep branches to hours or a couple of days, and use feature flags to hide unfinished work.
  • GitHub Flow: one main branch, pull requests, deploy from main. Simple and a good default for web apps.
  • Trunk-based development: merge into the trunk at least daily, with feature flags and strong CI. Commonly chosen by CI/CD teams.
  • Git Flow: main and develop, plus feature/*, release/*, and hotfix/*. Best for versioned releases, but complex.
  • Name branches as type/short-description: feature/, fix/, hotfix/, release/. Use lowercase and hyphens, and add the ticket ID when you have one.

Interview Answer: Which Branching Strategy Would You Use?

I use feature branches: a small branch for one piece of work, merged through a pull request after review and automated tests. I keep branches short-lived, because the longer a branch lives, the more it drifts from main, and the bigger the merge conflicts and the review become.

For the team strategy, it depends on how we release. GitHub Flow is simple: one main branch that is always deployable, with work merged through pull requests. Trunk-based development goes further: everyone merges into the trunk at least daily, with feature flags to hide unfinished work and strong CI to keep the trunk healthy. It is a common choice for CI/CD teams. Git Flow uses main, develop, and release/* and hotfix/* branches, which fits versioned software with scheduled releases, but it is more complex and slower for continuous delivery.

For a web service that deploys often, I would choose trunk-based or GitHub Flow. For a mobile app with numbered releases, I would consider Git Flow.

I name branches as type/short-description, such as feature/login-page, fix/cart-total, hotfix/payment-timeout, and release/1.4.0, in lowercase with hyphens, and with the ticket ID when there is one.

Next TopicMerge vs Rebase