This manual describes the convention used throughout Git CLI.
Many commands take revisions (most often "commits", but
sometimes "tree-ish", depending on the context and command) and
paths as their arguments. Here are the rules:
•Options come first and then args. A subcommand
may take dashed options (which may take their own arguments, e.g.
"--max-parents 2") and arguments. You SHOULD give dashed options
first and then arguments. Some commands may accept dashed options after you
have already given non-option arguments (which may make the command
ambiguous), but you should not rely on it (because eventually we may find a
way to fix these ambiguities by enforcing the "options then args"
rule).
•Revisions come first and then paths. E.g. in
git diff v1.0 v2.0 arch/x86 include/asm-x86, v1.0 and
v2.0 are revisions and arch/x86 and include/asm-x86 are
paths.
•When an argument can be misunderstood as either a
revision or a path, they can be disambiguated by placing -- between
them. E.g. git diff -- HEAD is, "I have a file called HEAD in my
work tree. Please show changes between the version I staged in the index and
what I have in the work tree for that file", not "show the
difference between the HEAD commit and the work tree as a whole". You can
say git diff HEAD -- to ask for the latter.
•Without disambiguating --, Git makes a
reasonable guess, but errors out and asks you to disambiguate when ambiguous.
E.g. if you have a file called HEAD in your work tree, git diff HEAD is
ambiguous, and you have to say either git diff HEAD -- or git diff
-- HEAD to disambiguate.
•Because
-- disambiguates revisions and
paths in some commands, it cannot be used for those commands to separate
options and revisions. You can use
--end-of-options for this (it also
works for commands that do not distinguish between revisions in paths, in
which case it is simply an alias for
--).
When writing a script that is expected to handle random
user-input, it is a good practice to make it explicit which arguments are
which by placing disambiguating -- at appropriate places.
•Many commands allow wildcards in paths, but you
need to protect them from getting globbed by the shell. These two mean
different things:
$ git restore *.c
$ git restore \*.c
The former lets your shell expand the fileglob, and you are asking
the dot-C files in your working tree to be overwritten with the version in
the index. The latter passes the *.c to Git, and you are asking the
paths in the index that match the pattern to be checked out to your working
tree. After running git add hello.c; rm hello.c, you will not
see hello.c in your working tree with the former, but with the latter
you will.
•Just as the filesystem . (period) refers
to the current directory, using a . as a repository name in Git (a
dot-repository) is a relative path and means your current repository.
Here are the rules regarding the "flags" that you should
follow when you are scripting Git:
•Splitting short options to separate words (prefer
git foo -a -b to git foo -ab, the latter may not even
work).
•When a command-line option takes an argument, use
the stuck form. In other words, write git foo -oArg instead of
git foo -o Arg for short options, and git foo --long-opt=Arg
instead of git foo --long-opt Arg for long options. An option that
takes optional option-argument must be written in the stuck form.
•When you give a revision parameter to a command,
make sure the parameter is not ambiguous with a name of a file in the work
tree. E.g. do not write git log -1 HEAD but write git log -1 HEAD
--; the former will not work if you happen to have a file called
HEAD in the work tree.
•Many commands allow a long option --option
to be abbreviated only to their unique prefix (e.g. if there is no other
option whose name begins with opt, you may be able to spell
--opt to invoke the --option flag), but you should fully spell
them out when writing your scripts; later versions of Git may introduce a new
option whose name shares the same prefix, e.g. --optimize, to make a
short prefix that used to be unique no longer unique.