2.4 Branches, HEAD, and the Default Branch
Key Takeaways
- A Git branch is a line of development; its tip is the latest commit on that line, and creating a branch is cheap (a movable pointer to a commit).
- HEAD is the pointer to the current branch (or a detached commit if you check out a SHA that is not a branch tip).
- GitHub has used main as the default branch name for new repositories since October 2020; the name is configurable, and existing repositories may still use master or another name.
- Merge combines two lines and can create a merge commit that preserves both histories; rebase replays commits onto a new base and rewrites SHAs, so you do not rebase branches other people already use.
- GitHub Flow depends on short-lived branches: create a branch from the default branch, commit, open a pull request, merge, then delete the feature branch.
A branch is a line of development. Git's glossary is precise: the most recent commit on a branch is the tip; that tip is referenced by a branch head, which moves forward as you commit. A repository can track many branches, but your working tree is associated with just one at a time — the current or checked-out branch. HEAD is the pointer to that current branch (or, in a special case, directly to a commit).
This is the second half of GH-900's compound Domain 1 bullet on repositories, commits, and branches. You cannot explain GitHub Flow, pull requests, or protected branches until you can explain a branch.
Why branches exist
GitHub Docs: branches let you develop features, fix bugs, or experiment in a contained area of the repository. You always create a branch from an existing branch, typically the default branch. Work on the new branch does not change the default branch until you merge (usually through a pull request).
A branch you create to build a feature is a feature branch or topic branch. GitHub flow guidance: use a short, descriptive name (increase-test-timeout, add-code-of-conduct) and a separate branch for each set of unrelated changes. That isolation is what makes review, revert, and CI tractable.
Creating a Git branch is cheap: Git writes a small ref (a name that points at a commit SHA). It does not copy the whole project. That is why teams create many short-lived branches instead of long-lived "dev copies" of the repo.
HEAD versus a branch head
Two similar words:
- A head (lowercase in Git's glossary) is a named ref at
refs/heads/<name>pointing at the tip commit of a branch (main,fix-timeout). - HEAD (uppercase) is the current branch. Your working tree is normally derived from the tree HEAD refers to. HEAD is a symbolic ref: it usually contains
ref: refs/heads/main, not a raw SHA.
When you git switch feature-a (or git checkout feature-a), HEAD now points at feature-a. New commits advance feature-a's tip and move HEAD with it.
Detached HEAD means you checked out a commit that is not the tip of a branch (for example git checkout a1b2c3d to inspect history). New commits would not belong to any branch name unless you create one. GH-900 depth: know that detached HEAD is "not on a branch," which is why Git warns you. Day-to-day GitHub Flow stays on named branches.
| Pointer | What it names | Moves when you commit? |
|---|---|---|
Branch (main, feature-a) | Tip commit of that line | Yes, if that branch is checked out |
| HEAD | The current branch (or a detached commit) | Yes; it follows the current branch |
| Tag | A (usually) fixed commit, often a release | No, not by git commit |
The default branch, and why it is often main
When you create a repository with content on GitHub, GitHub creates it with a single branch. That first branch is the default branch. GitHub Docs: the default branch is what GitHub displays when anyone visits the repository; it is the branch Git checks out locally on clone; and unless you specify otherwise, it is the base branch for new pull requests and code commits.
By default, GitHub names the default branch main in any new repository. GitHub switched new repositories from master to main in 2020 (announced 1 October 2020). The name is configurable:
- Per repository: Settings → Default branch (requires admin; the repo must already have more than one branch to change which branch is default).
- Per user or organization: default name for new repositories.
- Enterprises can enforce a default-branch-name policy.
GH-900 traps:
- The default branch is not required to be named
main. Older repos, mirrors, and teams that opted out may still usemaster,trunk, ordevelop. - Git's own historical default when you
git initlocally wasmaster; GitHub.com's default for new hosted repos ismain. Do not claim Git itself renamed every repo in 2020. - Existing repositories were not bulk-renamed. Renaming
mastertomainis a separate, explicit operation (and it updates pull request targets and some links). - "Default branch" is a role, not a magic name. Branch protection, GitHub Pages, and Actions
on: pushto the production line usually target that role.
Merge versus rebase (GH-900 conceptual depth)
You eventually combine a feature branch with the default branch. Two strategies:
| Merge | Rebase | |
|---|---|---|
| What it does | Combines two lines. If histories diverged, Git creates a merge commit with two parents. If the feature branch is a fast-forward, Git may just move the pointer. | Replays your commits onto a new base, producing new commits with new SHAs. |
| History shape | Preserves the exact parallel work (a join in the graph). | Linear history along the new base. |
| SHA stability | Existing feature commits keep their SHAs (non-rebase merge). | Feature commits are rewritten. |
| Shared branches | Safe default for integrating through a pull request. | Do not rebase a branch other people already based work on. |
GitHub pull requests typically merge (merge commit, squash merge, or rebase-and-merge are GitHub options — the last two are rewrites of the PR's commits onto the base). For GH-900, remember: merge keeps both histories; rebase rewrites. Rebase is a cleanup tool for your unshared branch, not a way to "fix" main.
A fast-forward is a merge where the target has no unique commits: Git just moves the branch pointer. No merge commit is created. git pull is fetch plus merge (unless you configure pull to rebase).
Why branches enable GitHub Flow
GitHub Flow is a lightweight, branch-based workflow. GitHub uses it for code, docs, and even site policy. The loop is:
- Create a branch from the default branch (a safe workspace).
- Commit on that branch until the change is ready.
- Open a pull request to propose the branch for review (GitHub, not Git).
- Address review; checks run against the branch's commits.
- Merge into the default branch.
- Delete the feature branch. History remains in the pull request and in
main.
Without cheap branches, that loop cannot exist: you would commit straight to main (unsafe) or copy the whole project (slow). Branch protection then enforces that main only moves through pull requests.
GitHub Flow is not Git Flow (the heavier model with long-lived develop, release/*, and hotfix/* branches). GH-900 names GitHub Flow. If a stem mentions develop and release as required, that is the other model.
Scenario: shipping a timeout fix
The default branch is main. You git switch -c increase-test-timeout from main. HEAD now points at increase-test-timeout. Commits stay off main. You push the branch and open a pull request. Reviewers comment; you add commits; the PR updates. After approval, you merge to main and delete increase-test-timeout. main is the default branch; HEAD on your laptop should switch back to main and pull. That entire story is why GH-900 treats branches, HEAD, and the default branch as one skill.
In Git, what does HEAD represent while you are working on a named feature branch?
Which statement about GitHub's default branch is accurate for GH-900?
A teammate wants a linear history on their unshared feature branch before opening a pull request. Another teammate wants to integrate a reviewed feature into main without rewriting commits other people already pulled. Which pair matches merge versus rebase at GH-900 depth?