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:
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:
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:
Git may interpret docs as a branch checkout rather than a path checkout.
This version is unambiguous:
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:
This means:
- take
README.mdfromHEAD~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:
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' - '
checkoutdetermines 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 switchfor changing branches' - '
git restorefor restoring files'
For example:
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:
After the checkout, the working tree version of config.yml matches the index again.
If instead you wanted the file from another commit:
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 -- filemeans restore the file path, not switch branches.' - '
git checkout rev -- filecopies 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 switchandgit restoreare usually clearer replacements.

