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