SovranCode
HomeCourses Git & GitHub Git Branch
This device
Course contentsGit Branch · 41 topics

1. Git Fundamentals

Git IntroductionGit Version ControlGit vs GitHubGit InstallationGit Working TreeGit RepositoryGit CommitGit .gitignoreGit Project: Learning Journal

2. Git History

Git LogGit DiffGit ResetGit RevertGit StashGit Project: Messy Repository

3. Branches & History

Git BranchGit MergeGit Merge ConflictsGit RebaseGit Cherry-PickGit TagsGit Project: Feature Branch

4. Remotes and GitHub

Git RemoteGitHub AuthenticationGitHub RepositoryGitHub ForkGitHub IssuesGitHub PagesGit Project: Two Clone Sync

5. GitHub Collaboration

GitHub Pull RequestsGitHub Code ReviewGit Branching WorkflowGitHub Branch ProtectionGitHub CollaborationGitHub ContributingGit Project: Reviewed Pull Request

6. Automation and Professional Git

GitHub ActionsGit InternalsGit RecoveryGitHub SecurityGit Project: Team Repository CIProject
Learn Git & GitHub40 complete · 1 planned

1. Git Fundamentals

Git IntroductionGit Version ControlGit vs GitHubGit InstallationGit Working TreeGit RepositoryGit CommitGit .gitignoreGit Project: Learning Journal

2. Git History

Git LogGit DiffGit ResetGit RevertGit StashGit Project: Messy Repository

3. Branches & History

Git BranchGit MergeGit Merge ConflictsGit RebaseGit Cherry-PickGit TagsGit Project: Feature Branch

4. Remotes and GitHub

Git RemoteGitHub AuthenticationGitHub RepositoryGitHub ForkGitHub IssuesGitHub PagesGit Project: Two Clone Sync

5. GitHub Collaboration

GitHub Pull RequestsGitHub Code ReviewGit Branching WorkflowGitHub Branch ProtectionGitHub CollaborationGitHub ContributingGit Project: Reviewed Pull Request

6. Automation and Professional Git

GitHub ActionsGit InternalsGit RecoveryGitHub SecurityGit Project: Team Repository CIProject
PREVIOUS · PROJECTGit Project: Messy Repository
NEXT LESSONGit Merge
3. Branches & History 70 min

Git Branch

Treat a branch as a movable pointer, follow HEAD, and recover from detached HEAD without discarding wanted commits.

What you will leave with

You will be able to draw branch refs and HEAD, predict which pointer a commit advances, create and switch branches without mixing operations, inspect divergence, enter detached HEAD deliberately, and preserve detached commits with a named branch.

Branches are names in a graph

PointTreat each branch as a named ref to one commit, not a copied directory.
FollowTrace HEAD through the current branch to its tip and parent history.
AdvancePredict which branch moves when a new commit is created.
RescueName detached commits before switching away or cleanup expires their recovery path.

A branch is a movable ref

A local branch such as main stores the object ID of one commit. That commit reaches its parents, so one pointer gives Git access to an entire line of history. Creating a branch adds another name at a chosen commit; it does not duplicate commit objects or working files.

  1. main
    C3

    Document formatter usage

  2. feature/search
    C2

    Add catalog data

  3. SHARED PARENT
    C1

    Initialize application

Both branch names can point to the same commit. Once one branch receives a new commit, its ref advances and the names diverge. The shared ancestors remain one set of objects.

Branches are inexpensive

The branch ref is small. Project files appear because a worktree checks out a commit; the files are not stored as a full branch copy.

HEAD identifies your checkout context

In the normal attached state, HEAD is a symbolic reference to the current local branch. The branch points to a commit. Git uses that chain to know which ref should advance after the next commit.

git status --short --branch
git branch --show-current
git log --oneline --decorate --graph --all
git rev-parse HEAD
git symbolic-ref --short HEAD
ATTACHED

HEAD → refs/heads/main → C3

A new commit creates C4 with C3 as parent, then moves main to C4.

DETACHED

HEAD → C3

A new commit can still be created, but no local branch automatically moves to name it.

git symbolic-ref --short HEAD prints the current branch in attached state and exits nonzero when HEAD is detached. git branch --show-current prints the branch name or an empty result when detached.

QUICK CHECK

Test what you learned

Type the command that prints only the currently attached branch name.

A commit advances only the attached branch

  1. 01
    Read HEAD

    Git resolves HEAD to the current branch and its tip commit.

  2. 02
    Create the commit object

    The new commit records the staged tree, metadata, message, and current tip as parent.

  3. 03
    Move the branch ref

    The attached branch changes from the former tip to the new commit.

  4. 04
    Keep other refs still

    Unrelated branches remain at their existing commits until an explicit operation moves them.

