Feature Branch Workflow
Learn the feature branch workflow in Git: create a branch, make changes, merge with pull requests, and keep your main branch stable.
Focus: feature branch workflow
Have you ever pushed code directly to main only to have a teammate’s review turn into a frantic scramble of reverts and hotfixes? Or found yourself staring at a tangled history of merge commits, unsure which change broke the build? That chaos is the exact pain the feature branch workflow eliminates. By isolating every new idea, bug fix, or experiment in its own branch, you and your team converge on a shared main that stays clean, deployable, and reviewable at all times. In this lesson, you’ll master the workflow that powers thousands of open-source projects and modern DevOps teams — and you’ll be ready to tackle collaboration without fear.
The problem this lesson solves
When every developer commits directly to main, you inherit a world of trouble:
- Conflicting changes appear constantly, because everyone is editing the same lines in the same files simultaneously.
- Broken builds become routine — one bad commit can take down the entire codebase for the whole team.
- Code review becomes an afterthought, or impossible, because there’s no clean way to see what a single change actually touches.
- Deployments turn into gambles, as you never know which commit is safe to ship.
In short, a single shared branch is a recipe for friction. The feature branch workflow solves this by giving every piece of work its own isolated space — a branch — where you can experiment, commit freely, and only merge back once the work is solid and reviewed.
Core concept / mental model
Think of your repository as a communal kitchen. The main branch is the clean, ready-to-serve countertop. Each feature branch is a private cutting board. You take your ingredients (your code changes), chop and taste on your own board, and only when the dish is perfect do you place it on the countertop for everyone to enjoy.
- A feature branch is a lightweight, movable pointer to a specific commit. It’s cheap to create, cheap to delete, and fully isolated from other branches.
- The workflow is built on a few repeating steps: create a branch, commit your changes, push the branch, open a pull request, review and discuss, and finally merge or close the branch.
- The golden rule:
mainshould always be deployable. New work lives in branches and only entersmainthrough a controlled, reviewed merge.
A branch is simply a named label that moves forward as you commit. The moment you git checkout -b feature/login, you’re standing on a new branch that shares the current commit — but from then on, your new commits belong only to that branch. main stays frozen, untouched, until you deliberately merge.
How it works step by step
Here’s the sequence you’ll follow on every feature, whether you’re working solo or in a team:
- Start from an up-to-date
main— pull the latest changes so your branch is based on the current state of the project. - Create a new branch — give it a descriptive, short name like
feature/user-loginorfix/typo-in-readme. You’re not committing tomainyet. - Make your changes and commit them on the feature branch. Commit early, commit often — each commit is a checkpoint you can return to.
- Push the branch to the remote (
origin) so others can see it — and so it’s backed up. - Open a pull request (PR) on your hosting platform (GitHub, GitLab, Bitbucket). This is the conversation point: reviewers comment, ask for changes, and approve.
- Address review feedback with additional commits pushed to the same branch. The PR updates automatically.
- Merge the branch into
mainonce approved — and after merging, delete the feature branch (locally and remotely) to keep the repository tidy.
The key insight is that nothing touches main until the very end. Every intermediate step is reversible and non-disruptive.
Hands-on walkthrough
Let’s put the workflow into practice. We’ll simulate adding a login feature to a small project. You’ll need a Git repository — create one locally or clone an existing one.
Step 1: Start clean
# Navigate to your project
cd my-project
# Ensure you're on main and have the latest changes
git checkout main
git pull origin main
Step 2: Create your feature branch
# Create and switch to a new branch
git checkout -b feature/user-login
Now make your changes. For demonstration, let’s add a simple file:
echo 'Login coming soon' > login.txt
git status
Expected output (simplified):
On branch feature/user-login
Untracked files:
(use "git add <file>" to commit)
login.txt
Step 3: Commit your work
git add login.txt
git commit -m "Add login placeholder"
Step 4: Push and open a pull request
git push origin feature/user-login
In real life, you’d now visit your hosting platform and click “New pull request.” For this exercise, just note the URL with your remote. Once you merge (or on GitHub, after approval), you can close the branch.
Step 5: Merge and clean up
On the hosting platform, merge the PR. Then back in your terminal:
# Switch back to main and pull the merged changes
git checkout main
git pull origin main
# Delete the local and remote feature branch (already merged)
git branch -d feature/user-login
git push origin --delete feature/user-login
Your main is now updated, and your repository is clean — no leftover branches cluttering the branch list.
Compare options / when to choose what
There are several branching workflows. Here’s a quick comparison to help you decide when the feature branch workflow is right (and when it isn’t):
| Workflow | Best for | Drawbacks | When to choose it |
|---|---|---|---|
| Feature branch workflow | Small teams, continuous delivery, keeping main stable |
Requires discipline to merge frequently; isolated branches can cause merge conflicts if they live too long | Most teams — it’s the default recommended approach for modern software development |
| GitFlow | Large projects with scheduled releases | Complex — many branch types (develop, release/*, hotfix/*) |
When you need strict release management |
| Trunk-based development | Very fast CI/CD, microservices | Requires excellent automated testing; all changes go to main directly or via short-lived branches |
Teams with strong CI and small, frequent changes |
| Forking workflow | Open-source projects with many external contributors | Each contributor forks the repository; integration is manual | When you can’t grant write access to everyone |
The feature branch workflow strikes the sweet spot for most teams: it’s simple enough to adopt in an afternoon and powerful enough to keep main production-ready. If your team ships releases on a schedule, you might evolve toward GitFlow. If you’re building a small service with automated tests, trunk-based might be simpler — but the skills you learn here (branching, reviewing, merging) transfer to any model.
Troubleshooting & edge cases
“My branch is behind main and I get merge conflicts”
This happens when other features merged before yours. The fix is to rebase your branch onto the latest main:
git fetch origin
git rebase origin/main
Resolve any conflicts by editing the files, then git add and git rebase --continue. After that, force-push your branch (since the history changed):
git push --force-with-lease origin feature/user-login
Pro tip: Always use
--force-with-lease, never plain--force. It refuses to overwrite remote changes you haven’t seen, preventing you from clobbering a teammate’s work.
“I merged a branch too early — how do I undo?”
The merge commit is just a commit. Use git revert to create a new commit that undoes the merge:
git revert -m 1 <merge-commit-hash>
This is safe on shared branches because it doesn’t rewrite history.
“I pushed sensitive data on my feature branch”
If the secret is already on a remote, you must rotate the key immediately. Even if you delete the branch, the data may be cached. The safest path is to rotate the secret and then clean history with tools like git filter-repo — but always assume the worst.
“I forgot to create a branch and committed directly to main”
No panic. You can move those commits to a new branch:
# Create a new branch from your current main (which has the commits)
git branch feature/emergency-fix
# Reset main back to the previous commit
git reset --hard HEAD~1 # adjust the number
# Now switch to your new branch
git checkout feature/emergency-fix
This rewrites history, so only do it if you haven’t pushed main yet (or if you’re the only one who has it).
What you learned & what's next
You now understand the feature branch workflow end to end: you saw the pain of sharing one branch, the mental model of isolated cutting boards, the exact series of commands to create, push, and merge a feature branch, and how to troubleshoot common hiccups like merge conflicts and accidental commits. All of this directly supports the lesson’s learning objectives: you can explain the core idea (isolation for parallel work) and you’ve completed a hands-on exercise that mimics a real team setting.
You’re no longer a bystander — you’re a collaborator. Next in the Git Tutorial, you’ll learn to handle merge conflicts — the moment when two branches touch the same lines. You’ll turn those scary “CONFLICT” messages into a systematic, calm resolution. The skills you’ve built here (clean branches, disciplined commits, focused reviews) are exactly what make conflict resolution possible without tears.
Practice recap
Create a new branch named practice/feature-branch in any repository, add a file with a comment describing a feature you plan to build, commit and push it, then open a pull request against main. As a next step, try rebasing your branch onto origin/main after making a dummy commit, and resolve any conflict it creates.
Common mistakes
- Forgetting to pull the latest
mainbefore creating your branch — your branch starts outdated and accumulates conflicts. - Merging feature branches directly into
mainwithout a pull request or review, skipping the whole safety net. - Deleting the feature branch locally but never removing it remotely, leaving stale branches piling up.
- Using
--forceinstead of--force-with-leasewhen rebasing — this can silently overwrite a teammate’s pushed commits.
Variations
- Open-source projects often use the forking workflow — each contributor forks the repo, adds their own remote, and pulls from the upstream instead of having direct write access.
- Teams with frequent releases sometimes layer GitFlow on top of feature branches, adding
develop,release/, andhotfix/branches to handle staging and maintenance. - For very fast-moving projects, trunk-based development keeps branches short-lived (less than a few hours) and relies on feature toggles to hide incomplete work.
Real-world use cases
- Adding a new login page to an e-commerce site — you branch off
main, implement, open a PR, get peer review, and merge only when the feature is polished. - Fixing a production bug in a microservices repo — you create a hotfix branch, patch it, and merge to
main(and the release branch) after CI passes. - Experimenting with a new refactor to the database schema — you develop on a branch, test thoroughly, and decide to merge or discard without ever affecting
main.
Key takeaways
- The feature branch workflow isolates work so
mainstays stable and deployable at all times. - Always start from an up-to-date
main, create a descriptive branch name, and commit early. - Open a pull request for every feature — it’s the gate for review, discussion, and automated checks.
- Merge only after review and approval, then delete the branch locally and remotely to keep your repo clean.
- Rebase your branch onto the latest
mainto avoid merge conflicts, and use--force-with-leasewhen pushing rewritten history. - If you accidentally commit to
main, you can move those commits to a new branch — but only if you haven’t pushed them.
Keep learning
Related tutorials, quizzes, and articles for this topic.
Discussion
Questions, corrections, and tips help everyone reading this page.
0 comments
Add a comment
No comments yet — start the thread.