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.

branches are pointers


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


HEAD pointer

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:

example-head


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:

branches-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

example-history

git log --oneline --graph master..experimental
# shows C and D

example-history

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

  1. Create branch from up-to-date main
  2. Work on feature with regular commits
  3. Test thoroughly before merging
  4. Request code review
  5. Merge to main after approval
  6. Delete feature branch after merge
  7. 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

  1. Create a repository called ‘my-site’
  2. Add a README file
  3. Create three branches: feature-header, feature-footer, feature-sidebar
  4. Make different changes in each branch
  5. Practice viewing the history with git log --graph --oneline