This is why switching branches before committing matters: the same staged snapshot committed on another attached branch advances a different name and changes the story told by the graph.

Create and switch branches explicitly

# Create a branch at the current commit and switch to it
git switch -c feature/search

# Make and inspect a commit on that branch
git add src/search.js
git diff --cached
git commit -m "Add catalog search"

# Return to main without merging
git switch main
git log --oneline --decorate --graph --all

git branch NAME

Create NAME at the current commit without switching the worktree or HEAD.

git switch NAME

Attach HEAD to an existing local branch and update the working tree and index for its commit.

git switch -c NAME

Create NAME at the chosen/default start point and switch to it.

git switch -C NAME START

Create or forcibly reset NAME to START before switching. This can discard a branch tip and needs preservation evidence.

Switching does not merge branches

Returning to main changes the checkout context. The feature commit remains reachable from feature/search and does not enter main until an integration operation moves or combines history.

Older Git often used git checkout both to switch branches and to restore files. This course uses git switch for branch movement. Restoring working-tree files belongs with Git Reset, where git restore is the dedicated command. git checkout still exists; treat it as an older combined Git interface, not a GitHub feature.

Switch only when the working state can survive

Git may carry compatible uncommitted changes across a switch, or refuse when checkout would overwrite them. A successful switch with local edits does not mean those edits belong to the destination branch.

git status --short
git diff
git diff --cached
git branch --show-current

# Then choose deliberately:
# - commit a coherent checkpoint
# - create a named stash for a brief pause
# - use a linked worktree for parallel contexts
# - restore only confirmed disposable edits

Do not force a switch to escape a confusing state. First identify every staged, unstaged, untracked, and ignored path and choose its destination.

Create a branch from the right start point

git switch -c feature/search main
git switch -c hotfix/payment v2.4.1
git branch investigation 8f42d91

git show --no-patch --decorate feature/search
git merge-base main feature/search

A branch can start at any resolvable commit, tag, or ref. Name the start point when it matters; “current commit” is safe only when you have proved where HEAD is. git merge-base identifies a best common ancestor used by later integration reasoning.

Read branch divergence without switching

git log --oneline --decorate --graph --all
git log main..feature/search --oneline
git log feature/search..main --oneline
git diff main...feature/search
git branch --contains 8f42d91
git branch --merged main
git branch --no-merged main

main..feature

Commits reachable from feature that are not reachable from main.

feature..main

Commits reachable from main that are not reachable from feature.

diff main...feature

Patch from their merge base to feature—the feature-side change since divergence.

branch --contains

Local branches whose histories reach the named commit.

Rename and delete refs safely

# Rename the current branch
git branch -m feature/catalog-search

# Delete only when Git considers it merged
git branch -d feature/catalog-search

# Inspect before considering force deletion
git log main..feature/catalog-search --oneline
git branch --contains feature/catalog-search

Renaming changes the local ref name, not the commit objects. Lowercase -d performs a merged-history safety check. Uppercase -D bypasses that protection; use it only after preserving or deliberately abandoning every commit unique to the branch.

Deletion removes a name, not necessarily an object immediately

Commits may remain reachable through other refs or reflogs. That is not permission to delete carelessly: reflogs expire and another clone may not have the same recovery data.

Detached HEAD is a valid inspection state

Checking out a commit, remote-tracking ref, or tag can detach HEAD. This is useful for inspecting or testing an exact snapshot without moving a branch.

git switch --detach 8f42d91
git branch --show-current
git rev-parse --short HEAD
git status --short --branch

# Inspect or test, then return without creating commits:
git switch main

Detached does not mean corrupted. The warning matters only when you create wanted commits and then switch away without giving them a durable ref.

Commits can exist while HEAD is detached

Git can create a commit with detached HEAD as its parent. HEAD advances directly to the new commit, but no local branch name follows. The commit is real and visible in the current checkout; it becomes harder to find after you leave.

  1. main
    C3

    Main remains here.

  2. DETACH
    C2

    HEAD was detached at an older commit.

  3. HEAD
    D1

    Wanted experiment commit has no branch name yet.

Name wanted detached work before leaving

If you switch away, D1 is no longer reached by HEAD or a branch. Reflog may recover it temporarily, but a branch created now is simpler and durable.

Rescue detached work immediately

# While detached, preserve the current commit with a new branch
git switch -c rescue/detached-work

# Verify HEAD is attached and the commit is reachable by name
git branch --show-current
git log --oneline --decorate --graph --all

If you already switched away, inspect the reflog, verify the candidate commit with git show, and create a branch at the exact ID:

