Course outline

Git and GitHub / Basic: the local Git model / Lesson 4

Branches, HEAD, and safe switching

Use branch references to separate work and understand what happens to files and commits when the current reference changes.

About 5 min readContent reviewed
On this page

Lesson goals

  • Explain branch creation and detached HEAD.
  • Protect uncommitted work before switching contexts.

A branch is a movable reference

Creating a branch adds a name pointing to a commit; it does not create a separate physical copy of every file. When HEAD symbolically refers to that branch, a new commit advances the branch to the new object. Other branch references remain where they were. The working tree displays one selected snapshot plus local changes, so branch names are not folders containing independent unsaved edits. This distinction explains why an uncommitted modification may remain visible after a permitted switch: the edit belongs to the working tree rather than being permanently assigned to the old branch.

Create a named line of work

In a clean temporary repository with an initial main commit, git switch -c creates a branch at the current commit and checks it out. The branch name should describe a coherent task rather than encode a claim that the work is already approved. After a lab commit on the topic, main still points to the original commit. Inspect names and ancestry instead of guessing from the files currently displayed. The commands below use a synthetic branch and remain local. No hosted branch, pull request, or remote update is created by this operation.

bash Create and advance a temporary topic branch
git switch -c feature/title
printf 'A better title\n' > title.txt
git add -- title.txt
git -c user.name="Lab Author" -c user.email="lab@example.invalid" commit -m "Add title"
git branch --show-current

Requires a clean initialized lab with an existing main commit. The last command prints feature/title. main does not gain the Add title commit until an explicit integration operation occurs. Commit identifiers and summary formatting are generated by Git.

Understand when switching is refused

Git normally refuses a switch that would overwrite conflicting local modifications or untracked paths. This protection is contextual, not a promise that all work is automatically stored. Inspect status first, then commit a coherent change, use an intentional stash, or move work to a separate worktree as appropriate. Do not respond to a refusal with a force option merely to continue a tutorial. A clean index and working tree simplify reasoning, especially before merges or rebases. Preserve the exact file content you care about before using any command that discards or replaces it.

Name experimental commits before leaving them

Checking out a commit directly can detach HEAD, meaning HEAD points to a commit rather than a branch name. New commits are still valid objects, but no ordinary branch automatically keeps their tip reachable after you switch away. Create a branch at the experiment when it should be retained. The example reads a previous snapshot and then creates a named branch from that position. It does not reset main or rewrite its history. The special state is useful for inspection and testing, provided you understand where new work will be referenced.

bash Turn a detached inspection point into a named experiment
git switch --detach HEAD~1
git switch -c experiment/old-title
git branch --show-current

Run in a lab with at least two first-parent commits and a clean working tree. The final name is experiment/old-title. The original branch reference remains unchanged; only the current checkout and newly created reference differ.

Manage names without confusing them with data deletion

Renaming or deleting a local branch changes references, not every object immediately. Reachability, reflogs, and later object maintenance determine whether unreferenced commits remain recoverable. Gitโ€™s safe deletion checks can help, but they do not replace knowing whether work is integrated into the intended destination or preserved elsewhere. A hosted branch has a separate lifecycle and permissions. Use branch cleanup as a deliberate collaboration step after verifying integration, tests, and any release references. Keep important recovery anchors before reorganizing experiments, and avoid forced deletion as a routine shortcut.

Common errors and fixes

Uncommitted edits appear on another branch

Why it happens
The edit lived in the working tree, not in a commit.
How to fix it
Inspect state and deliberately assign the work through a commit or stash.
Prevent it next time
Check status before switching tasks.

Experimental commits seem lost after switching

Why it happens
Work was created with detached HEAD and no branch anchor.
How to fix it
Inspect the local reflog and create a recovery branch at the verified commit.
Prevent it next time
Name experiments before leaving them.

A switch refuses to overwrite a file

Why it happens
Local work conflicts with the destination snapshot.
How to fix it
Preserve the work and choose a suitable save or integration path.
Prevent it next time
Avoid force options as a default response.

Check your understanding

1. A topic receives two commits. Does main advance too?

Show worked solution

No. Only the checked-out branch is advanced by ordinary commits. main remains at its existing reference until explicitly updated. Inspect the graph and branch refs to verify the relationship before merging.

2. You inspect a release commit detached and then want to keep a fix. What is the safe next step?

Show worked solution

Create a named topic branch from the intended point before continuing work, then follow the projectโ€™s supported maintenance and review workflow. Do not assume committing in detached state automatically creates a branch or publishes the fix.

Key takeaways

  • Branches name commits; uncommitted edits belong to working state.
  • Detached HEAD is useful when its reference lifetime is understood.
  • Preserve work before switching or deleting names.

Official references