Git/
Lesson

You have used git checkout to switch branches. But this command is far more powerful than a branch switcher. It is your tool for viewing the past, recovering deleted files, and retrieving specific versions of files from any point in history.

Understanding checkout's full capabilities means you can recover from almost any mistake. Accidentally deleted a file? Checkout brings it back. Need to see how the code looked last week? Checkout takes you there. Want to grab just one file from another branch? Checkout does that too.

AI tools often suggest git checkout . or git checkout -- . to "clean up" your working directory. This permanently discards all uncommitted changes in every file. It is the file-level equivalent of git reset --hard and just as dangerous if you have unsaved work.

Restoring files to previous versions

Restore to the last commitWhat is commit?A permanent snapshot of your staged changes saved in Git's history, identified by a unique hash and accompanied by a message describing what changed.

You made changes to a file but want to discard them entirely:

# Discard local changes to app.js
git checkout -- app.js

# Modern equivalent (more explicit)
git restore app.js

This permanently overwrites your local modifications. The file reverts to exactly how it was at the last commit.

Restore to a specific commit

You want a file as it existed several commits ago:

# Get app.js as it was in commit abc1234
git checkout abc1234 -- app.js

# Git stages the restored version automatically
git status
# Changes to be committed:
#   modified: app.js

# Commit the restoration
git commit -m "revert: restore app.js to stable version"

This does not move you to that commit. You stay on your current branch. Only that specific file changes.

Restore multiple files or directories

# Restore an entire directory
git checkout abc1234 -- src/components/

# Restore multiple specific files
git checkout HEAD -- package.json package-lock.json

# Restore all files (dangerous, discards all changes)
git checkout abc1234 -- .
When you restore a file from a specific commit, Git automatically stages it. If you do not want it staged, unstage it with git restore --staged file.
02

Detached HEADWhat is detached head?A Git state where you're viewing a specific commit directly instead of being on a branch, meaning any new commits will be orphaned when you switch away. state

Checking out a commitWhat is commit?A permanent snapshot of your staged changes saved in Git's history, identified by a unique hash and accompanied by a message describing what changed. directly (instead of a branch) puts you in "detached HEAD" state:

git checkout abc1234

Git warns you:

You are in 'detached HEAD' state. You can look around, make
experimental changes and commit them, and you can discard any
commits you make in this state without impacting any branches.

What you can do in detached HEAD:

  • View the code as it was at that commit
  • Run tests, build the project
  • Look around to understand what changed

What you should not do:

  • Make commits (they will be orphaned and eventually garbage collected)

Getting back:

git checkout main

Creating a branch from an old commit

If you want to actually work from a historical point, create a branch:

# Create a new branch starting from an old commit
git checkout -b hotfix-v1 abc1234

Now you are on a proper branch and can commit safely.

03

Recovering a deleted file

# You accidentally deleted config.js
git status
# D config.js

# Restore it from the last commit
git checkout HEAD -- config.js

# If you already committed the deletion, go back further
git log --oneline -- config.js
# e4f5g6h Delete config
# a1b2c3d Update config

# Restore from the commit before deletion
git checkout a1b2c3d -- config.js
04

Checkout vs restore vs switch vs reset

Modern Git splits the overloaded checkout command into specialized tools:

TaskOld commandModern command
Switch branchesgit checkout branchgit switch branch
Create and switchgit checkout -b branchgit switch -c branch
Restore a filegit checkout -- filegit restore file
Unstage a filegit reset HEAD filegit restore --staged file
Restore from specific commitgit checkout commit -- filegit restore --source=commit file

Both the old and modern commands work. The modern versions are clearer about intent, which reduces the chance of accidentally doing the wrong thing.

05

Practical workflows

Code archaeology: finding when a bug appeared

# Go back 10 commits and test
git checkout HEAD~10
# Run tests... bug not present

# Go back 5 commits
git checkout HEAD~5
# Bug present! Narrow down further

# Return to main when done
git checkout main

Cherry-picking a file from another branch

# Grab one file from another branch without merging
git checkout feature-branch -- src/utils/helpers.js
git commit -m "feat: add helper functions from feature-branch"
06

Quick reference

CommandPurpose
git checkout -- fileRestore file to last commit (destructive)
git checkout commit -- fileRestore file to specific commit
git checkout commitView old commit (detached HEAD)
git checkout -b branch commitCreate branch from old commit
git restore fileModern: restore file to last commit
git switch branchModern: switch branches