DEV Community

📚 Git & GitHub Series
➡️ You're reading Part 4
⬅️ Part 3: Creating Commits & Exploring the .git Folder
Understanding Branching with an Analogy
Think of a branch in Git as a railway track.
Each commit is like a rail car placed on that track, and the branch name (e.g., main
) is the track's label.
Now let’s imagine two developers, Developer A and Developer B, working on their respective features.
Why Not Work on the Same Branch?
If both developers work directly on the same branch (main
), over time the commit history gets polluted.
Now imagine if we need to revert Developer A’s changes, doing so would also affect Developer B’s work.
This is why we avoid working directly on
main
and instead create branches.
How Branching Helps
At the beginning, the HEAD (which points to the latest commit) is on the last commit of the main
branch.
- Developer A needs to work on a new feature.
- They create a new branch from
main
using:
git checkout -b feat/a
- Developer A commits code into
feat/a
, creating 3 commits.
Meanwhile, other contributors may add commits to the main
branch, moving its HEAD forward.
When Developer A completes their work:
- The
feat/a
branch is merged back intomain
. - The merge can happen in one of two ways:
- As individual commits
- As a single commit using squash:
git merge --squash feat/a
Real-World Git Rules (In Companies)
Different organizations follow different Git workflows, but a common approach includes:
- The
main
branch is treated as the Single Source of Truth. - Developers never push directly to
main
. - Instead, they follow a similar process to this:
- Create a feature branch (e.g.,
feat/login
). - Push it to the remote repository.
- Open a Pull Request (PR) to merge into
main
. - The PR is reviewed, discussed, and approved.
- After approval, it gets merged into
main
.
This keeps the
main
branch clean, stable, and production-ready.
Branch Naming Conventions in Companies
To maintain clarity and consistency across teams, branches are often named following specific patterns:
git branch "feat/whatsapp-integration" #New feature
git branch "bug/login-not-working" #Fixing a bug
git branch "wip/wontBeFinishedSoon" #Work in progress
git branch "junk/experimenting" #Temporary or experimental work
đź’ˇ Best Practices for Branch Naming:
- Always use lowercase letters and hyphens
-
to separate words. - Start the branch name with a category prefix (
feat/
,bug/
,wip/
,chore/
,junk/
). - Keep branch names short but descriptive.
- Avoid using spaces or special characters other than
-
and/
.
A consistent naming convention makes it easier to automate workflows, review pull requests, and manage releases.
Let's Perform Branching & Merging in Git
Follow along with this hands-on example to understand branching, committing, and merging.
Step 1: Check Which Branch You’re On
To see your current branch:
git branch
You’ll likely see main
(or master
).
If you’re not on main, switch to it:
git checkout main
Step 2: Create a New File and Commit
Create a file named feat-a.html
and add some text inside the <body>
.
Then stage and commit the file:
git add feat-a.html
git commit -m "Working on feat/a"
Step 3: Create a Branch from main
and Switch to It
Let’s say you want to start working on Feature B:
git checkout -b feat/b
This:
- Creates a new branch
feat/b
- Checks out into it (i.e., switches to it)
- Sets
HEAD
at the last commit frommain
Step 4: Make Changes and Commit in the New Branch
Create a file called feat-b.html
, add some content in it, and make two commits:
git add feat-b.html
git commit -m "Added feature b file"
Make another small change, then:
git commit -am "Updated feature b file"
Step 5: View the Commit History
You can view commit history in two ways:
git log
Or a simplified version:
git log --oneline
Step 6: Merge feat/b
into main
Now that your work is done in feat/b
, let’s merge it back to main
:
git checkout main
git merge feat/b
Your changes from feat/b
are now part of the main
branch.
Step 7: Create a New Branch and Switch in One Command
This is a shortcut to create and move into a branch:
git checkout -b feat/c
Make some changes in feat/c
, then:
git add feat-c.html
git commit -m "Added feature c"
Then merge into main
:
git checkout main
git merge feat/c
Step 8: View Your Updated Commit History
After the merges:
git log --oneline
You’ll see the new commits from feat/b
and feat/c
as part of the main branch history.
Delete Merged Branches (Recommended)
To keep your branch list clean, delete branches that have already been merged:
git branch -d feat/b
git branch -d feat/c
This won’t delete any history, your changes are already part of the main
branch.
What Is a Squash Merge?
Squashing is a hybrid merging approach where multiple commits are combined into a single commit at the time of merging a branch.
When you merge a feature branch into main
using squash, Git adds all changes but keeps the main
branch history clean.
Benefits of Squash Merging:
-
Clean history – Only one commit added to
main
- Removes noise – No clutter from WIP commits or small fixes
Disadvantages of Squash Merging:
- History is lost – You lose visibility into the original commit timeline
- Harder to debug – Can be challenging if something goes wrong and you need fine-grained history
Try It Yourself: Squash Example
- Create a new branch:
git checkout -b feat/d
- Create a file feat-d.html, and make 4 commits with different content.
- View the commit log:
git log --oneline
You’ll see 4 separate commits in feat/d
.
Now Squash the Branch into Main
Switch to the main
branch:
git checkout main
Perform a squash merge:
git merge --squash feat/d
Git will stage all changes from feat/d
. Now create a single squashed commit:
git commit -m "Squashed: Feature D implementation"
Check the updated commit log:
git log --oneline
You’ll see just one new commit on main
.
The 4 commits from feat/d
are not shown separately.
Visual Breakdown
Let's break down how a branch is created and how merging works with and without squash.
Creating the Branch
Regular Merge
Squash Merge
Real-World Scenario: GitHub Flow with Squash
Let’s say your branch is 3 commits ahead of main
.
1. Create a Feature Branch
git checkout -b feat/z
2. Make 3 Commits and Push
git push --set-upstream origin feat/z
Once pushed, GitHub will show:
"3 commits ahead of main"
3. Open a Pull Request
Suppose your organization has locked the main
branch — you can't push directly.
So, you'll create a Pull Request by clicking "Compare & pull request" on GitHub.
4. Choose Squash & Merge
To merge cleanly into main
, select "Squash and Merge".
This will:
- Combine all 3 commits into one
- Add a clean commit message to
main
- Automatically link the PR (e.g.
#3
) - Leave the feature branch (
feat/z
) visible until deleted
This keeps the
main
timeline clean while retaining traceability via the PR number.
5. Pull the Latest Changes to Your Local main
After merging the PR, update your local repo:
git checkout main
git pull origin main
By following this squash-based GitHub flow, your history stays clean, yet your collaboration remains fully traceable.
Git Rebase
Rebase is powerful, clean, and dangerous if misused.
It rewrites commit history by placing your branch commits on top of another branch (usually main
).
When to Rebase?
- You're working on a feature branch
-
main
has moved ahead - You want your branch to reflect the latest changes before merging
Common Mistake
If you’re on feat/b
, avoid this:
git merge main # This works but pollutes the history
Or:
git merge --squash main # Uncommon usage, may not behave as expected
Correct Way: Rebase
git checkout feat/b
git rebase main
This replays your commits on top of the latest from main
, keeping your history linear and clean.
Best Practice for Merging Into Main
To keep the main
branch clean and organized:
git checkout main
git merge --squash feat/b
This brings in all the changes from your feature branch as one commit and avoids clutter in the commit log.
Wrapping Up
In this article, you learned:
- Why branching is essential for clean, collaborative development
- How to create, switch, and merge branches safely
- The difference between regular merges and squash merges
- How teams manage contributions using Pull Requests
- The role of squash merges — both in GitHub and locally
- How
git rebase
can help you keep a linear commit history - Real-world branch naming conventions used in professional workflows
By applying these concepts, you’ll keep your repository organized, your main branch production-ready, and your team collaboration smooth.
📚 More from the Series
- Part 1: Why Git & GitHub Matter
- Part 2: Setting Up Git and GitHub
- Part 3: Creating Commits & Exploring the .git Folder
- âś… Part 4: You're here!
- Part 5: Working with Pull Requests & Conflict Resolution
Enjoyed this post?
Found this helpful? Drop a comment, share it with your team, or follow along for the next deep dive.
For further actions, you may consider blocking this person and/or reporting abuse
Top comments (0)