Git branches are one of the most powerful features that make Git the preferred version control system for development teams worldwide. This comprehensive guide will walk you through every aspect of Git branching and merging, from basic concepts to advanced workflows, with real examples and outputs.
π― What You'll Learn: In this hands-on tutorial, you'll discover:
- What Git branches are and why they're mandatory (not optional) in Git
- How to create, switch, and manage branches effectively
- Understanding branch isolation and independent development paths
- Various merging strategies: fast-forward vs. merge commits
- Handling divergent branches and collaborative workflows
- Best practices for team-based development with branches
π³ Understanding Git Branches: The Foundation
Git branches are not just a convenience featureβthey are mandatory and fundamental to how Git works. Every Git repository starts with at least one branch, and understanding branches is crucial for effective version control.
Prerequisites
Before we dive into branching, make sure you have:
- Git installed on your system
- Basic understanding of
git add
,git commit
, andgit status
- A Git repository to practice with
- Terminal or command prompt access
Why Branches Matter in Development Teams
In large development teams, branches serve several critical purposes:
- Parallel Development: Multiple developers work on different features simultaneously
- Code Isolation: Experimental features don't affect the main codebase
- Release Management: Separate stable releases from ongoing development
- Bug Fixes: Apply critical fixes without disrupting new feature development
- Code Reviews: Branches enable proper review processes before merging
π Examining Your Current Branch Status
Let's start by understanding the current state of our repository. Every Git command provides valuable information about your project's status.
Checking Repository Status
git status
Example Output:
On branch master
nothing to commit, working tree clean
What this tells us:
- We're currently on the
master
branch - There are no uncommitted changes
- The working directory matches the last commit
Viewing Files in Your Repository
ls -al
Example Output:
total 8
drwxr-xr-x. 3 centos9 centos9 53 Sep 24 13:22 .
drwxr-xr-x. 3 centos9 centos9 23 Sep 24 13:21 ..
-rw-r--r--. 1 centos9 centos9 23 Sep 24 13:21 first.txt
drwxr-xr-x. 8 centos9 centos9 166 Sep 24 13:22 .git
-rw-r--r--. 1 centos9 centos9 24 Sep 24 13:22 second.txt
Understanding the output:
first.txt
andsecond.txt
are our project files.git
directory contains all Git metadata and history- File permissions and timestamps show when files were created/modified
π Listing Available Branches
Basic Branch Listing
git branch
Example Output:
* master
What the asterisk (*) means:
- The asterisk indicates your current active branch
- You can only be on one branch at a time
- All commits you make will be added to this branch
Detailed Branch Information
git branch -v
Example Output:
* master 61460b3 added few files
Understanding the details:
master
: Branch name61460b3
: Abbreviated commit hash (first 7 characters)added few files
: The commit message of the latest commit- This shows both branches point to the same commit initially
π‘ Branch Names: Modern Git uses main
as the default branch name, but older repositories often use master
. Both function identicallyβit's just a naming convention.
π Creating Your First Branch
Creating a branch in Git creates a new line of development while keeping your main branch intact.
Creating a New Branch
git branch dev
What happens when you run this:
- Git creates a new branch named
dev
- The new branch starts from your current commit
- You remain on your current branch (master)
- No files are changed or moved
Verifying Branch Creation
git branch
Example Output:
dev
* master
Understanding the output:
- Both branches exist now
master
still has the asterisk (you're still on master)dev
is listed without an asterisk (exists but not active)
Detailed View of Both Branches
git branch -v
Example Output:
dev 61460b3 added few files
* master 61460b3 added few files
Key observation:
- Both branches point to the exact same commit (
61460b3
) - They have identical commit history at this point
- This is the starting point before branches diverge
π Switching Between Branches
Switching branches is one of the most common Git operations. It changes your working directory to match the target branch.
Switching to the Development Branch
git checkout dev
Example Output:
Switched to branch 'dev'
What happens during checkout:
- Your working directory updates to match the
dev
branch - Git updates the HEAD pointer to point to
dev
- Any new commits will now be added to the
dev
branch
Confirming the Branch Switch
git status
Example Output:
On branch dev
nothing to commit, working tree clean
Verifying Files Remain the Same
ls -ahl
Example Output:
total 8.0K
drwxr-xr-x. 3 centos9 centos9 53 Sep 24 13:22 .
drwxr-xr-x. 3 centos9 centos9 23 Sep 24 13:21 ..
-rw-r--r--. 1 centos9 centos9 23 Sep 24 13:21 first.txt
drwxr-xr-x. 8 centos9 centos9 166 Sep 24 13:25 .git
-rw-r--r--. 1 centos9 centos9 24 Sep 24 13:22 second.txt
Why files are identical: Since both branches currently point to the same commit, the working directory contains the same files with identical content.
π Making Changes on the Development Branch
Now let's create some changes that will be specific to the dev
branch, demonstrating branch isolation.
Adding a New File
nano third.txt
After creating and saving the file with some content, let's check Git's perspective:
Checking Status After Adding Files
git status
Example Output:
On branch dev
Untracked files:
(use "git add <file>..." to include in what will be committed)
third.txt
nothing added to commit but untracked files present (use "git add" to track)
Understanding Git's message:
On branch dev
: Confirms we're working on the development branchUntracked files
: Git sees the new file but isn't monitoring it yet- The helpful suggestion tells us how to start tracking the file
Staging the New File
git add .
What git add .
does:
- Stages all changes in the current directory
- Prepares files for the next commit
- Moves files from "untracked" to "staged" state
Checking Status After Staging
git status
Example Output:
On branch dev
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
new file: third.txt
Status explanation:
- File is now in the staging area
- Ready to be committed
- Git provides helpful command to unstage if needed
Committing the Changes
git commit -m "added third.txt"
Example Output:
[dev 09f228c] added third.txt
1 file changed, 1 insertion(+)
create mode 100644 third.txt
Understanding the commit output:
[dev 09f228c]
: Shows branch name and new commit hash1 file changed, 1 insertion(+)
: Statistics of the changescreate mode 100644
: File permissions for the new file
π Examining Branch History and Differences
After making commits on different branches, their histories begin to diverge.
Viewing Commit History on Dev Branch
git log
Example Output:
commit 09f228cc64cd1c9373f7a09b5cb553317785d41e (HEAD -> dev)
Author: Owais Abbasi <owais.abbasi9@gmail.com>
Date: Wed Sep 24 13:27:44 2025 +0500
added third.txt
commit 61460b32d6fabc6b2f42cfcef35a32ad4ff14686 (master)
Author: Owais Abbasi <owais.abbasi9@gmail.com>
Date: Wed Sep 24 13:22:27 2025 +0500
added few files
Key observations:
HEAD -> dev
: Shows current position and active branch(master)
: Indicates where master branch points- Dev branch has one additional commit
Switching Back to Master
git checkout master
Viewing Master Branch History
git log
Example Output:
commit 61460b32d6fabc6b2f42cfcef35a32ad4ff14686 (HEAD -> master)
Author: Owais Abbasi <owais.abbasi9@gmail.com>
Date: Wed Sep 24 13:22:27 2025 +0500
added few files
Important difference:
- Master branch has only one commit
- The commit made to dev branch is not visible in master's history
- This demonstrates branch isolation
Confirming File Differences
ls -al
Example Output on Master:
total 8
drwxr-xr-x. 3 centos9 centos9 53 Sep 24 13:28 .
drwxr-xr-x. 3 centos9 centos9 23 Sep 24 13:21 ..
-rw-r--r--. 1 centos9 centos9 23 Sep 24 13:21 first.txt
drwxr-xr-x. 8 centos9 centos9 166 Sep 24 13:28 .git
-rw-r--r--. 1 centos9 centos9 24 Sep 24 13:22 second.txt
Notice: third.txt
is missing from the master branch because it was only added to the dev branch.
Switching Back to Dev to Confirm
git checkout dev
ls -al
Example Output on Dev:
total 12
drwxr-xr-x. 3 centos9 centos9 70 Sep 24 13:29 .
drwxr-xr-x. 3 centos9 centos9 23 Sep 24 13:21 ..
-rw-r--r--. 1 centos9 centos9 23 Sep 24 13:21 first.txt
drwxr-xr-x. 8 centos9 centos9 166 Sep 24 13:29 .git
-rw-r--r--. 1 centos9 centos9 24 Sep 24 13:22 second.txt
-rw-r--r--. 1 centos9 centos9 17 Sep 24 13:29 third.txt
Confirmation: third.txt
exists on the dev branch, demonstrating perfect isolation between branches.
π Advanced Branch Comparison Commands
Git provides powerful commands to compare branches and understand their differences.
Comparing Branch Commit Differences
Commits in Dev but Not in Master
git log master..dev
Example Output:
commit 09f228cc64cd1c9373f7a09b5cb553317785d41e (HEAD -> dev)
Author: Owais Abbasi <owais.abbasi9@gmail.com>
Date: Wed Sep 24 13:27:44 2025 +0500
added third.txt
What this shows: All commits that exist in dev
but not in master
.
Commits in Master but Not in Dev
git log dev..master
Example Output: (empty output initially)
What this means: Currently, master has no commits that dev doesn't have.
π Your First Merge: Fast-Forward Merge
When one branch is directly ahead of another (no divergent commits), Git performs a "fast-forward" merge.
Merging Dev into Master
git checkout master
git merge dev
Example Output:
Updating 61460b3..09f228c
Fast-forward
third.txt | 1 +
1 file changed, 1 insertion(+)
create mode 100644 third.txt
Understanding fast-forward merge:
Fast-forward
: Git moved the master branch pointer forward- No new commit was created
- Master now points to the same commit as dev
third.txt
is now available on master
Verifying the Merge
ls -ahl
Example Output:
total 12K
drwxr-xr-x. 3 centos9 centos9 70 Sep 24 13:33 .
drwxr-xr-x. 3 centos9 centos9 23 Sep 24 13:21 ..
-rw-r--r--. 1 centos9 centos9 23 Sep 24 13:21 first.txt
drwxr-xr-x. 8 centos9 centos9 183 Sep 24 13:33 .git
-rw-r--r--. 1 centos9 centos9 24 Sep 24 13:22 second.txt
-rw-r--r--. 1 centos9 centos9 17 Sep 24 13:33 third.txt
Success: third.txt
now exists in the master branch.
Checking Unified History
git log
Example Output:
commit 09f228cc64cd1c9373f7a09b5cb553317785d41e (HEAD -> master, dev)
Author: Owais Abbasi <owais.abbasi9@gmail.com>
Date: Wed Sep 24 13:27:44 2025 +0500
added third.txt
commit 61460b32d6fabc6b2f42cfcef35a32ad4ff14686
Author: Owais Abbasi <owais.abbasi9@gmail.com>
Date: Wed Sep 24 13:22:27 2025 +0500
added few files
Important note: Both HEAD -> master
and dev
now point to the same commit.
π Creating Divergent Branches
Now let's create a more complex scenario where both branches have unique commits, requiring a true merge.
Making Changes on Master Branch
git checkout master
nano second.txt # Add content: "hello world"
After editing the file:
cat second.txt
Example Output:
This is the second file
hello world
Staging and Committing Master Changes
git add .
git commit -m "updated second.txt"
Example Output:
[master 5fe32d0] updated second.txt
1 file changed, 1 insertion(+)
Viewing Master Branch History
git log
Example Output:
commit 5fe32d0847de689fb3e3fe0515461985b31d8cf8 (HEAD -> master)
Author: Owais Abbasi <owais.abbasi9@gmail.com>
Date: Wed Sep 24 13:35:14 2025 +0500
updated second.txt
commit 09f228cc64cd1c9373f7a09b5cb553317785d41e (dev)
Author: Owais Abbasi <owais.abbasi9@gmail.com>
Date: Wed Sep 24 13:27:44 2025 +0500
added third.txt
Notice: Master has moved ahead with (dev)
indicating where dev branch currently points.
Checking Dev Branch State
git checkout dev
cat second.txt
Example Output:
This is the second file
Key observation: The changes made to second.txt
on master are not reflected in the dev branch. The branches have now diverged.
Making Independent Changes on Dev
git checkout dev
nano fifth.txt # Add content: "new fifth file"
git add .
git commit -m "added fifth.txt"
Example Output:
[dev c1b9188] added fifth.txt
1 file changed, 1 insertion(+)
create mode 100644 fifth.txt
π Understanding Branch Divergence
At this point, both branches have commits the other doesn't have.
Viewing Differences Between Branches
Commits in Master but Not in Dev
git checkout master
git log dev..master
Example Output:
commit 89d5d17f538430e5295da5ac53340f57a5a0ebdc (HEAD -> master)
Author: Owais Abbasi <owais.abbasi9@gmail.com>
Date: Wed Sep 24 13:46:58 2025 +0500
added fourth.txt
Commits in Dev but Not in Master
git log master..dev
Example Output:
commit c1b9188cbefe8360bf9f6a2e7191417111c95ab2 (dev)
Author: Owais Abbasi <owais.abbasi9@gmail.com>
Date: Wed Sep 24 13:49:03 2025 +0500
added fifth.txt
Understanding divergence: Both branches now have unique commits that need to be merged.
π€ Performing a True Merge
When branches have diverged, Git creates a merge commit to combine the histories.
Merging Divergent Branches
git checkout master
git merge dev
Example Output:
Merge made by the 'ort' strategy.
fifth.txt | 1 +
1 file changed, 1 insertion(+)
create mode 100644 fifth.txt
Understanding the merge:
'ort' strategy
: Git's recursive merge strategy for divergent branches- A new merge commit is created automatically
- Both branch histories are preserved
Examining the Merge Result
git log
Example Output:
commit e3bd41e2222a54729e15b529d79befaf3f065fc7 (HEAD -> master)
Merge: 89d5d17 c1b9188
Author: Owais Abbasi <owais.abbasi9@gmail.com>
Date: Wed Sep 24 13:50:44 2025 +0500
Merge branch 'dev'
commit c1b9188cbefe8360bf9f6a2e7191417111c95ab2 (dev)
Author: Owais Abbasi <owais.abbasi9@gmail.com>
Date: Wed Sep 24 13:49:03 2025 +0500
added fifth.txt
commit 89d5d17f538430e5295da5ac53340f57a5a0ebdc
Author: Owais Abbasi <owais.abbasi9@gmail.com>
Date: Wed Sep 24 13:46:58 2025 +0500
added fourth.txt
Key features of merge commit:
Merge: 89d5d17 c1b9188
: References both parent commits- Automatic commit message: "Merge branch 'dev'"
- Preserves both branch histories
Verifying All Files Are Present
ls -ahl
Example Output:
total 20K
drwxr-xr-x. 3 centos9 centos9 105 Sep 24 13:50 .
drwxr-xr-x. 3 centos9 centos9 23 Sep 24 13:21 ..
-rw-r--r--. 1 centos9 centos9 15 Sep 24 13:50 fifth.txt
-rw-r--r--. 1 centos9 centos9 23 Sep 24 13:21 first.txt
-rw-r--r--. 1 centos9 centos9 12 Sep 24 13:49 fourth.txt
drwxr-xr-x. 8 centos9 centos9 183 Sep 24 13:53 .git
-rw-r--r--. 1 centos9 centos9 36 Sep 24 13:36 second.txt
-rw-r--r--. 1 centos9 centos9 17 Sep 24 13:33 third.txt
Perfect merge: All files from both branches are now present in master.
π Synchronizing Branches After Merge
After merging, the dev branch is behind master and needs to be updated.
Updating Dev Branch
git checkout dev
git merge master
Example Output:
Updating c1b9188..e3bd41e
Fast-forward
fourth.txt | 1 +
1 file changed, 1 insertion(+)
create mode 100644 fourth.txt
Result: Dev branch now includes all changes from master, and both branches are synchronized.
π Branch Management Commands Summary
Here's a comprehensive table of essential Git branch commands:
Command | Purpose | Example Output/Usage |
---|---|---|
git branch | List all branches | Shows branches with * indicating current |
git branch -v | List branches with last commit info | Includes commit hash and message |
git branch <name> | Create new branch | git branch feature-x |
git checkout <branch> | Switch to branch | Updates working directory |
git checkout -b <name> | Create and switch to new branch | Combines creation and checkout |
git merge <branch> | Merge branch into current | Creates merge commit if needed |
git log branch1..branch2 | Show commits in branch2 not in branch1 | Compare branch differences |
git branch -d <name> | Delete merged branch | Safe deletion of merged branches |
git branch -D <name> | Force delete branch | Deletes unmerged branches |
π― Merge Types Explained
Understanding different merge types helps you choose the right strategy:
Merge Type | When It Occurs | Result | History |
---|---|---|---|
Fast-forward | Target branch directly ahead | Branch pointer moves forward | Linear history |
True Merge | Branches have diverged | New merge commit created | Branched history preserved |
Squash Merge | Using --squash flag | Single commit with all changes | Linear, loses branch history |
π¨ Common Scenarios and Best Practices
Working with Team Branches
π‘ Team Workflow: In team environments, always pull the latest changes before creating new branches and before merging.
# 1. Update your main branch
git checkout main
git pull origin main
# 2. Create feature branch
git checkout -b feature/user-authentication
# 3. Work on your feature
# ... make changes and commits ...
# 4. Before merging, update main again
git checkout main
git pull origin main
# 5. Merge your feature
git merge feature/user-authentication
# 6. Push to remote
git push origin main
# 7. Clean up
git branch -d feature/user-authentication
Handling Merge Conflicts
When the same file is modified in both branches, Git cannot automatically merge:
# Attempt to merge
git merge feature-branch
# If conflicts occur, Git will pause and show:
# Auto-merging filename.txt
# CONFLICT (content): Merge conflict in filename.txt
# Automatic merge failed; fix conflicts and then commit the result.
# 1. Check which files have conflicts
git status
# 2. Edit conflicted files manually
# Look for conflict markers: <<<<<<<, =======, >>>>>>>
# 3. Stage resolved files
git add filename.txt
# 4. Complete the merge
git commit -m "Resolved merge conflict in filename.txt"
β οΈ Important: Never commit files with conflict markers still present. Always resolve conflicts completely before committing.
π― Key Takeaways
β Remember These Points
- Branches are Mandatory: Git always uses branches; understanding them is essential
- Branch Isolation: Changes on one branch don't affect others until merged
- Two Merge Types: Fast-forward for linear history, true merge for divergent branches
- Clean Workflow: Always check status and branch location before making changes
- Team Coordination: Pull latest changes before creating branches and merging
π οΈ Git Branching Command Quick Reference
Essential Commands Cheat Sheet
Task | Command | Description |
---|---|---|
Check current branch | git branch | Lists all branches, * shows current |
Create new branch | git branch <name> | Creates branch from current commit |
Switch branches | git checkout <branch> | Changes working directory to branch |
Create and switch | git checkout -b <name> | Creates new branch and switches to it |
Show branch details | git branch -v | Shows last commit hash and message |
Merge branch | git merge <branch> | Merges specified branch into current |
Compare branches | git log A..B | Shows commits in B but not A |
Delete merged branch | git branch -d <name> | Safely deletes merged branches |
Force delete branch | git branch -D <name> | Deletes branch even if unmerged |
Check repository status | git status | Shows current branch and changes |
View commit history | git log | Shows commits on current branch |
π Congratulations! You've mastered Git branching and merging fundamentals. You now understand how branches provide isolation for development work, how merging combines different lines of development, and the difference between fast-forward and true merges.
What's your next step? Practice these commands in your own projects and experiment with different branching strategies to solidify your understanding.
π¬ Discussion
I'd love to hear about your Git branching experience:
- What branching strategies work best for your projects?
- Have you encountered complex merge conflicts? How did you resolve them?
- Which commands from this guide do you find most useful in daily development?
- Are there specific Git workflows you'd like me to cover in future posts?
Connect with me: