[英]Git - why are double dashes needed when running a command on a deleted file?
Consider a git repository, where a file was once deleted. 考虑一个git存储库,其中一个文件曾被删除。
git rm path/to/file
git commit -a -m"testing"
Ok, now I want to see the git log
for the file, but I receive the classic error message: 好的,现在我想看到该文件的
git log
,但是我收到了经典的错误消息:
git log path/to/file
fatal: ambiguous argument 'path/to/file': unknown revision or path not in the working tree.
Use '--' to separate paths from revisions
The solution is simple - add --
: 解决方案很简单 - 添加
--
:
git log -- path/to/file
But... why? 但为什么? Why is this needed?
为什么需要这个? What is the rationale here?
这里的理由是什么? Can't git do an educated guess, that this might have been a file once?
不能git做一个有根据的猜测,这可能是一个文件一次? I understand the "ambiguity" problem - but there never was a tag by that name.
我理解“模棱两可”的问题 - 但从来没有这个名称的标签。 If the file was once deleted, and no tag is present, then choosing "the file interpretation" is always the good choice.
如果文件一旦删除,并且没有标记,那么选择“文件解释”始终是一个不错的选择。
On the other hand, it's possible to have a tag named the same as a file, which git log
handles pretty well: 另一方面,可以有一个名为与文件相同的标记,
git log
处理得非常好:
fatal: ambiguous argument 'path/to/file': both revision and filename
Use '--' to separate filenames from revisions
This behavior seems inconsistent. 这种行为似乎不一致。 Could anyone explain what the developers of git had in mind?
任何人都可以解释一下git的开发人员的想法吗?
git log
could be used on files as well as on branches, tags and so on. git log
可用于文件以及分支,标签等。
Assume you have a folder called a/b/c
, you'll get the commits for this folder using 假设您有一个名为
a/b/c
的文件夹,您将获得此文件夹的提交
git log a/b/c
That's fine. 没关系。
You could also have a branch called d/e/f
. 你也可以有一个名为
d/e/f
的分支。 You'll get the commits for this branch using 您将获得此分支的提交
git log d/e/f
That's fine too. 那也没关系。
Things start to get complicated if the item where git log
should work on could not be clearly determined. 如果
git log
应该处理的项目无法明确确定,事情开始变得复杂。 If you're stupid and call your branch a/b/c
too, git has no clue whose log shall be printed: that of the branch a/b/c
or the log of your directory a/b/c
? 如果你是愚蠢的并且也给你的分支机构打电话
a/b/c
,那么git就没有任何线索可以打印其日志: a/b/c
分支或你的目录日志a/b/c
? Therefore, you have to tell a bit more about the information you want to receive: 因此,您必须更多地了解您想要接收的信息:
a/b/c
: a/b/c
的日志: git log a/b/c --
a/b/c
in the current branch: a/b/c
的日志: git log -- a/b/c
a/b/c
in the a/b/c
branch: a/b/c
分支中文件夹 a/b/c
的日志: git log a/b/c -- a/b/c
With the deleted file, you have a similar problem: there's neither a file called path/to/file
present in the working copy, nor is there a branch called path/to/file
. 使用已删除的文件,您会遇到类似的问题:工作副本中既没有名为
path/to/file
,也没有名为path/to/file
的分支。 This is the reason why you have to specify what you want. 这就是你必须指定你想要的东西的原因。
Of course, git could know that there was a file called path/to/file
20.000 revisions ago but this would require (worst case) to search the entire history of your project whether such a file existed or not. 当然,混帐会知道有一个叫做文件
path/to/file
20.000修订前但这需要(最坏情况)来搜索项目的整个历史是否存在或没有这样的文件。
By explicitly specifying the file path after the --
, you tell git: 通过在
--
之后显式指定文件路径,你告诉git:
search harder for that file, even if it takes hours
即使需要数小时,也要更加努力地搜索该文件
Conclusion (answering your question): 结论(回答你的问题):
in your case, the --
is needed because otherwise git log
would work slower in general. 在你的情况下,
--
是必要的,因为否则git log
将一般工作比较慢。
Why the difference when the file exists versus when it doesn't? 为什么文件存在时的差异与不存在时的区别? Let's look at the cases:
让我们来看看案例:
Indeed it is. 的确是。
To know whether a file ever existed at some path means to walk history, opening each commit, opening each tree and walking the tree to see if this path existed then. 要知道文件是否存在于某个路径中意味着遍历历史记录,打开每个提交,打开每个树并走树,以查看此路径是否存在。 On a large repository with a lot of commits and a deep path... this could get expensive, especially on a slow disk.
在具有大量提交和深度路径的大型存储库中......这可能会变得昂贵,尤其是在慢速磁盘上。
But! 但! You say.
你说。 Isn't that exactly what
git log filename
does anyway? 这究竟是
git log filename
无论如何都不是吗? And the answer is yes, it is. 答案是肯定的,确实如此。 The difference is that when I run
git log filename
and the file is known to exist, then git-log
knows that I want to spend the time to get this history. 不同的是,当我运行
git log filename
并且知道该文件存在时, git-log
知道我想花时间来获取这个历史记录。
If, instead, I run git log foo
and foo is not a revision or a file that currently exists then it would need to invest the time to walk the entire graph just to tell me that foo
was ambiguous. 相反,如果我运行
git log foo
并且foo不是当前存在的修订版或文件,那么它需要花费时间来遍历整个图表,只是为了告诉我foo
是不明确的。
Ouch. 哎哟。
So you're welcome to say git log -- filename
to tell git that you really want it to go walking the graph. 所以欢迎你说
git log -- filename
来告诉git你真的希望它走图表。 Otherwise, it will decline. 否则,它会下降。
Side note: git merely stat(2)
s the argument you give on the command line to determine if the file exists. 旁注:git只是
stat(2)
s在命令行上给出的参数,用于确定文件是否存在。 It doesn't look in the index, nor does it open up your HEAD tree. 它不会查找索引,也不会打开您的HEAD树。 It could, of course, do those things, which would allow you to use
git log filename
where filename
was a deletion not staged for commit. 当然,它可以做那些事情,这将允许你使用
git log filename
,其中filename
是一个删除而不进行提交。 This seems like a very reasonable change. 这似乎是一个非常合理的变化。
there never was a tag by that name.
那个名字从未有过这个标签。
Why do you say that? 你为什么这么说?
git tag path/to/file
works just fine. git tag path/to/file
工作得很好。
It really is as simple as it looks: git rm
takes pathnames only; 它看起来非常简单:
git rm
只接受路径名; git log
takes ref names and path names, refnames first, and anything that could be a pathname could also be a ref name -- this isn't so much a rule for what could be a ref name as the definition. git log
获取引用名称和路径名,首先重新命名,任何可能是路径名的东西也可以是引用名称 - 这不是一个规则,可以作为定义的引用名称。
On small projects it'd be easy for git log to decide that if it's valid at all it has to have been a path to a source file at some point, but at this point you have to make a judgement call balancing the likelihood and cost of all the possible screwups here. 在小型项目上,git log很容易决定,如果它有效则必须在某个时刻成为源文件的路径,但此时你必须做出判断调用来平衡可能性和成本这里所有可能的搞砸了。 Is it likelier that you're asking for the logs for a file that no longer exists, or that you fatfingered an existing path name or an existing ref?
您是否更有可能要求提供不再存在的文件的日志,或者您是否使用了现有的路径名或现有的ref?
git log remote/ref
is very common. git log remote/ref
很常见。 I think git's just presuming a name that matches nothing current is likeliest to be a typo. 我认为git只是假设一个名称不匹配当前最有可能成为一个错字。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.