为什么没有 Git Clone 特定的提交选项?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/26135216/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Why Isn't There A Git Clone Specific Commit Option?
提问by ivan.sim
In light of a recent question on SO, I am wondering why isn't there an option in git clone
such that the HEAD
pointer of the newly created branch will point to a specified commit? In say question above, OP is trying to provide instructions on the specific commit his users should clone.
鉴于最近关于 SO的一个问题,我想知道为什么没有一个选项可以让新创建的分支git clone
的HEAD
指针指向指定的提交?在上面的问题中,OP 试图提供有关他的用户应该克隆的特定提交的说明。
Note that this question is not about How To Clone To A Particular Versionusing reset
; but about why isn't there?
采纳答案by torek
Two answers so far (at the time I wrote this, now there are more) are correct in what they say, but don't really answer the "why" question. Of course, the "why" question is really hard to answer, except by the authors of the various bits of Git (and even then, what if two frequent Git contributors gave two different answers?).
到目前为止,有两个答案(在我写这篇文章的时候,现在有更多)在他们所说的方面是正确的,但并没有真正回答“为什么”的问题。当然,“为什么”这个问题真的很难回答,除了 Git 各个部分的作者(即便如此,如果两个频繁的 Git 贡献者给出了两个不同的答案呢?)。
Still, considering Git's "philosophy" as it were, in general, the various transfer protocols work by naming a reference. If they provide an SHA-1, it's the SHA-1 of that reference. For someone who does not already have direct (e.g., command-line) access to the repository, none1of the built in commands allow one to refer to commits by ID. The closest thing I can find to a reasonfor this—and it is actually a good reason2—is this bit in the git upload-archive
documentation:
尽管如此,考虑到 Git 的“哲学”,一般来说,各种传输协议通过命名引用来工作。如果他们提供 SHA-1,则是该参考的 SHA-1 。对于人谁不已经有直接的(如命令行)访问存储库,没有1内置在命令允许一个由ID来指代的提交。我能找到的最接近原因的事情——实际上是一个很好的原因2——是git upload-archive
文档中的这一点:
SECURITY
In order to protect the privacy of objects that have been removed from history but may not yet have been pruned, git-upload-archive avoids serving archives for commits and trees that are not reachable from the repository's refs. However, because calculating object reachability is computationally expensive, git-upload-archive implements a stricter but easier-to-check set of rules ...
安全
为了保护已从历史记录中删除但可能尚未修剪的对象的隐私,git-upload-archive 避免为无法从存储库的引用访问的提交和树提供存档。然而,因为计算对象可达性的计算成本很高,所以 git-upload-archive 实现了一套更严格但更易于检查的规则......
However, it goes on to say:
然而,它接着说:
If the config option
uploadArchive.allowUnreachable
is true, these rules are ignored, and clients may use arbitrary sha1 expressions. This is useful if you do not care about the privacy of unreachable objects, or if your object database is already publicly available for access via non-smart-http.
如果 config 选项
uploadArchive.allowUnreachable
为 true,则忽略这些规则,并且客户端可以使用任意 sha1 表达式。如果您不关心无法访问对象的隐私,或者您的对象数据库已经可以通过非智能 http 公开访问,这将非常有用。
which is particularly interesting since git clone
gets all reachable objects in the first place, after which your local clone could trivially check out a commit by SHA-1 ID (and create a local branch name pointing to that ID if desired, or just leave your clone in "detached HEAD" mode).
这特别有趣,因为首先git clone
获取所有可访问的对象,之后您的本地克隆可以通过 SHA-1 ID 轻松检查提交(并根据需要创建指向该 ID 的本地分支名称,或者只是将您的克隆留在“分离头”模式)。
Given these two cross-currents, I think the real answer to "why", at this point, is "nobody cares enough to add it". :-) The privacy argument is valid, but there is no reason that git clone
could not check out a commit by ID after cloning, just as it can be told to check out some branch other than master
3with git clone -b ...
. The only drawback to allowing -b sha1
is that Git cannot check up front (before the cloning process begins) whether sha1
will be received. It cancheck reference names, since those are transferred (along with their branch tips or other SHA-1 values) up front, so git clone -b nonexistentbranch ssh://...
terminates quickly and does not create the copy:
鉴于这两个交叉流,我认为此时“为什么”的真正答案是“没有人足够关心添加它”。:-)隐私的说法是有效的,但没有理由git clone
不能检查出克隆后提交的ID,只是因为它可以告诉检查出比其他一些分行master
3用git clone -b ...
。允许的唯一缺点是 Git 无法预先检查(在克隆过程开始之前)是否会收到。它可以检查引用名称,因为这些名称是预先传输的(连同它们的分支提示或其他 SHA-1 值),因此会快速终止并且不会创建副本:-b sha1
sha1
git clone -b nonexistentbranch ssh://...
fatal: Remote branch nonexistentbranch not found in upstream origin
fatal: The remote end hung up unexpectedly
If -b
allowed an ID, you'd get the whole clone, then it would have to tell you: "oh gosh, sorry, can't check out that ID, I'll leave you on master instead" or whatever. (Which is more or less what happens now with a busted submodule.)
如果-b
允许一个 ID,你会得到整个克隆,然后它会告诉你:“哦,天哪,对不起,不能检查那个 ID,我会让你留在 master 上”或其他什么。(这或多或少是现在被破坏的子模块发生的情况。)
1While git upload-archive
nowenforces this "privacy" rule, this was not always the case (it was introduced in version 1.7.8.1); and many (most?) git-web servers, including the one distributed with Git itself, allow viewing by arbitrary ID. This is probably why allowUnreachable
was added to upload-archive
a few years after the "only by ref name" code was added (but note that releases of Git after 1.7.8 and before 2.0.0 have no way to loosen the rules). Hence, while the "security" idea is valid, there was a period (pre 1.7.8.1) when it was not enforced.
1虽然git upload-archive
现在强制执行此“隐私”规则,但情况并非总是如此(它是在 1.7.8.1 版中引入的);许多(大多数?)git-web 服务器,包括与 Git 本身一起分发的服务器,允许通过任意 ID 进行查看。这可能就是为什么allowUnreachable
在添加upload-archive
“only by ref name”代码后几年才添加的原因(但请注意,1.7.8 之后和 2.0.0 之前的 Git 版本无法放松规则)。因此,虽然“安全”的想法是有效的,但有一段时间(1.7.8.1 之前)没有强制执行。
2There are numerous ways to "leak" ostensibly private data out of a Git repository. A new file, Documentation/transfer-data-leaks, is about to appear in Git 2.11.1, while Git 2.11.0 added some internal features (see commit 722ff7f87among others) to immediately drop objects pushed but not accepted. Such objects are eventually garbage-collected, but that leaves them exposed for the duration.
2有多种方法可以从 Git 存储库中“泄露”表面上的私有数据。一个新文件Documentation/transfer-data-leaks即将出现在 Git 2.11.1 中,而 Git 2.11.0 添加了一些内部功能(参见提交 722ff7f87等)以立即删除推送但未被接受的对象。这样的对象最终会被垃圾收集,但这会使它们在持续时间内暴露。
3Actually, by default git clone
makes a local check-out of the branch it thinks goes with the remote's HEAD
reference. Usually that's master
anyway, though.
3实际上,默认情况下git clone
,对它认为与远程HEAD
引用一致的分支进行本地检出。不过,通常情况下也是master
如此。
回答by Andrew C
Cloning a repo is a different operation than checkout. You don't "clone a specific commit". For convenience you can clone and then checkout a particular pre-existing branch at the same time, since that is what most people want. If that doesn't meet your needs (no branch for the particular SHA you want) just use or alias some form of
克隆 repo 是与 checkout 不同的操作。您不会“克隆特定的提交”。为方便起见,您可以克隆并同时检出特定的预先存在的分支,因为这是大多数人想要的。如果这不能满足您的需求(您想要的特定 SHA 没有分支),只需使用或别名某种形式的
git clone -n <some repo> && cd <some repo> && git checkout SHA
回答by Andrew C
As the other answers say, this is typically not much of an issue, but they don't say why you can't clone a specific commit. The answer is security.
正如其他答案所说,这通常不是什么大问题,但他们没有说明为什么不能克隆特定提交。答案是安全。
If you accidentally push confidential information, and then force-push a fixed history, the commits with the confidential information will still be stored on the server, until the server's Git's garbage collector finds it is no longer needed. If the hash is known (it might for example be available in logs), a malicious user might request the specific commit that shouldn't have been pushed, even if you were able to verify that when you force-pushed the fixed history, nobody had fetched those commits yet.
如果你不小心推送了机密信息,然后强制推送了一个固定的历史记录,带有机密信息的提交仍然会存储在服务器上,直到服务器的 Git 的垃圾收集器发现它不再需要。如果哈希是已知的(例如它可能在日志中可用),恶意用户可能会请求不应该推送的特定提交,即使您能够验证当您强制推送修复的历史时,没有人已经获取了那些提交。
Making sure you can only clone from refs makes sure that only "reachable" commits will be sent to the clients.
确保您只能从 refs 克隆确保只有“可访问”的提交才会发送到客户端。
回答by VonC
If your specific commit is referenced by a branch, you can do a:
如果您的特定提交被分支引用,您可以执行以下操作:
git clone -b yourBranch /url/of/the/repo
The cloned repo will be directly at the commit referenced by that branch.
克隆的 repo 将直接位于该分支引用的提交处。