从远程 Git 存储库检索特定提交 [英] Retrieve specific commit from a remote Git repository

查看:30
本文介绍了从远程 Git 存储库检索特定提交的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

有没有办法只从远程 Git 存储库中检索一个特定的提交,而无需将其克隆到我的 PC 上?远程仓库的结构和我的完全一样,因此不会有任何冲突,但我不知道如何做到这一点,我不想克隆那个庞大的仓库.

我是 git 新手,有什么办法吗?

解决方案

从 Git 2.5+ 版(2015 年第 2 季度)开始,获取单个提交(无需克隆完整存储库)实际上是可能的.

请参阅 commit 68ee628.com/moroten" rel="nofollow noreferrer">Fredrik Medley (moroten),2015 年 5 月 21 日.
(由 Junio C Hamano 合并 -- gitster --commit a9d3493,2015 年 6 月 1 日)

你现在有一个新的配置(在服务器端)

uploadpack.allowReachableSHA1InWant

<块引用>

允许 upload-pack 接受一个 fetch 请求,该请求请求一个可以从任何 ref 提示访问的对象.但是,请注意,计算对象可达性的计算成本很高.
默认为 false.

如果您将该服务器端配置与浅层克隆结合起来 (git fetch --depth=1),你可以要求一次提交(见t/t5516-fetch-push.sh:

git fetch --depth=1 ../testrepo/.git <全长SHA1>

你可以使用git cat-file命令来查看提交是否已经被获取:

git cat-file commit <全长SHA1>

<块引用>

"git upload-pack"服务于git fetch";可以被告知服务不在任何 ref 尖端的提交,只要它们是可从 ref 访问,使用 uploadpack.allowReachableSHA1InWant配置变量.

matt 所述,在 评论:

<块引用>

注意 SHA 必须是完整的未缩写的 SHA,否则 Git 会声称它找不到提交


完整的文档是:

<块引用>

upload-pack:可选择允许获取可达的 sha1

<块引用>

在服务器端设置 uploadpack.allowReachableSHA1InWant 配置选项后,git fetch";可以提出带有想要"的请求命名尚未公布的对象的行(可能是从带外或从子模块指针获得的).
只有从分支提示可达的对象,即被transfer.hideRefs隐藏的广告分支和分支的联合,才会被处理.
请注意,必须返回历史记录以检查可达性会产生相关成本.

这个特性可以在获取某个commit的内容时使用,sha1 已知,无需克隆整个存储库,尤其是在使用浅提取时.

有用的例子是例如

  • 在历史记录中包含大文件的存储库,
  • 仅获取子模块检出所需的数据,
  • 当共享一个 sha1 而不告诉它属于哪个确切的分支和在 Gerrit 中时,如果你考虑的是提交而不是更改数量.
    (Gerrit 案例已经通过 allowTipSHA1InWant 解决了,因为每个 Gerrit 更改都有一个引用.)


Git 2.6(2015 年第 3 季度)将改进该模型.
参见 commit 2bc31d1commit cc118a6(2015 年 7 月 28 日) (peff).
(由 Junio C Hamano 合并 -- gitster --commit 824a0be,2015 年 8 月 19 日)

<块引用>

refs:支持否定 transfer.hideRefs

<块引用>

如果您使用 transfer.hideRefs 配置隐藏引用的层次结构,则以后无法将该配置覆盖为取消隐藏"它.
这个补丁实现了一个否定的"hide 导致匹配立即被标记为未隐藏,即使另一个匹配会隐藏它.
我们注意以与配置机制提供给我们的方式相反的顺序应用匹配项,因为这让我们通常的最后一个获胜"成为可能.配置优先工作(例如,.git/config 中的条目将覆盖 /etc/gitconfig).

所以你现在可以:

git config --system transfer.hideRefs refs/secretgit config transfer.hideRefs '!refs/secret/not-so-secret'

在所有 repos 中隐藏 refs/secret,除了一个公共位在一个特定的存储库中.


Git 2.7(2015 年 11 月/12 月)将再次改进:

参见 commit 948bfa2commit 00b293e(2015 年 11 月 5 日),commit 00b293erel="nofollow noreferrer">提交 78a766a,9commit 92cab4a href="https://github.com/git/git/commit/92cab492ba988ffd3e3edf040f19ba820306c833" rel="nofollow noreferrer">commit 92cab49, 提交92cab49 (2015年11月3日),提交 00b293e, commit 00b293e(2015 年 11 月 5 日),以及 提交 92cab49提交92cab49 commit 92cab49(2015 年 11 月 3 日)由 Lukas Fleischer (lfos).
帮助者:Eric Sunshine (sunshineco).
(由 Jeff King -- peff -- 合并在 提交 dbba85e,2015 年 11 月 20 日)

<块引用>

config.txt:用命名空间记录hideRefs的语义

<块引用>

目前,对于 transfer.hideRefs 应该如何处理没有明确的定义设置命名空间时的行为.
解释在这种情况下 hideRefs 前缀匹配剥离的名称.这就是 hideRefs 模式目前的样子在接收包中处理.

<块引用>

hideRefs:添加对匹配完整引用的支持

<块引用>

除了匹配剥离的 refs 之外,现在还可以添加 hideRefs 模式,以匹配完整(未剥离的)ref.
为了区分剥离匹配和完整匹配,这些新模式必须以抑扬符 (^) 为前缀.

因此 新文档:

transfer.hideRefs:

<块引用>

如果命名空间正在使用中,命名空间前缀会在每个引用与 transfer.hiderefs 模式匹配之前从每个引用中剥离.
例如,如果在 transfer.hideRefs 中指定了 refs/heads/master 并且当前命名空间是 foo,然后 refs/namespaces/foo/refs/heads/master广告中省略了但 refs/heads/masterrefs/namespaces/bar/refs/heads/master 仍然被宣传为所谓的有"线.
为了在剥离前匹配 refs,在前面添加一个 ^参考名称.如果将 !^ 结合使用,则必须先指定 !.


R.. 提到了 在评论中 配置 uploadpack.allowAnySHA1InWant,允许 upload-pack 接受 fetch要求任何对象的请求.(默认为 false).

请参阅 commit f8edeaa(2016 年 11 月,Git v2.11).a href="https://github.com/novalis" rel="nofollow noreferrer">大卫novalis"特纳(novalis):

<块引用>

upload-pack:可选择允许获取任何 sha1

<块引用>

在我们的情况下进行可达性检查似乎有点愚蠢信任用户绝对可以访问存储库中的所有内容.

此外,它在分布式系统中很活跃——也许是一台服务器为一个 ref 做广告,但此后另一个 ref 强行推向了该 ref,也许这两个 HTTP 请求最终指向这些不同的服务器.


使用 Git 2.34(2021 年第四季度),man) 在 git fetch(man) 在处理 want-ref 请求时忘记考虑 ref 命名空间.

