在阅读Git命令的手册页时,你经常会看到一个可选的--(破折号)。根据我的经验,--是不必要的,也没有什么区别。你什么时候需要?既然它出现在这么多命令中,那么它通常意味着什么呢?
--
yqlxgs2m1#
git中的双破折号--对不同的命令有不同的含义,但一般来说,它将选项和参数分开。在git中,--的含义取决于你使用的是哪个子命令。它通常将子命令参数(如git checkout中的分支名称)与修订或文件名分开。有时它是完全可选的,仅用于防止不寻常的文件名被解释为程序选项。例如
git checkout
git checkout <commit>要将 checkout 细化到一两个文件,可以使用--将“树型”参数与您希望 checkout 的“文件名”分开。
git checkout <commit>
git commit
git add
git commit [-m消息]要忽略通过git add添加的任何内容并提交特定文件中的更改,请使用git commit -- <filename>
git commit -- <filename>
-
git add -- -sample.txt
git log
git log -- <filename>如果你需要了解git命令的具体含义,你需要查看手册页。
git log -- <filename>
rm5edbpk2#
这个问题要求对所有git命令中的双破折号有一个概念性的理解。双破折号表示选项的结束,被认为对Git来说是“不够的”。在Git 2.24(2019年第三季度)中,命令行解析器学习了“--end-of-options”表示法:脚本编写者的标准约定是先在命令行上硬编码一组选项,并强制命令将最终用户输入视为非选项,这是**使用“--”作为分隔符,但这不适用于使用“--”作为revs和pathspec之间分隔符的命令。参见commit 67feca3,commit 51b4594,commit 19e8789(2019年8月6日)by Jeff King ( peff )。(由Junio C Hamano -- gitster --合并至commit 4a12f89,2019年9月9日)
--end-of-options
peff
gitster
revision
目前还没有一种可靠的方法来告诉Git某个特定的选项是一个修订版本,而不是一个选项。所以如果你有一个分支“refs/heads/--foo”,你不能说:
refs/heads/--foo
git rev-list --foo
字符串你可以说:
git rev-list refs/heads/--foo
型但是如果您不知道refname,特别是如果您是一个从其他地方传递值的脚本,那么这种方法就行不通了。在大多数程序中,你可以使用“--“来结束选项解析,像这样:
some-prog -- "$revision"
型
但这对修订解析器不起作用,因为“--“已经有意义了:它将修订与路径规范分开。
因此,我们需要一些其他的标记来区分选项和修订。此修补程序引入了“--end-of-options”,用于此目的:
git rev-list --oneline --end-of-options "$revision"
型无论“$revision”中的内容是什么,它都将工作(如果你说“--“,它可能会失败,但它不会做一些危险的事情,比如触发一个意外的选项)。名字很冗长,但这可能是件好事;这意味着用于可读性比简洁更重要的脚本调用。一种替代方法是引入一个明确的选项来标记修订,例如:
git rev-list --oneline --revision="$revision"
型这比这次提交的信息要多一点(因为它甚至会让像“--”这样的愚蠢的东西变得毫不含糊)。但是在git和其他命令中,使用分隔符“--”的模式已经很好地建立起来了,它使一些脚本任务变得更简单,比如:
git rev-list --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-log
parse_options()
setup_revisions()
argv
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)"。参见commit 3a1f91c,commit 9033add,commit e05e2ae(2020年11月10日)by Jeff King ( peff )。(由Junio C Hamano -- gitster --合并到commit 0dd171f,2020年11月21日)
git rev-parse
git rev-parse --verify -q --end-of-options $rev
rev-parse
签收人:杰夫·金我们教rev-list一种新的方法来区分19e8789b23中的选项和修订版本(“revision:allow --end-of-options to end option paralysis”,2019-08-06,Git v2.24.0-rc 0--merge中列出的batch #2),但rev-parse使用自己的解析器。它应该知道--end-of-options,这不仅是为了一致性,而且因为它可能出现类似的模糊情况。例如,如果呼叫者这样做:
git rev-parse "$rev" -- "$path"
型如果$rev包含类似于选项的字符串,比如“--local-env-vars”,那么它就会被混淆。或者甚至是“--not-real“,我们会将其作为一个选项传递给rev-list。或者更重要的是:
$rev
--local-env-vars
--not-real
git rev-parse --verify "$rev"
型可能会被选项混淆,即使它的目的是安全地解析不受信任的输入。从好的方面来说,它总是会失败--verify部分,因为它不会解析修订版本,所以调用者通常会“失败关闭”,而不是继续使用不可信的字符串。但它仍然会触发“$rev“中的任何选项;这应该是无害的,因为rev-parse选项都是只读的,但我没有仔细审核所有路径。此修补程序允许调用者写入:
--verify
git rev-parse --end-of-options "$rev" -- "$path"
型以及:
git rev-parse --verify --end-of-options "$rev"
型这两者都将始终将“$rev”视为修订参数。后者有点笨重。如果我们定义了“--verify“,要求它的下一个参数是版本号,那就更好了。但我们历史上没有这样做,而且:
git rev-parse --verify -q "$rev"
型目前正在工作。我在这里加了一个测试来确认我们没有破坏它。一些实施说明:
我们不必重新缩进主要的选项解析块,因为我们可以将“我们看到选项的结尾了吗”检查与“它以破折号开始了吗”检查结合起来。例外的是预设置选项,它们需要自己的块。
但是,我们必须将“--”解析从“does it start with dash”块中提取出来,因为即使我们已经看到了--end-of-options,我们也要解析它。
我们将在输出中保留“--end-of-options“。这在技术上可能没有必要,因为谨慎的呼叫者会这样做:
git rev-parse --end-of-options $revs -- $paths并且$revs中的任何内容都将被解析为对象ID。但是,它确实可以帮助稍微不太小心的呼叫者,例如:
git rev-parse --end-of-options $revs_or_paths
其中路径“--foo”将保留在输出中,只要它也存在于磁盘上。在这种情况下,保留--end-of-options以沿着rev-list是有帮助的,否则它只会看到“--foo”。git rev-parse现在在其手册页中包括:请注意,如果您正在验证来自不受信任来源的名称,则明智的做法是使用--end-of-options,这样name参数就不会被误认为是另一个选项。
--foo
$ git rev-parse --verify --end-of-options $REV^{commit} $ git rev-parse --default master --verify --end-of-options $REV
在Git 2.31(2021年第一季度)中,“git mktag”(man)在写入标记对象之前使用自己的规则验证其输入-它已更新为与git fsck共享逻辑。这意味着它也支持--end-of-options。参见commit 06ce791(2021年1月6日),commit 2aa9425,commit 3f390a3,commit 9a1a3a4,commit acfc013,commit 1f3299f,commit acf9de4,commit 40ef015,commit dfe3948,commit 0c43911,commit 692654d,commit 30f882c,commit ca9a1ed,commit 47c95e7,commit 3b9e4dd,commit 5c2303e、commit 317c176、commit 0d35ccb、commit b5ca549、commit aba5377、commit 18430ed(2021年1月5日)和commit 9ce0fc3、commit f59b61d(2020年12月23日)。(由Junio C Hamano -- gitster --合并到commit c7d6d41,2021年1月25日)
git mktag
git fsck
mktag
签收人:埃瓦尔·阿恩菲约德·比亚尔马森将“mktag“命令转换为使用parse-options.h,而不是它自己的ad-hoc argc处理。这在实践中并不重要,因为它不支持任何选项,但它删除了代码库中的另一个特例,并使将来添加选项变得更容易。它确实稍微改善了那些想要以一致的方式执行git命令的程序的情况,例如。始终使用--end-of-options。例如:“gitaly“就是这样做的,并且有一个不支持--end-of-options的内置程序的黑名单。这是一个较少的特殊情况下,它和其他类似的程序支持。
parse-options.h
gitaly
2条答案
按热度按时间yqlxgs2m1#
git中的双破折号
--
对不同的命令有不同的含义,但一般来说,它将选项和参数分开。在git中,
--
的含义取决于你使用的是哪个子命令。它通常将子命令参数(如git checkout
中的分支名称)与修订或文件名分开。有时它是完全可选的,仅用于防止不寻常的文件名被解释为程序选项。例如
git checkout
。要检出一个“提交”(在手册中称为“树型”,因为您实际上可以指定一系列对象类型),您可以使用git checkout <commit>
要将 checkout 细化到一两个文件,可以使用
--
将“树型”参数与您希望 checkout 的“文件名”分开。git commit
。要提交“index”中的任何内容(即通过git add
暂存的内容),只需发出git commit
命令。git commit
[-m消息]要忽略通过
git add
添加的任何内容并提交特定文件中的更改,请使用git commit -- <filename>
git add
.要提交一个文件名以-
或--
开头的文件,必须告诉git add停止阅读参数,并开始读取文件名;--
就是这么做的。git add -- -sample.txt
git log
。要查看仅限于影响文件的提交的提交历史,请使用git log -- <filename>
如果你需要了解git命令的具体含义,你需要查看手册页。
rm5edbpk2#
这个问题要求对所有git命令中的双破折号有一个概念性的理解。
双破折号表示选项的结束,被认为对Git来说是“不够的”。
在Git 2.24(2019年第三季度)中,命令行解析器学习了“
--end-of-options
”表示法:脚本编写者的标准约定是先在命令行上硬编码一组选项,并强制命令将最终用户输入视为非选项,这是**使用“
--
”作为分隔符,但这不适用于使用“--
”作为revs和pathspec之间分隔符的命令。参见commit 67feca3,commit 51b4594,commit 19e8789(2019年8月6日)by Jeff King (
peff
)。(由Junio C Hamano --
gitster
--合并至commit 4a12f89,2019年9月9日)revision
:允许--end-of-options
结束选项解析目前还没有一种可靠的方法来告诉Git某个特定的选项是一个修订版本,而不是一个选项。
所以如果你有一个分支“
refs/heads/--foo
”,你不能说:字符串
你可以说:
型
但是如果您不知道refname,特别是如果您是一个从其他地方传递值的脚本,那么这种方法就行不通了。
在大多数程序中,你可以使用“
--
“来结束选项解析,像这样:型
但这对修订解析器不起作用,因为“
--
“已经有意义了:它将修订与路径规范分开。因此,我们需要一些其他的标记来区分选项和修订。
此修补程序引入了“
--end-of-options
”,用于此目的:型
无论“$revision”中的内容是什么,它都将工作(如果你说“
--
“,它可能会失败,但它不会做一些危险的事情,比如触发一个意外的选项)。名字很冗长,但这可能是件好事;这意味着用于可读性比简洁更重要的脚本调用。
一种替代方法是引入一个明确的选项来标记修订,例如:
型
这比这次提交的信息要多一点(因为它甚至会让像“--”这样的愚蠢的东西变得毫不含糊)。但是在git和其他命令中,使用分隔符“
--
”的模式已经很好地建立起来了,它使一些脚本任务变得更简单,比如:型
parse-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 2.30(2021年第一季度)中,“
git rev-parse
”(man)学习了“--end-of-options
”,以帮助脚本安全地获取一个应该是修订版的参数,例如:“git rev-parse --verify -q --end-of-options $rev
(man)"。参见commit 3a1f91c,commit 9033add,commit e05e2ae(2020年11月10日)by Jeff King (
peff
)。(由Junio C Hamano --
gitster
--合并到commit 0dd171f,2020年11月21日)rev-parse
:手柄--end-of-options
签收人:杰夫·金
我们教rev-list一种新的方法来区分19e8789b23中的选项和修订版本(“
revision
:allow --end-of-options to end option paralysis”,2019-08-06,Git v2.24.0-rc 0--merge中列出的batch #2),但rev-parse
使用自己的解析器。它应该知道
--end-of-options
,这不仅是为了一致性,而且因为它可能出现类似的模糊情况。例如,如果呼叫者这样做:型
如果
$rev
包含类似于选项的字符串,比如“--local-env-vars
”,那么它就会被混淆。或者甚至是“
--not-real
“,我们会将其作为一个选项传递给rev-list。或者更重要的是:
型
可能会被选项混淆,即使它的目的是安全地解析不受信任的输入。
从好的方面来说,它总是会失败
--verify
部分,因为它不会解析修订版本,所以调用者通常会“失败关闭”,而不是继续使用不可信的字符串。但它仍然会触发“
$rev
“中的任何选项;这应该是无害的,因为rev-parse选项都是只读的,但我没有仔细审核所有路径。此修补程序允许调用者写入:
型
以及:
型
这两者都将始终将“
$rev
”视为修订参数。后者有点笨重。如果我们定义了“
--verify
“,要求它的下一个参数是版本号,那就更好了。但我们历史上没有这样做,而且:
型
目前正在工作。我在这里加了一个测试来确认我们没有破坏它。
一些实施说明:
我们不必重新缩进主要的选项解析块,因为我们可以将“我们看到选项的结尾了吗”检查与“它以破折号开始了吗”检查结合起来。例外的是预设置选项,它们需要自己的块。
但是,我们必须将“
--
”解析从“does it start with dash”块中提取出来,因为即使我们已经看到了--end-of-options
,我们也要解析它。我们将在输出中保留“
--end-of-options
“。这在技术上可能没有必要,因为谨慎的呼叫者会这样做:git rev-parse --end-of-options $revs -- $paths
并且$revs中的任何内容都将被解析为对象ID。
但是,它确实可以帮助稍微不太小心的呼叫者,例如:
其中路径“
--foo
”将保留在输出中,只要它也存在于磁盘上。在这种情况下,保留
--end-of-options
以沿着rev-list是有帮助的,否则它只会看到“--foo
”。git rev-parse
现在在其手册页中包括:请注意,如果您正在验证来自不受信任来源的名称,则明智的做法是使用
--end-of-options
,这样name参数就不会被误认为是另一个选项。在Git 2.31(2021年第一季度)中,“
git mktag
”(man)在写入标记对象之前使用自己的规则验证其输入-它已更新为与git fsck
共享逻辑。这意味着它也支持
--end-of-options
。参见commit 06ce791(2021年1月6日),commit 2aa9425,commit 3f390a3,commit 9a1a3a4,commit acfc013,commit 1f3299f,commit acf9de4,commit 40ef015,commit dfe3948,commit 0c43911,commit 692654d,commit 30f882c,commit ca9a1ed,commit 47c95e7,commit 3b9e4dd,commit 5c2303e、commit 317c176、commit 0d35ccb、commit b5ca549、commit aba5377、commit 18430ed(2021年1月5日)和commit 9ce0fc3、commit f59b61d(2020年12月23日)。
(由Junio C Hamano --
gitster
--合并到commit c7d6d41,2021年1月25日)mktag
:转换为解析选项签收人:埃瓦尔·阿恩菲约德·比亚尔马森
将“
mktag
“命令转换为使用parse-options.h
,而不是它自己的ad-hoc argc处理。这在实践中并不重要,因为它不支持任何选项,但它删除了代码库中的另一个特例,并使将来添加选项变得更容易。
它确实稍微改善了那些想要以一致的方式执行git命令的程序的情况,例如。始终使用
--end-of-options
。例如:
“
gitaly
“就是这样做的,并且有一个不支持--end-of-options
的内置程序的黑名单。这是一个较少的特殊情况下,它和其他类似的程序支持。