--
的含义取决于你使用它的子命令。它通常用于将子命令的参数(例如git checkout
中的分支名称)与修订版本或文件名分隔开来。有时它是可选的,仅用于防止将不寻常的文件名解释为程序选项。git checkout
。要检出一个“提交”(在手册中称为“树状物”,因为您实际上可以指定一系列对象类型),您可以使用
git checkout <commit>
要将检出精确到一个或两个文件,请使用--
将“树状物”参数与要检出的“文件名”分隔开。
git commit
。要提交“索引”中的内容(即,通过git add
暂存的内容),只需执行git commit
命令。
git commit
[-m message]
要忽略通过git add
添加的内容,并提交特定文件中的更改,请使用git commit -- <filename>
git add
。要提交以-
或--
开头的文件名,您必须告诉git add停止读取参数,并开始读取文件名;--
就是这样做的。
git add -- -sample.txt
git log
。要查看仅限于影响某个文件的提交历史,请使用
git log -- <filename>
查看提交 67feca3, 提交 51b4594, 提交 19e8789 (2019年8月6日)由Jeff King (peff
)完成。
(由Junio C Hamano -- gitster
合并于提交 4a12f89, 2019年9月9日)
修订版
: 允许 --end-of-options
结束选项解析There's currently no robust way to tell Git that a particular option is meant to be a revision, and not an option.
So if you have a branch "refs/heads/--foo
", you cannot just say:git rev-list --foo
You can say:
git rev-list refs/heads/--foo
But that breaks down if you don't know the refname, and in particular if you're a script passing along a value from elsewhere.
In most programs, you can use "--
" to end option parsing, like this:
some-prog -- "$revision"
But that doesn't work for the revision parser, because "
--
" is already meaningful there: it separates revisions from pathspecs.
So we need some other marker to separate options from revisions.This patch introduces "
--end-of-options
", which serves that purpose:git rev-list --oneline --end-of-options "$revision"
will work regardless of what's in "$revision" (well, if you say "
--
" it may fail, but it won't do something dangerous, like triggering an unexpected option).The name is verbose, but that's probably a good thing; this is meant to be used for scripted invocations where readability is more important than terseness.
One alternative would be to introduce an explicit option to mark a revision, like:
git rev-list --oneline --revision="$revision"
That's slightly more informative than this commit (because it makes even something silly like "--" unambiguous). But the pattern of using a separator like "
--
" is well established in git and in other commands, and it makes some scripting tasks simpler like:git rev-list --end-of-options "$@"
解析选项: 允许使用
--end-of-options
作为"--"的同义词
最近的修订选项解析器学会了使用
--end-of-options
,但这对于所有调用者来说还不够。
其中一些调用者,例如git-log
,使用parse_options()
挑选出一些选项,然后将其余部分传递给setup_revisions()
。
对于这些情况,我们需要停止parse_options()
在看到--end-of-options
时找到更多选项,并保留该选项在argv
中,以便setup_revisions()
也可以看到它。让我们像处理"
--
"一样处理它。我们甚至可以利用PARSE_OPT_KEEP_DASHDASH
的处理方式,因为任何想要保留一个的调用者也会想要保留另一个。
示例:
git update-ref refs/heads/--source HEAD &&\
git log --end-of-options --source
随着Git 2.30(2021年第一季度)的到来, "git rev-parse
"(man) 学会了 "--end-of-options
",以帮助脚本安全地获取参数,这些参数应该是一个修订版本,例如 "git rev-parse --verify -q --end-of-options $rev
(man)"。
查看 提交3a1f91c, 提交9033add, 提交e05e2ae (2020年11月10日) 由 Jeff King (peff
).
(合并自Junio C Hamano -- gitster
-- 在 提交0dd171f, 2020年11月21日)
rev-parse
: 处理--end-of-options
签名:Jeff King
We taught rev-list a new way to separate options from revisions in 19e8789b23 ("
revision
: allow --end-of-options to end option parsing", 2019-08-06, Git v2.24.0-rc0 -- merge listed in batch #2), butrev-parse
uses its own parser.
It should know about--end-of-options
not only for consistency, but because it may be presented with similarly ambiguous cases. E.g., if a caller does:git rev-parse "$rev" -- "$path"
to parse an untrusted input, then it will get confused if
$rev
contains an option-like string like "--local-env-vars
".
Or even "--not-real
", which we'd keep as an option to pass along to rev-list.Or even more importantly:
git rev-parse --verify "$rev"
can be confused by options, even though its purpose is safely parsing untrusted input.
On the plus side, it will always fail the--verify
part, as it will not have parsed a revision, so the caller will generally "fail closed" rather than continue to use the untrusted string.
But it will still trigger whatever option was in "$rev
"; this should be mostly harmless, since rev-parse options are all read-only, but I didn't carefully audit all paths.This patch lets callers write:
git rev-parse --end-of-options "$rev" -- "$path"
and:
git rev-parse --verify --end-of-options "$rev"
which will both treat "
$rev
" always as a revision parameter.
The latter is a bit clunky. It would be nicer if we had defined "--verify
" to require that its next argument be the revision.
But we have not historically done so, and:git rev-parse --verify -q "$rev"
does currently work. I added a test here to confirm that we didn't break that.
A few implementation notes:
We don't have to re-indent the main option-parsing block, because we can combine our "did we see end of options" check with "does it start with a dash". The exception is the pre-setup options, which need their own block.
We do however have to pull the "
--
" parsing out of the "does it start with dash" block, because we want to parse it even if we've seen--end-of-options
.We'll leave "
--end-of-options
" in the output. This is probably not technically necessary, as a careful caller will do:git rev-parse --end-of-options $revs -- $paths
and anything in $revs will be resolved to an object id.
However, it does help a slightly less careful caller like:git rev-parse --end-of-options $revs_or_paths
where a path "
--foo
" will remain in the output as long as it also exists on disk.
In that case, it's helpful to retain--end-of-options
to get passed along to rev-list, as it would otherwise see just "--foo
".
git rev-parse
现在在其手册页中包含了:
Note that if you are verifying a name from an untrusted source, it is wise to use
--end-of-options
so that the name argument is not mistaken for another option.$ git rev-parse --verify --end-of-options $REV^{commit} $ git rev-parse --default master --verify --end-of-options $REV
git mktag
"(man) 在写入标签对象之前会使用自己的规则验证其输入 - 它已更新为与git fsck
共享逻辑。这意味着它也支持--end-of-options
。avar
)提交。(由Junio C Hamano -- gitster
--在commit c7d6d41中合并,2021年1月25日)
将“
mktag
: 转换为解析选项Signed-off-by: Ævar Arnfjörð Bjarmason
mktag
”命令转换为使用parse-options.h
而不是自己的特定参数处理方式。这在实践中并不重要,因为它不支持任何选项,但可以消除代码库中的另一个特例,并使将来向其中添加选项更加容易。对于希望以一致的方式执行git命令并始终使用--end-of-options
的程序,情况稍微有所改善。例如,“gitaly
”就是这样做的,并且有一个内置黑名单,不支持--end-of-options
。这是它和其他类似程序需要支持的一个特例。--foo
用作分支、标签或文件名”。但是能够编写能够安全处理这样的仓库的强健脚本还是很不错的。 - ojdo
git checkout
命令。 - Eric