参见 commit 53a66eccommit 3955140, 提交 bac01c6(2021 年 8 月 13 日)由 Kim Altintop (kim).
(由 Junio C Hamano 合并 -- gitster --commit 1ab13eb,2021 年 9 月 10 日)

<块引用>

docs:阐明传输的交互.hideRefs 和命名空间

签字人:Kim Altintop
审核人:Jonathan Tan

<块引用>

展开transfer.hideRefs文档中关于命名空间的部分,指出upload-packreceive-pack之间的细微差别.

3955140(upload-pack.c:相对于命名空间02处理想要引用",-07-30, Git v2.34.0 -- merge列在batch #5) 教 upload-pack 拒绝 want-refs 用于隐藏的 refs,现在提到了.
需要澄清的是,隐藏 ref 的名称不会被泄露,但它指向的对象 id 可能会被泄露.

git config 现在包含在其 手册页:

<块引用>

在与 transfer.hiderefs 模式匹配之前的引用.在为了在剥离前匹配 refs,请在 ref 名称前添加 ^.如果结合!^,必须先指定!.

git config 现在包含在其 手册页:

<块引用>

从广告中省略.如果设置了 uploadpack.allowRefInWantupload-pack 将在协议 v2 中处理 want-ref refs/heads/masterfetch 命令就好像 refs/namespaces/foo/refs/heads/master 不存在一样.receive-pack,另一方面,仍然会公布对象 idref 指向而不提及其名称(所谓的.have"行).

Is there any way to retrieve only one specific commit from a remote Git repo without cloning it on my PC? The structure of remote repo is absolutely same as that of mine and hence there won't be any conflicts but I have no idea how to do this and I don't want to clone that huge repository.

I am new to git, is there any way?

解决方案

Starting with Git version 2.5+ (Q2 2015), fetching a single commit (without cloning the full repo) is actually possible.

See commit 68ee628 by Fredrik Medley (moroten), 21 May 2015.
(Merged by Junio C Hamano -- gitster -- in commit a9d3493, 01 Jun 2015)

You now have a new config (on the server side)

uploadpack.allowReachableSHA1InWant

Allow upload-pack to accept a fetch request that asks for an object that is reachable from any ref tip. However, note that calculating object reachability is computationally expensive.
Defaults to false.

If you combine that server-side configuration with a shallow clone (git fetch --depth=1), you can ask for a single commit (see t/t5516-fetch-push.sh:

git fetch --depth=1 ../testrepo/.git <full-length SHA1>

You can use the git cat-file command to see that the commit has been fetched:

git cat-file commit <full-length SHA1>

"git upload-pack" that serves "git fetch" can be told to serve commits that are not at the tip of any ref, as long as they are reachable from a ref, with uploadpack.allowReachableSHA1InWant configuration variable.

As noted by matt in the comments:

Note that SHA must be the full unabbreviated SHA, otherwise Git will claim it couldn't find the commit


The full documentation is:

upload-pack: optionally allow fetching reachable sha1

With uploadpack.allowReachableSHA1InWant configuration option set on the server side, "git fetch" can make a request with a "want" line that names an object that has not been advertised (likely to have been obtained out of band or from a submodule pointer).
Only objects reachable from the branch tips, i.e. the union of advertised branches and branches hidden by transfer.hideRefs, will be processed.
Note that there is an associated cost of having to walk back the history to check the reachability.

This feature can be used when obtaining the content of a certain commit, for which the sha1 is known, without the need of cloning the whole repository, especially if a shallow fetch is used.

Useful cases are e.g.

  • repositories containing large files in the history,
  • fetching only the needed data for a submodule checkout,
  • when sharing a sha1 without telling which exact branch it belongs to and in Gerrit, if you think in terms of commits instead of change numbers.
    (The Gerrit case has already been solved through allowTipSHA1InWant as every Gerrit change has a ref.)


Git 2.6 (Q3 2015) will improve that model.
See commit 2bc31d1, commit cc118a6 (28 Jul 2015) by Jeff King (peff).
(Merged by Junio C Hamano -- gitster -- in commit 824a0be, 19 Aug 2015)

refs: support negative transfer.hideRefs

If you hide a hierarchy of refs using the transfer.hideRefs config, there is no way to later override that config to "unhide" it.
This patch implements a "negative" hide which causes matches to immediately be marked as unhidden, even if another match would hide it.
We take care to apply the matches in reverse-order from how they are fed to us by the config machinery, as that lets our usual "last one wins" config precedence work (and entries in .git/config, for example, will override /etc/gitconfig).

So you can now do:

git config --system transfer.hideRefs refs/secret
git config transfer.hideRefs '!refs/secret/not-so-secret'

to hide refs/secret in all repos, except for one public bit in one specific repo.


Git 2.7 (Nov/Dec 2015) will improve again:

See commit 948bfa2, commit 00b293e (05 Nov 2015), commit 78a766a, commit 92cab49, commit 92cab49, commit 92cab49 (03 Nov 2015), commit 00b293e, commit 00b293e (05 Nov 2015), and commit 92cab49, commit 92cab49, commit 92cab49, commit 92cab49 (03 Nov 2015) by Lukas Fleischer (lfos).
Helped-by: Eric Sunshine (sunshineco).
(Merged by Jeff King -- peff -- in commit dbba85e, 20 Nov 2015)

config.txt: document the semantics of hideRefs with namespaces

Right now, there is no clear definition of how transfer.hideRefs should behave when a namespace is set.
Explain that hideRefs prefixes match stripped names in that case. This is how hideRefs patterns are currently handled in receive-pack.

hideRefs: add support for matching full refs

In addition to matching stripped refs, one can now add hideRefs patterns that the full (unstripped) ref is matched against.
To distinguish between stripped and full matches, those new patterns must be prefixed with a circumflex (^).

Hence the new documentation:

transfer.hideRefs:

If a namespace is in use, the namespace prefix is stripped from each reference before it is matched against transfer.hiderefs patterns.
For example, if refs/heads/master is specified in transfer.hideRefs and the current namespace is foo, then refs/namespaces/foo/refs/heads/master is omitted from the advertisements but refs/heads/master and refs/namespaces/bar/refs/heads/master are still advertised as so-called "have" lines.
In order to match refs before stripping, add a ^ in front of the ref name. If you combine ! and ^, ! must be specified first.


R.. mentions in the comments the config uploadpack.allowAnySHA1InWant, which allows upload-pack to accept a fetch request that asks for any object at all. (Defaults to false).

See commit f8edeaa (Nov. 2016, Git v2.11.1) by David "novalis" Turner (novalis):

upload-pack: optionally allow fetching any sha1

It seems a little silly to do a reachabilty check in the case where we trust the user to access absolutely everything in the repository.

Also, it's racy in a distributed system -- perhaps one server advertises a ref, but another has since had a force-push to that ref, and perhaps the two HTTP requests end up directed to these different servers.


With Git 2.34 (Q4 2021), "git upload-pack"(man) which runs on the other side of git fetch(man) forgot to take the ref namespaces into account when handling want-ref requests.

See commit 53a66ec, commit 3955140, commit bac01c6 (13 Aug 2021) by Kim Altintop (kim).
(Merged by Junio C Hamano -- gitster -- in commit 1ab13eb, 10 Sep 2021)

docs: clarify the interaction of transfer.hideRefs and namespaces

Signed-off-by: Kim Altintop
Reviewed-by: Jonathan Tan

Expand the section about namespaces in the documentation of transfer.hideRefs to point out the subtle differences between upload-pack and receive-pack.

3955140 ("upload-pack.c: treat want-ref relative to namespace", 2021-07-30, Git v2.34.0 -- merge listed in batch #5) taught upload-pack to reject want-refs for hidden refs, which is now mentioned.
It is clarified that at no point the name of a hidden ref is revealed, but the object id it points to may.

git config now includes in its man page:

reference before it is matched against transfer.hiderefs patterns. In order to match refs before stripping, add a ^ in front of the ref name. If you combine ! and ^, ! must be specified first.

git config now includes in its man page:

is omitted from the advertisements. If uploadpack.allowRefInWant is set, upload-pack will treat want-ref refs/heads/master in a protocol v2 fetch command as if refs/namespaces/foo/refs/heads/master did not exist. receive-pack, on the other hand, will still advertise the object id the ref is pointing to without mentioning its name (a so-called ".have" line).

这篇关于从远程 Git 存储库检索特定提交的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