What Are Branches?
A branch in Git is essentially a moveable pointer to a specific commit.
Branches are lightweight - a branch is just a file containing a commit hash.
Files you commit on one branch are not visible when you switch to another.
Why Use Branches?
-
Safe experimentation - Try new features without breaking working code
-
Parallel development - Multiple people can work on different features simultaneously
-
Easy rollback - Discard experimental work if it doesn’t work out
-
Version support - apply fixes to previous versions
Listing Branches
When you create a repository, Git automatically creates a default branch (usually called main
or master
).
# See current branch
git branch
# See all branches with more details
git branch -v
# List all branches (local and remote)
git branch -a
Branch Visualization
Multiple branches can point to the same commit.
Creating a New Branch
# Create a new branch (but stay on current branch)
git branch feature-user-profile
# Create and immediately switch to new branch
git checkout -b feature-user-profile
# Modern alternative (Git 2.23+)
git switch -c feature-user-profile
Branch Naming Conventions
# Good branch names
feature/user-authentication
bugfix/login-timeout
docs/api-documentation
refactor/database-queries
# Poor branch names
fix
temp
my-branch
new-stuff
Switching Between Branches
# Switch to existing branch
git checkout main
git checkout feature-user-profile
# Modern alternative (Git 2.23+)
git switch main
git switch feature-user-profile
Since I am old, you’d probably see me using the old commands out of habit.
The HEAD meta-branch
Git tracks the current branch in a special ref called HEAD
.
It is similar to a branch in that it can be used as an argument where-ever a branch is needed.
But it is NOT a true branch - it points to the current branch
Branches point to commits; HEAD points at a branch
All of the following commands will do the same thing - display the contents of the commit that is pointed to by the branch, that is currently checked-out
git show HEAD
git show master
git show f30ab
Checkout
The checkout command does 2 main things:
- Changes the branch that
HEAD
points to - Overwrites the contents of the working directory with
the contents of the commit pointed by the new
HEAD
branch
In this example HEAD
is pointing to the testing
branch
which is one commit ahead of master
:
Replicate the state of the repository from the picture
Renaming Branches
# Rename current branch
git branch -m new-name
# Rename specific branch
git branch -m old-name new-name
Deleting Branches
# Delete merged branch (safe)
git branch -d feature-name
# Force delete branch (even if unmerged)
git branch -D feature-name
# Delete remote tracking branch
# more on this later
git branch -dr origin/feature-name
Branches can diverge
Until now we have been looking at linear histories. But often branches will diverge:
Later we will explore how to merge them back together
Viewing divergent trees
log
provides a couple of options for viewing commit ranges:
# shows all commits on my_branch that
# are NOT on master
git log --oneline --graph main..my_branch
# shows all commits on both main and my_branch
# but NOT the shared ancestry
git log --oneline --graph main...my_branch
git log --oneline --graph master..experimental
# shows C and D
git log --oneline --graph master...experimental
# shows E, F, C and D
Tracking Remote Branches
# See all branches (local and remote)
git branch -a
# Create local branch that tracks remote
git checkout -b feature-branch origin/feature-branch
# Simplified version (Git 2.23+)
# Auto-tracks if remote exists
git switch feature-branch
Working with Remote Branches
# Create local branch
git checkout -b new-feature
# make changes, commit and push to remote
git push -u origin new-feature
# Delete remote branch
git push origin --delete old-feature
# Update remote tracking branches
git fetch --prune
Branch Life-cycle
- Create branch from up-to-date main
- Work on feature with regular commits
- Test thoroughly before merging
- Request code review
- Merge to main after approval
- Delete feature branch after merge
- Update local main branch
Detached HEAD
If HEAD points directly at a commit, git will inform you that you are in a detached HEAD state.
git checkout <commit>
# prints:
# Note: switching to '<commit>'.
#
# You are in 'detached HEAD' state.
# You can look around, make experimental changes
# ...
Example of using branches
# Start from main branch
git checkout main
# Create and switch to feature branch
git checkout -b add-login-system
# Verify you're on the new branch
git branch
# * add-login-system
# main
# Make some changes
echo "login.html" > login.html
echo "auth.js" > auth.js
# Commit the changes
git add .
git commit -m "feat: add basic login system files"
# Switch back to main
git switch main
# Notice: login.html and auth.js are not here!
ls
What happens when you switch branches with uncommitted changes?
- Git prevents the switch and asks you to commit first
- Git automatically commits the changes
- Git moves the changes to the new branch
- Git deletes the changes
Feature Branch Workflow
- Create a repository called ‘my-site’
- Add a README file
- Create three branches:
feature-header
,feature-footer
,feature-sidebar
- Make different changes in each branch
- Practice viewing the history with
git log --graph --oneline