Lesson 6 of 7 in Branching & Merging

HEAD and relative refs

Story: An agent always knows where they stand in time, and how to step back a moment or two. Juno will show you how.

HEAD is git's name for where you are. Most of the time it points at a branch, the one you're on, and through that branch at its newest commit. That's why a commit moves the branch you're on: git moves the branch HEAD points at.

Counting back: ~ and ^

You don't need commit ids to name older commits. Add ~ to any name for a commit to count back from it:

  • HEAD~1 is the commit before the one you're on: its parent.
  • HEAD~2 is the one before that, and main~3 is three commits before main's newest.
  • ^ means "the parent" too: HEAD^ is the same commit as HEAD~1.

A merge commit has two parents. The first is where the branch you were on was, and the second is where the branch you merged was. A number after ^ picks one: HEAD^1 is the first parent, and HEAD^2 the second. ~ always follows first parents.

They chain, read from left to right: HEAD~1^2 is the second parent of the commit before HEAD.

These names work wherever git takes a commit: git log main~1, git show HEAD~2, git branch old main~3, and git switch -c fix HEAD~1, which starts a new branch at that commit.

Looking around: a detached HEAD

To see your files as they were in an older commit, move HEAD there with git switch --detach:

$ git switch --detach HEAD~2
HEAD is now at 37d7cf7 Add a README
$ git status
HEAD detached at 37d7cf7
nothing to commit, working tree clean

HEAD now points straight at a commit instead of a branch: a detached HEAD. Your files are as they were in that commit, and no branch has moved. git switch main takes you back.

switch expects a branch, so plain git switch HEAD~2 refuses, with a hint to add --detach. Saying --detach makes it clear you mean to leave every branch.

Commits on a detached HEAD

You can commit on a detached HEAD, and HEAD moves to the new commit. But no branch moves with it, so the commit is on no branch. git status then says HEAD detached from the commit you started at. When you switch away, git warns you that you're leaving the commit behind:

$ git switch main
Warning: you are leaving 1 commit behind, not connected to
any of your branches:

  804c28a Try a purple heading

If you want to keep it by creating a new branch, this may be a good time
to do so with:

 git branch <new-branch-name> 804c28a

Switched to branch 'main'

The commit isn't deleted, but no branch leads to it any more, and the Live Graph shows it faded. To keep commits you made on a detached HEAD, give them a branch before you leave: git switch -c <name> makes one right there and switches to it, and git branch <name> makes one without switching.

Command What it does
HEAD~<n> The commit n commits before HEAD, following first parents. It works after any name for a commit: main~2.
HEAD^, HEAD^2 The first parent of HEAD, and the second parent of a merge commit.
git switch --detach <commit> Moves HEAD to a commit without a branch: a detached HEAD. -d is short for it.
git switch -c <name> <commit> Starts a new branch at that commit and switches to it. Without a commit, it starts where you are, which keeps the commits you made on a detached HEAD.

New commands

  • git switch --detach

Explainer: Naming commits by counting back

project: your repo, you are here37d7cf7 Add a README37d7cf7ab89288 Add the home pageab89288a4b8d97 Style the headinga4b8d972328a9e Start a list of ideas2328a9ebd5f84a Merge branch 'ideas'bd5f84aHEAD → mainideas
The repository at the end of the Explainer.
Graph as text

project: your repo, you are here

  • HEAD → main at bd5f84a "Merge branch 'ideas'"

Branches and tags

  • ideas at 2328a9e "Start a list of ideas"
  • main at bd5f84a "Merge branch 'ideas'"

Commits, newest first

  1. bd5f84a "Merge branch 'ideas'"; parents a4b8d97 and 2328a9e; refs: HEAD → main
  2. 2328a9e "Start a list of ideas"; parent 37d7cf7; refs: ideas
  3. a4b8d97 "Style the heading"; parent ab89288
  4. ab89288 "Add the home page"; parent 37d7cf7
  5. 37d7cf7 "Add a README"; no parent

Challenge 1 of 3

Story: Step back two moments in this timeline, Agent, and just look. Touch nothing.

Look at the project as it was two commits before the one you're on. Move HEAD there with a detached HEAD, without making a branch. You're on main.

Unlocks after Basics.

Terminal

Unlocks after Basics.

This Lesson can be played once Basics is complete. Its text and Explainer are open to everyone.