DEV Community

Cover image for Git Branches: How Teams Build Features Without Breaking Each Other’s Code
swathi m
swathi m

Posted on

Git Branches: How Teams Build Features Without Breaking Each Other’s Code

Imagine your team is building an app for digital payments.
Thousand and thousands of users need it everyday. So your code main branch (it’s usually called master or main) must be always stable and free of bugs.

But developers are adding new feature constantly

  • One wants to add UPI QR payments,
  • One other person wants to improve the transaction history page,
  • Someone else is fixing a critical login bug.

If everybody edits the same branch (master) at the same time, it’s very likely that the app will break! This is why Git branches are so important.


So, What is a Branch?

A branch in Git is basically a parallel timeline of your project.

  • By default, you have one branch when you initialize a repo and it’s called master.
  • A branch is just a pointer to the latest commit.
  • You can create new branches to safely experiment or develop features without touching master.

Think of master as your production app (the one customers use), and new branches are playgrounds where developers try new features.


Creating a New Branch

Let’s say Ravi is assigned to build a “Rewards Points” feature.

Instead of coding directly on master, Ravi creates a new branch:

git checkout -b feature/rewards
Enter fullscreen mode Exit fullscreen mode

you’re telling Git to do two things in one command:

Create a new branch

  • The -b option means create a new branch.
  • Here, the new branch is named feature/rewards.
  • Branch names are often written like this (feature/..., bugfix/..., hotfix/...) to organize work.

Switch to that new branch

  • After creating the branch, Git immediately “checks it out,” meaning your working directory now points to that branch.
  • Any new commits you make will go into this branch, not the previous one (usually main or develop).

It is like

  • You’re on main right now.
  • You run git checkout -b feature/rewards.
  • Git makes a new branch feature/rewards starting from the current commit of main.
  • Git switches you into it.

Now you can work on the “rewards” feature separately, without affecting main.


Viewing Branches

To see all branches:

git branch
Enter fullscreen mode Exit fullscreen mode

Example output:

* feature/rewards
  master
Enter fullscreen mode Exit fullscreen mode

The * means Ravi is currently on the feature/rewards branch.


Commits in Branches

Ravi adds code for the rewards system and commits it:

git add rewards.js
git commit -m "Add rewards points calculation"
Enter fullscreen mode Exit fullscreen mode

This commit is stored only in feature/rewards.
master doesn’t have it yet.

( That commit is saved in Git history, but only on the branch Ravi is currently on → which is feature/rewards.

  • The feature/rewards branch now points to a new commit.
  • The master branch still points to the old commit (the one before this) )

Now feature/rewards is ahead of master by 1 commit.

Visualize it

Before the commit:

(master) A
          \
(feature/rewards) A
Enter fullscreen mode Exit fullscreen mode

After Ravi’s commit:

(master) A
          \
(feature/rewards) A → B ("Add rewards points calculation")
Enter fullscreen mode Exit fullscreen mode

Here:
A = last commit both branches share (where feature/rewards was created).
B = Ravi’s new commit.

Why we say “ahead by 1 commit”?

  • feature/rewards has one extra commit (B) that master does not have.
  • So Git describes this as: feature/rewards is 1 commit ahead of master.

This is why if you switch back to master, you won’t see rewards.js yet — because master doesn’t have commit B.


Another Developer’s Branch

Meanwhile, Neha finds a bug in the login page.
She creates her own branch:

git checkout -b bugfix/login-redirect
Enter fullscreen mode Exit fullscreen mode

She fixes the bug and commits.
Now:
• Ravi’s branch has the rewards feature.
• Neha’s branch has the bugfix.
• master has neither.

Both developers are working safely in isolation.


Understanding HEAD

In Git, HEAD is a pointer to where you currently are ( it tells Git where you “are” right now )

  • If Ravi is on feature/rewards, HEAD points to the latest commit in that branch.
  • If he switches to master, HEAD moves to the latest commit in master.

This is how Git knows “which timeline” you’re on.

So, usually, HEAD points to a branch, and that branch points to the latest commit. Switching branches just moves HEAD to another branch.


Merging Branches

Once Ravi finishes his rewards feature, it’s time to bring it back into master.

He switches to master:

git checkout master
Enter fullscreen mode Exit fullscreen mode

Now: HEAD → master → A. He’s standing on the master branch (the timeline without rewards yet).

And merges his branch:

git merge feature/rewards
Enter fullscreen mode Exit fullscreen mode

This tells Git:
“Take all the work from feature/rewards and combine it into master.”

  • Git looks at the common ancestor of both branches (commit A).
  • It compares changes between A → B (in feature/rewards) and A → A (in master).
  • Since master has no new commits after A, Git can just fast-forward master to B.

Result:

(master) A → B
(feature/rewards) B
Enter fullscreen mode Exit fullscreen mode

Now both branches point to commit B.
Master has the rewards code!


Types of Merges

(a) Fast-forward merge

If no one else has committed to master since Ravi branched off, Git just “moves” the master pointer ahead.

Situation before merging:

  • master has commit A.
  • Ravi made a new commit B on feature/rewards.
(master) A
          \
(feature/rewards) B
Enter fullscreen mode Exit fullscreen mode

What happens when Ravi merges into master:

Since no new commits were added to master, Git doesn’t need to create a new “merge commit.”
It just moves the master pointer forward to where feature/rewards is.

(master) A → B
(feature/rewards) B
Enter fullscreen mode Exit fullscreen mode

master now contains Ravi’s commit. History looks like a straight line. Super clean.

(b) No-fast-forward merge

But suppose Neha already merged her login bugfix into master.
Now master has commits Ravi doesn’t.

  • master has commit A → C (Neha added a bugfix).
  • feature/rewards has commit A → B (Ravi added rewards).
(master) A → C
          \
(feature/rewards) B
Enter fullscreen mode Exit fullscreen mode

What happens when Ravi merges into master:

Git cannot just “move master forward” because master already went in a different direction (C).
So Git creates a merge commit (let’s call it M) that ties the two histories together.

          C
         / \
A ——       M   (master)
         \ /
          B
(feature/rewards)
Enter fullscreen mode Exit fullscreen mode

The merge commit M clearly shows the moment when feature/rewards was brought into master. If someone looks at git log, they can see which commits came from which branch. This keeps a record of teamwork.

This way, the log clearly shows:

  • When feature/rewards was merged.
  • Which commits came from it.

So,
Fast-forward merge = the pointer just moves forward (no extra commit, linear history).
No-fast-forward merge = Git creates a new commit that join two different histories (more explicit, useful for teamwork tracking).


In real time:

  • master (or main) → always stable, production-ready.
  • Developers create feature branches for new functionality.
  • Bugfix branches for urgent issues.
  • Release branches for preparing production releases.
  • Merges happen through Pull Requests (PRs) on platforms like GitHub or GitLab.

Many teams enforce no-fast-forward merges so that every merge leaves a clear trace in history.


Recap:
Branches = Safe playgrounds for features & fixes.
master/main = Production-ready code.
HEAD = Pointer to your current commit/branch.
Merge = Bring changes from a branch into another.
Fast-forward = Clean history.
No-fast-forward = Adds a merge commit (preferred in teams).

With branches, developers in Bengaluru, Pune, or San Francisco can all work on the same project at the same time without stepping on each other’s toes.
It’s like giving every developer their own workspace, while the master branch stays clean and safe for the users.

Top comments (0)