Ready to master Git branching? After learning how to push and pull changes, it's time to explore one of Git's most powerful features: branching. This tutorial follows a real terminal session with detailed explanations of creating, switching, and managing branches both locally and on GitHub.
🎯 What You'll Learn: In this comprehensive guide, you'll discover:
- Understanding what Git branches are and why they're essential
- Creating new local branches with git branch
- Switching between branches safely with git checkout
- Making commits on different branches independently
- Pushing local branches to GitHub remote repositories
- Understanding upstream tracking for branches
- Pulling remote branches to your local machine
- Creating local branches from remote branches
- Synchronizing branch changes between local and remote
- Best practices for branch management and naming conventions
Prerequisites: Understanding of Git push/pull operations and a GitHub repository
🌳 Understanding Git Branches
What Are Branches?
Git Branch: An independent line of development that allows you to work on features, fixes, or experiments without affecting the main codebase.
Real-World Analogy: Think of branches like parallel universes in your project. You can create a new universe (branch) to experiment with changes, and if things go well, you can merge that universe back into the main timeline. If not, you can simply discard it without affecting the original.
Key Benefits:
- ✅ Isolation: Work on features without breaking the main code
- ✅ Experimentation: Try new ideas safely
- ✅ Collaboration: Multiple developers work on different features simultaneously
- ✅ Organization: Separate production code from development work
Current Repository Status
Let's start by examining our repository's current state:
[02:41:59 centos9@vbox seconddemo]$ git branch
* master
Command Explanation:
git branch- Lists all local branches in your repository- ***** (asterisk) - Indicates the currently active branch
- master - The default primary branch in this repository
Current State: We only have one branch (master) and we're currently on it.
Viewing Commit History
Let's see what commits exist in our repository:
[02:43:35 centos9@vbox seconddemo]$ git log
commit 8c331caa10309fcb76a8cbd38c4f2e8cbff80b64 (HEAD -> master, hello/master)
Author: Owais Abbasi <81351747+owais-io@users.noreply.github.com>
Date: Tue Sep 30 23:47:49 2025 +0500
Update second.txt on github
commit 4a130bb7b63436556220809afcaefe58260d7c45
Author: Owais Abbasi <owais.abbasi9@gmail.com>
Date: Tue Sep 30 23:43:25 2025 +0500
updated second.txt
commit a38542e836ebbc1e75179c3b6b6c064efb72b8cd
Author: Owais Abbasi <owais.abbasi9@gmail.com>
Date: Tue Sep 30 23:30:38 2025 +0500
updated first.txt and added second.txt
commit 303fea0985b17714f6f3ed934684a653e11c6578
Author: Owais Abbasi <owais.abbasi9@gmail.com>
Date: Tue Sep 30 23:28:12 2025 +0500
added first.txt
Log Analysis:
- HEAD -> master - Your local branch pointer
- hello/master - Remote branch reference (GitHub)
- Commit history: Four commits showing the project's evolution
- Both pointers at same commit: Local and remote are synchronized
🔨 Creating Your First Branch
The Branch Creation Command
Let's create a new branch for development work:
[02:43:40 centos9@vbox seconddemo]$ git branch dev
[02:43:46 centos9@vbox seconddemo]$ git branch
dev
* master
Command Breakdown:
git branch dev- Creates a new branch named "dev"- No output - Success is silent in Git
- Verification:
git branchshows both branches now exist
Important Understanding:
- Creating a branch does NOT switch to it automatically
- The new branch starts from the current commit you're on
- Both branches currently point to the same commit
💡 Branch Naming Convention: Use descriptive names like feature/login, bugfix/payment, dev, staging, etc. Keep names lowercase with hyphens or slashes for separation.
Verifying Repository Status
[02:43:52 centos9@vbox seconddemo]$ git status
On branch master
Your branch is up to date with 'hello/master'.
nothing to commit, working tree clean
Status Breakdown:
- On branch master - Still on the master branch
- Up to date with 'hello/master' - Synchronized with GitHub
- Clean working tree - No uncommitted changes
🔄 Switching Between Branches
The Checkout Command
Let's switch to our new dev branch:
[02:43:56 centos9@vbox seconddemo]$ git checkout dev
Switched to branch 'dev'
[02:44:03 centos9@vbox seconddemo]$ git status
On branch dev
nothing to commit, working tree clean
Command Explanation:
git checkout dev- Switches your working directory to the dev branch- "Switched to branch 'dev'" - Confirmation message
- Status changes: Now shows "On branch dev"
What Happens During Checkout:
- Git updates your working directory files to match the branch
- HEAD pointer moves to the new branch
- Future commits will be made on this branch
⚠️ Important: Always commit or stash your changes before switching branches. Uncommitted changes can cause conflicts or be lost when switching.
📝 Working on a New Branch
Creating Content on Dev Branch
Let's add a new file to our dev branch:
[02:44:06 centos9@vbox seconddemo]$ vim third.txt
[02:44:59 centos9@vbox seconddemo]$ cat third.txt
working
Steps Performed:
- Created and edited
third.txtusing vim - Added content: "working"
- Important: This file exists only in our working directory, not yet tracked by Git
Checking File Status
[02:45:01 centos9@vbox seconddemo]$ git status
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)
Status Analysis:
- On branch dev - Confirms we're on the dev branch
- Untracked files: Git sees
third.txtbut isn't tracking it yet - Helpful hint: Git suggests using
git addto track the file
Staging and Committing on Dev Branch
[02:45:25 centos9@vbox seconddemo]$ git add .
[02:45:26 centos9@vbox seconddemo]$ git commit -m "added third.txt"
[dev 87de0f7] added third.txt
1 file changed, 1 insertion(+)
create mode 100644 third.txt
[02:45:34 centos9@vbox seconddemo]$ git status
On branch dev
nothing to commit, working tree clean
Commit Analysis:
- [dev 87de0f7] - Shows branch name and commit hash
- 1 file changed, 1 insertion(+) - Summary of changes
- create mode 100644 - File permissions set
- Clean working tree: All changes committed successfully
📊 Understanding Branch Divergence
Viewing Branch-Specific History
Let's examine the commit history on dev branch:
[02:45:36 centos9@vbox seconddemo]$ git log
commit 87de0f7ad3b2e2f1e68e2f17fe1c2a559a87ce24 (HEAD -> dev)
Author: Owais Abbasi <owais.abbasi9@gmail.com>
Date: Sun Oct 19 02:45:34 2025 +0500
added third.txt
commit 8c331caa10309fcb76a8cbd38c4f2e8cbff80b64 (hello/master, master)
Author: Owais Abbasi <81351747+owais-io@users.noreply.github.com>
Date: Tue Sep 30 23:47:49 2025 +0500
Update second.txt on github
commit 4a130bb7b63436556220809afcaefe58260d7c45
Author: Owais Abbasi <owais.abbasi9@gmail.com>
Date: Tue Sep 30 23:43:25 2025 +0500
updated second.txt
commit a38542e836ebbc1e75179c3b6b6c064efb72b8cd
Author: Owais Abbasi <owais.abbasi9@gmail.com>
Date: Tue Sep 30 23:30:38 2025 +0500
updated first.txt and added second.txt
commit 303fea0985b17714f6f3ed934684a653e11c6578
Author: Owais Abbasi <owais.abbasi9@gmail.com>
Date: Tue Sep 30 23:28:12 2025 +0500
added first.txt
Understanding the References:
- (HEAD -> dev) - Current position on dev branch
- (hello/master, master) - Where master and remote master branches point
- New commit 87de0f7 - Exists only on dev branch
- Branch divergence: Dev has one more commit than master
Visual Branch Representation:
master: A -- B -- C -- D
^
master (local)
hello/master (remote)
dev: A -- B -- C -- D -- E
^
HEAD -> dev
Where:
A = "added first.txt"
B = "updated first.txt and added second.txt"
C = "updated second.txt"
D = "Update second.txt on github"
E = "added third.txt" (only on dev)
Current State: The dev branch has moved forward with a new commit, while master remains at the previous commit.
🚀 Pushing Branches to GitHub
Understanding Remote Branch Tracking
Before pushing, let's check our remote configuration:
[02:46:37 centos9@vbox seconddemo]$ git remote -v
hello https://github.com/owais-io/secondproject.git (fetch)
hello https://github.com/owais-io/secondproject.git (push)
Remote Configuration:
- Remote name: "hello" (custom name, usually "origin")
- fetch URL: Where we pull changes from
- push URL: Where we push changes to
Pushing a New Branch with Upstream Tracking
Let's push our dev branch to GitHub:
[02:47:14 centos9@vbox seconddemo]$ git push -u hello dev
Username for 'https://github.com': owais-io
Password for 'https://owais-io@github.com':
Enumerating objects: 4, done.
Counting objects: 100% (4/4), done.
Delta compression using up to 4 threads
Compressing objects: 100% (2/2), done.
Writing objects: 100% (3/3), 317 bytes | 317.00 KiB/s, done.
Total 3 (delta 0), reused 0 (delta 0), pack-reused 0 (from 0)
remote:
remote: Create a pull request for 'dev' on GitHub by visiting:
remote: https://github.com/owais-io/secondproject/pull/new/dev
remote:
To https://github.com/owais-io/secondproject.git
* [new branch] dev -> dev
branch 'dev' set up to track 'hello/dev'.
Command Breakdown:
git push -u hello dev- Pushes dev branch to remote "hello"-uor--set-upstream- Sets up tracking relationship- Authentication: Prompts for GitHub username and Personal Access Token
Push Output Analysis:
| Output Line | Meaning | Significance |
|---|---|---|
| Enumerating objects: 4 | Git identifies objects to transfer | Includes the new commit and file |
| Compressing objects: 100% (2/2) | Optimizes data transfer | Reduces bandwidth usage |
| Writing objects: 317 bytes | Data transfer size | Very small - just one new file |
| [new branch] dev -> dev | Created new remote branch | GitHub now has a dev branch |
| branch 'dev' set up to track 'hello/dev' | Upstream tracking established | Future pushes can use just git push |
GitHub's Helpful Message:
Create a pull request for 'dev' on GitHub by visiting:
https://github.com/owais-io/secondproject/pull/new/dev
This URL allows you to create a pull request to merge dev into master on GitHub - we'll cover this in the next tutorial!
Verifying Branch on GitHub
After pushing, you can verify the branch exists on GitHub:
- Navigate to your repository on GitHub
- Click the branch dropdown (usually shows "main" or "master")
- You should see "dev" listed as an available branch
- Switch to the dev branch to see
third.txtthat exists only in this branch - The master branch will still have only 2 files (first.txt and second.txt)
🔀 Merging Branches Locally
Switching to Master Branch
Let's switch back to master and merge our dev changes:
[02:53:26 centos9@vbox seconddemo]$ git checkout master
Switched to branch 'master'
Your branch is up to date with 'hello/master'.
Checkout Confirmation:
- Successfully switched to master
- Status shows synchronization with remote master
Performing the Merge
[02:53:35 centos9@vbox seconddemo]$ git merge dev
Updating 8c331ca..87de0f7
Fast-forward
third.txt | 1 +
1 file changed, 1 insertion(+)
create mode 100644 third.txt
Merge Explanation:
git merge dev- Merges dev branch into current branch (master)- Fast-forward - Clean merge without conflicts
- Updating commit range: Shows the commits being merged
- 1 file changed: third.txt was added
Understanding Fast-Forward: Since master hasn't changed since dev was created, Git can simply move the master pointer forward to include the dev commits. No merge commit is needed.
Checking Post-Merge Status
[02:53:40 centos9@vbox seconddemo]$ git status
On branch master
Your branch is ahead of 'hello/master' by 1 commit.
(use "git push" to publish your local commits)
nothing to commit, working tree clean
Status Analysis:
- On branch master - Back on master branch
- Ahead by 1 commit - Local master has the merge that remote doesn't have yet
- Helpful suggestion: Git prompts us to push
Viewing Post-Merge History
[02:53:48 centos9@vbox seconddemo]$ git log
commit 87de0f7ad3b2e2f1e68e2f17fe1c2a559a87ce24 (HEAD -> master, hello/dev, dev)
Author: Owais Abbasi <owais.abbasi9@gmail.com>
Date: Sun Oct 19 02:45:34 2025 +0500
added third.txt
commit 8c331caa10309fcb76a8cbd38c4f2e8cbff80b64 (hello/master)
Author: Owais Abbasi <81351747+owais-io@users.noreply.github.com>
Date: Tue Sep 30 23:47:49 2025 +0500
Update second.txt on github
[... previous commits ...]
Key Observations:
- (HEAD -> master, hello/dev, dev) - Local master and dev now point to same commit
- (hello/master) - Remote master is still one commit behind
- Linear history: Fast-forward merge maintains clean history
📤 Pushing Merged Changes
Pushing Master to Remote
[02:54:33 centos9@vbox seconddemo]$ git status
On branch master
Your branch is ahead of 'hello/master' by 1 commit.
(use "git push" to publish your local commits)
nothing to commit, working tree clean
[02:54:33 centos9@vbox seconddemo]$ git push hello master
Username for 'https://github.com': owais-io
Password for 'https://owais-io@github.com':
Total 0 (delta 0), reused 0 (delta 0), pack-reused 0 (from 0)
To https://github.com/owais-io/secondproject.git
8c331ca..87de0f7 master -> master
Push Analysis:
- Total 0 - Objects already on GitHub (we pushed them with dev branch)
- 8c331ca..87de0f7 - Commit range being updated
- master -> master - Local master pushed to remote master
Verification on GitHub: After this push, GitHub's master branch will now also contain third.txt. Both master and dev branches on GitHub have the same content now.
📥 Creating Branches on GitHub and Pulling Locally
Creating a Branch Directly on GitHub
The session demonstrates creating a branch called "newtest" directly on GitHub's web interface:
Steps to Create Branch on GitHub:
- Go to your repository on GitHub
- Click the branch dropdown (shows current branch, e.g., "master")
- Type the new branch name in the search box: "newtest"
- When it shows "Create branch: newtest from 'master'", click it
- The new branch is created on GitHub, based on the current branch you're viewing
Detecting Remote Branches Locally
Let's see how Git detects new remote branches:
[03:01:23 centos9@vbox seconddemo]$ git status
On branch master
Your branch is up to date with 'hello/master'.
nothing to commit, working tree clean
[03:01:34 centos9@vbox seconddemo]$ git pull
From https://github.com/owais-io/secondproject
* [new branch] newtest -> hello/newtest
Already up to date.
Pull Output Explanation:
- [new branch] newtest -> hello/newtest - Git discovered a new remote branch
- Already up to date - No changes to current branch (master)
- Remote tracking: Git now knows about hello/newtest
Checking Local Branches
[03:01:53 centos9@vbox seconddemo]$ git branch
dev
* master
Important Observation:
- Only dev and master appear in local branches
- The newtest branch is not automatically created locally
- It exists as a remote tracking branch (hello/newtest) but not as a local branch yet
Creating Local Branch from Remote
Let's create a local version of the newtest branch:
[03:02:04 centos9@vbox seconddemo]$ git status
On branch master
Your branch is up to date with 'hello/master'.
nothing to commit, working tree clean
[03:02:26 centos9@vbox seconddemo]$ git checkout newtest
branch 'newtest' set up to track 'hello/newtest'.
Switched to a new branch 'newtest'
[03:02:30 centos9@vbox seconddemo]$ git status
On branch newtest
Your branch is up to date with 'hello/newtest'.
nothing to commit, working tree clean
Checkout Magic:
git checkout newtest- Git is smart enough to know you want the remote branch- Automatic tracking setup: Creates local branch and sets upstream automatically
- "Switched to a new branch": Created local newtest tracking hello/newtest
Verifying All Branches
[03:02:51 centos9@vbox seconddemo]$ git branch
dev
master
* newtest
Branch List:
- Three local branches now exist
- ***** shows we're currently on newtest
- All branches are synchronized with their remote counterparts
💼 Working on a Remote-Created Branch
Making Changes on Newtest Branch
Let's add some changes to our new branch:
[03:02:51 centos9@vbox seconddemo]$ vim second.txt
[03:03:24 centos9@vbox seconddemo]$ cat second.txt
working
working again
hello from remote repo on github
hello
Changes Made:
- Opened second.txt in vim
- Added a new line: "hello"
- File now has 4 lines of content
Staging and Committing Changes
[03:03:27 centos9@vbox seconddemo]$ git status
On branch newtest
Your branch is up to date with 'hello/newtest'.
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in working directory)
modified: second.txt
no changes added to commit (use "git add" and/or "git commit -a")
[03:03:32 centos9@vbox seconddemo]$ git add .
[03:03:37 centos9@vbox seconddemo]$ git commit -m "updated second.txt"
[newtest 6d3aac9] updated second.txt
1 file changed, 2 insertions(+)
Commit Analysis:
- [newtest 6d3aac9] - Committed on newtest branch
- 1 file changed, 2 insertions(+) - Added 2 new lines
Checking Status Before Push
[03:03:46 centos9@vbox seconddemo]$ git status
On branch newtest
Your branch is ahead of 'hello/newtest' by 1 commit.
(use "git push" to publish your local commits)
nothing to commit, working tree clean
Status Information:
- Ahead by 1 commit - Local newtest has changes remote doesn't have
- Git suggests pushing to synchronize
Pushing Branch Updates
[03:03:51 centos9@vbox seconddemo]$ git push hello newtest
Username for 'https://github.com': owais-io
Password for 'https://owais-io@github.com':
Enumerating objects: 5, done.
Counting objects: 100% (5/5), done.
Delta compression using up to 4 threads
Compressing objects: 100% (3/3), done.
Writing objects: 100% (3/3), 341 bytes | 341.00 KiB/s, done.
Total 3 (delta 1), reused 0 (delta 0), pack-reused 0 (from 0)
remote: Resolving deltas: 100% (1/1), completed with 1 local object.
To https://github.com/owais-io/secondproject.git
87de0f7..6d3aac9 newtest -> newtest
Push Success Indicators:
- Total 3 (delta 1) - Sent 3 objects with 1 delta compression
- Resolving deltas: GitHub processed the changes
- 87de0f7..6d3aac9 - Commit range updated on GitHub
- newtest -> newtest - Local newtest pushed to remote newtest
Verifying on GitHub
After this push:
- Navigate to the newtest branch on GitHub
- You'll see second.txt has the new "hello" line
- Master and dev branches remain unchanged (they don't have this modification)
🎯 Understanding Branch Isolation
Branch-Specific Content
One of the most powerful features of Git branches is isolation. Let's verify this:
On newtest branch:
- second.txt has 4 lines (including the new "hello" line)
- All three files exist (first.txt, second.txt, third.txt)
On master branch:
- second.txt would have 3 lines (without the "hello" modification)
- All three files exist
On dev branch:
- Same as master (they point to the same commit)
This demonstrates that changes made on one branch don't affect other branches until you explicitly merge them.
🏆 Best Practices for Branch Management
Branch Naming Conventions
| Branch Type | Naming Convention | Example |
|---|---|---|
| Feature Branches | feature/description | feature/user-authentication |
| Bug Fixes | bugfix/description | bugfix/login-error |
| Hotfixes | hotfix/description | hotfix/security-patch |
| Development | dev or develop | dev |
| Release | release/version | release/v1.2.0 |
Branch Workflow Best Practices
| Practice | Why Important | How To |
|---|---|---|
| Create Branches for Features | Isolate changes from main code | git branch feature/new-feature |
| Commit Before Switching | Prevent losing work | Always commit or stash changes first |
| Keep Branches Updated | Avoid merge conflicts | Regularly merge or rebase from main |
| Delete Merged Branches | Keep repository clean | git branch -d branch-name |
| Use Descriptive Names | Team understands purpose | Use feature/bugfix prefixes |
| Push Branches Early | Backup and collaboration | git push -u origin branch-name |
📋 Git Branch Commands Cheat Sheet
Essential Branch Commands
# List all local branches
git branch
# List all branches (including remote)
git branch -a
# Create a new branch
git branch branch-name
# Create and switch to new branch
git checkout -b branch-name
# Switch to existing branch
git checkout branch-name
# Delete a local branch (safe - prevents deleting unmerged)
git branch -d branch-name
# Force delete a local branch
git branch -D branch-name
# Rename current branch
git branch -m new-name
# Rename a specific branch
git branch -m old-name new-name
Remote Branch Commands
# Push branch to remote with upstream tracking
git push -u remote-name branch-name
# Push branch without upstream (subsequent pushes)
git push remote-name branch-name
# Pull changes for current branch
git pull
# Fetch all remote branches (doesn't merge)
git fetch remote-name
# List remote branches
git branch -r
# Delete remote branch
git push remote-name --delete branch-name
# Check out remote branch locally
git checkout remote-branch-name
# Show all branches with tracking info
git branch -vv
Branch Comparison Commands
# Show commits in branch1 but not in branch2
git log branch2..branch1
# Show differences between branches
git diff branch1..branch2
# Show branches that have been merged into current branch
git branch --merged
# Show branches that haven't been merged
git branch --no-merged
# See which branch you're on
git branch --show-current
# View detailed branch information
git show-branch
Merging Commands
# Merge branch into current branch
git merge branch-name
# Merge with commit message
git merge branch-name -m "Merge message"
# Abort a merge (if conflicts)
git merge --abort
# Continue merge after resolving conflicts
git merge --continue
🎯 Key Takeaways
✅ Branch Management Concepts Mastered
-
Branch Creation: Used
git branchto create new branches for isolated development -
Branch Switching: Mastered
git checkoutto switch between branches safely -
Branch Isolation: Understood how commits on one branch don't affect others
-
Remote Branches: Successfully pushed local branches to GitHub with upstream tracking
-
Pulling Remote Branches: Learned how to detect and checkout branches created on GitHub
-
Branch Merging: Performed fast-forward merges to integrate branch changes
-
Branch Synchronization: Kept local and remote branches synchronized with push/pull
-
Branch Tracking: Understood upstream relationships between local and remote branches
-
Multiple Branch Workflow: Worked with multiple branches simultaneously (master, dev, newtest)
🚀 What's Next?
Now that you've mastered Git branching fundamentals, you're ready to learn about collaborative team workflows! In the next tutorial, we'll explore:
- Git Flow Workflow: Industry-standard branching strategy
- Pull Requests: How to request code reviews on GitHub
- Branch Protection: Preventing direct commits to important branches
- Team Collaboration: Working with multiple developers
- Merge Strategies: Different ways to combine branches
🎉 Congratulations! You've successfully mastered:
- ✅ Creating and managing local Git branches
- ✅ Switching between branches safely
- ✅ Pushing branches to GitHub with upstream tracking
- ✅ Pulling remote branches to your local machine
- ✅ Merging branches using fast-forward merges
- ✅ Understanding branch isolation and independence
- ✅ Working with multiple branches simultaneously
Next Step: Learn about Git Workflow & Pull Requests to master team collaboration!
💬 Discussion
How is your Git branching experience going?
- Have you created branches for your projects yet?
- What branch naming convention do you prefer?
- Have you encountered any challenges when switching branches?
- Are you working on multiple branches simultaneously?
- What questions do you have about more advanced branching strategies?
