Git
Version Control
Command Line
Software Development
Git Checkout

Meaning of Git checkout double dashes

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

In Git commands, -- usually means "stop parsing options here." With git checkout, it also helps Git distinguish branch or commit names from file paths. That matters because checkout historically does more than one job, and the separator makes your intent explicit.

-- as a Separator

At the command-line level, -- marks the end of options. After that point, later arguments are treated as positional values rather than command flags.

In the specific case of git checkout, the separator is especially useful because the command can mean:

  • switch to another branch
  • check out a specific commit
  • restore one or more paths

Without a separator, Git has to guess whether a token is a revision name or a path. -- removes the ambiguity.

The Classic File-Restore Form

This pattern:

bash
git checkout -- README.md

means "check out the path README.md from the index into the working tree." In practical terms, it discards local unstaged changes to that file and restores the version Git currently has staged for HEAD.

That is why people often use it as a "revert my working copy of this file" command.

The modern equivalent is usually:

bash
git restore README.md

But older codebases and tutorials still use git checkout --.

Why the Separator Is Needed

Suppose your repository contains both:

  • a branch named docs
  • a file named docs

Then this command is ambiguous:

bash
git checkout docs

Git may interpret docs as a branch checkout rather than a path checkout.

This version is unambiguous:

bash
git checkout -- docs

Now Git knows docs is a pathspec, not a branch name.

Checking Out Paths from Another Revision

You can also combine a revision with a path:

bash
git checkout HEAD~1 -- README.md

This means:

  • take README.md from HEAD~1
  • write that version into the index and working tree

Again, the -- separates the revision expression from the file path. Without it, Git would have a harder time knowing where the revision argument stops and the path list begins.

The modern equivalent is:

bash
git restore --source=HEAD~1 README.md

It Does Not Mean "Delete Everything After This"

A common misconception is that -- is some kind of destructive operator. It is not. It is just a parser boundary.

The dangerous part of commands like git checkout -- file comes from what checkout does to the file, not from the separator itself. If you tell Git to restore a path, your uncommitted changes in that path can be overwritten.

So the mental model should be:

  • '-- tells Git how to read the command'
  • 'checkout determines the actual behavior'

checkout Is Historically Overloaded

Part of the confusion comes from the fact that git checkout used to serve several purposes under one verb. Newer Git versions split that intent into:

  • 'git switch for changing branches'
  • 'git restore for restoring files'

For example:

bash
git switch feature/login
git restore src/app.py

These commands are easier to read because they make the target action explicit. But you still need to understand git checkout -- because it appears in many existing docs, scripts, and team habits.

A Concrete Example

Suppose you edited config.yml locally and want to discard those edits:

bash
git status
git checkout -- config.yml
git status

After the checkout, the working tree version of config.yml matches the index again.

If instead you wanted the file from another commit:

bash
git checkout main -- config.yml

That copies config.yml from main into your current working tree and index. It does not switch your current branch to main.

That distinction is important. git checkout main switches branches. git checkout main -- config.yml copies one file from main.

Common Pitfalls

The biggest mistake is assuming git checkout -- file switches to a branch named file. It does not. The separator forces Git to treat the argument as a path.

Another issue is using git checkout -- file without realizing it discards local unstaged changes to that file. This can feel surprising if you only thought about the parser syntax and not the file-restore behavior.

Developers also sometimes confuse git checkout branch -- file with a branch switch. That form copies a path from the named revision; it does not move HEAD to that branch.

Finally, on modern Git, reach for git switch and git restore in new documentation when clarity matters. They express the intent better than overloaded checkout syntax.

Summary

  • In git checkout, -- separates revisions or options from file paths.
  • 'git checkout -- file means restore the file path, not switch branches.'
  • 'git checkout rev -- file copies the file from a specific revision without changing branches.'
  • The separator itself is not dangerous, but the restore action can overwrite local changes.
  • In newer Git workflows, git switch and git restore are usually clearer replacements.

Course illustration
Course illustration

All Rights Reserved.