git reflog --date=iso
git show --stat <detached-commit>
git branch rescue/detached-work <detached-commit>
git log --oneline --decorate --graph --all
QUICK CHECK

Test what you learned

While still on a wanted detached commit, type the command that creates and switches to rescue/experiment.

Understand the unborn initial branch

Immediately after git init -b main, HEAD can symbolically reference main even though no commit exists and the branch ref has not been created. This is an unborn branch state.

git symbolic-ref --short HEAD
# main

git rev-parse --verify HEAD
# exits nonzero because no commit exists yet

# The first commit creates the commit and makes main point to it.

This explains why some revision commands fail before the first commit while the status message can still name the intended branch.

Guided practice: draw and move refs

Use a disposable repository with three commits on main. Keep the working tree clean before each switch.

  1. 01
    Draw the attached state

    Record HEAD, main, the tip ID, and three parent relationships.

  2. 02
    Create a feature branch

    Switch to a new branch, make one coherent commit, and prove only that branch advanced.

  3. 03
    Return to main

    Show that the feature commit remains in the graph but is not reachable from main.

  4. 04
    Detach at the root

    Inspect the snapshot, create one experiment commit, and draw HEAD without a branch.

  5. 05
    Rescue the experiment

    Create a branch before leaving, return to main, and prove all refs and commits remain reachable.

Independent lab: recover an unnamed experiment

Create a disposable five-commit history and two local branches. Then complete this audit:

  1. Draw the initial graph with exact branch tips and HEAD attachment.
  2. Create a feature branch from the third commit, add two commits, and compare both directional ranges with main.
  3. Return to main and detach at the second commit.
  4. Create two experimental commits while detached and switch back to main without first naming them.
  5. Use reflog and show to identify the correct detached tip without guessing.
  6. Create rescue/experiment at that tip and prove both experiment commits are reachable.
  7. Use merged and no-merged reports to decide which practice branch can be deleted with lowercase -d.
  8. Finish with clean status and a graph whose every ref and parent edge you can explain.
Definition of done

No wanted commit is reachable only through reflog, every branch was created from an intentional start point, deletion decisions use graph evidence, and the final working tree is clean.

Common branch and HEAD mistakes

Treating a branch as copied files

The ref points to one commit. Worktree checkout produces files from the selected snapshot.

Creating from the wrong tip

Prove HEAD or name the intended start revision explicitly before creating a branch.

Assuming switch merges work

Switch changes checkout context; branch histories remain distinct until integration.

Carrying edits unknowingly

Inspect status and both diffs before and after switching so local changes retain an intentional owner.

Panicking at detached HEAD

Inspection is safe. Wanted commits need a branch name before their reflog-only path expires.

Force-deleting without containment proof

-D bypasses a useful guard. Preserve or explicitly abandon unique commits first.

Lesson review

You can now reason about branches as movable names over a shared commit graph. HEAD determines the current checkout and, when attached, which branch advances. Detached HEAD is useful and recoverable as long as wanted commits receive a durable ref.

  • I distinguish branch refs, HEAD, commits, the index, and working-tree files.
  • I can predict which branch advances after a commit.
  • I create branches from verified start points and inspect divergence without switching.
  • I recognize detached HEAD and preserve wanted commits with a branch.
  • I use containment and merged-history evidence before deleting a branch.

Related lessons

  • Git Merge — Integration moves history after the branch exists.
  • Git Log — Log and decorate show where each branch points.
KNOWLEDGE CHECK

Check your branch-pointer model

Follow refs and HEAD through commits, switches, detached work, and recovery.

01What is a local Git branch fundamentally?
02In the normal attached state, what does HEAD reference?
03What happens to the current branch after a new ordinary commit?
04Which command creates feature/search at the current commit and switches to it?
05What does detached HEAD mean?
06You made a wanted commit while detached. What is the clearest immediate recovery?
07Why can git branch -d refuse to delete a branch?
PREVIOUS · PROJECTGit Project: Messy Repository
NEXT LESSONGit Merge
ON THIS PAGEGit BranchBranches are names in a graphA branch is a movable refHEAD identifies your checkout contextA commit advances only the attached branchCreate and switch branches explicitlySwitch only when the working state can surviveCreate a branch from the right start pointRead branch divergence without switchingRename and delete refs safelyDetached HEAD is a valid inspection stateCommits can exist while HEAD is detachedRescue detached work immediatelyUnderstand the unborn initial branchGuided practice: draw and move refsIndependent lab: recover an unnamed experimentCommon branch and HEAD mistakesLesson reviewKnowledge checkRelated lessons
Course contents