有没有办法从远程Git回购中只检索一个特定的提交,而不将其克隆到我的PC上?远程回购的结构与我的完全相同,因此不会有任何冲突,但我不知道如何做到这一点,我不想克隆那个巨大的存储库。

我是新来的,有什么办法吗?


您只需克隆一次,因此如果您已经有了远程存储库的克隆,那么从它提取就不会再次下载所有内容。只需指出您想要拉哪个分支,或者获取更改并签出您想要的提交。

从新的存储库中获取带宽非常便宜,因为它只会下载您没有的更改。考虑到Git以最小的负载做出正确的事情。

Git将所有内容都存储在。Git文件夹中。提交不能孤立地获取和存储,它需要所有的祖先。它们是相互关联的。


为了减少下载大小,你可以让git只获取与特定分支相关的对象或提交:

git fetch origin refs/heads/branch:refs/remotes/origin/branch

这将只下载包含在远程分支分支中的提交(以及您错过的那些),并将其存储在origin/branch中。然后您可以合并或签出。

你也可以只指定一个SHA1提交id——但注意你必须使用完整的40个字符不缩写的标识符:

git fetch origin 96de5297df87096de5297df87096de5297df8709:refs/remotes/origin/foo-commit

这将只下载指定的SHA-1 96de5297df87096de5297df8709(以及您错过的祖先)的提交,并将其存储为(不存在的)远程分支origin/foo-commit。


我查了一下我的git repo

git pull --rebase <repo> <branch>

允许git为分支拉入所有代码,然后我对我感兴趣的提交进行了重置。

Git reset——hard <commit-hash>

希望这能有所帮助。


您可以简单地获取远程回购的单个提交

git fetch <repo> <commit-id>

在那里,

<repo>可以是一个远程回购名称(例如origin),甚至是一个远程回购URL(例如https://git.foo.com/myrepo.git) <commit- ID >是提交的ID

例如

git fetch https://git.foo.com/myrepo.git 0a071603d87e0b89738599c160583a19a6d95545

在获取提交(以及丢失的祖先)之后,您可以简单地用它签出

git checkout FETCH_HEAD

注意,这将使你进入“分离的头脑”状态。


我认为'git ls-remote' (http://git-scm.com/docs/git-ls-remote)应该做你想要的。不用用力,取或拉。


从Git 2.5+版本(2015年第二季度)开始,获取单个提交(不克隆完整的回购)实际上是可能的。

参见Fredrik Medley的commit 68ee628 (moroten), 2015年5月21日。 (由Junio C Hamano—gitster—在commit a9d3493中合并,2015年6月1日)

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

uploadpack.allowReachableSHA1InWant

允许upload-pack接受一个获取请求,该请求要求从任何引用提示可达的对象。但是,请注意,计算对象可达性在计算上是昂贵的。 默认为false。

如果你把服务器端配置和一个浅克隆(git fetch——depth=1)结合起来,你可以请求一次提交(参见t/t5516-fetch-push.sh:

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

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

git cat-file commit <full-length SHA1>

服务于“git fetch”的“git upload-pack”可以被告知服务 提交的文件不在任何引用的顶端,只要它们在 使用uploadpack.allowReachableSHA1InWant从ref中可达 配置变量。

正如matt在评论中所指出的:

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


完整的文档如下:

上传包:可选地允许抓取可达的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(2015年第三季度)将改进该模型。 参见Jeff King (peff)的commit 2bc31d1, commit cc118a6(2015年7月28日)。 (由Junio C Hamano—gitster—在commit 824a0be中合并,2015年8月19日)

refs:支持负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(2015年11月/ 12月)将再次改进:

参见Lukas Fleischer (lfos)的commit 948bfa2, commit 00b293e(2015年11月05日),commit 78a766a, commit 92cab49, commit 92cab49, commit 92cab49, commit 92cab49(2015年11月03日),commit 00b293e, commit 00b293e(2015年11月05日),commit 92cab49, commit 92cab49, commit 92cab49, commit 92cab49, commit 92cab49, commit 92cab49(2015年11月03日)。 帮助:Eric Sunshine (sunshineco)。 (由Jeff King在commit dbba85e中合并,2015年11月20日)

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

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

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

除了匹配剥离的引用,现在还可以添加hideRefs模式,以匹配完整的(未剥离的)引用。 为了区分剥离匹配和完全匹配,这些新模式必须以回旋(^)作为前缀。

因此有了新的文档:

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 . .在评论中提到config uploadpack。allowAnySHA1InWant,它允许upload-pack接受请求任何对象的获取请求。(默认为false)。

参见David "novalis" Turner (novalis)提交f8edeaa(2016年11月,Git v2.11.1):

上传包:可选的允许抓取任何sha1

在这种情况下做可达性检查似乎有点傻 相信用户可以访问存储库中的所有内容。 此外,它在分布式系统(也许是一台服务器)中很有活力 给裁判打了广告,但另一个人后来对裁判用力推搡, 也许这两个HTTP请求最终指向这些不同的 服务器。


在Git 2.34 (Q4 2021)中,运行在Git fetch(man)另一端的“Git upload-pack”(man)在处理want-ref请求时忘记考虑ref名称空间。

参见Kim Altintop (Kim)的commit 53a66ec, commit 3955140, commit bac01c6(2021年8月13日)。 (由Junio C Hamano—gitster—在commit 1ab13eb中合并,2021年9月10日)

文件:阐明转让的相互作用。hideRefs和命名空间 署名:Kim Altintop 作者:Jonathan Tan

展开转移文档中关于名称空间的部分。hideRefs来指出上传包和接收包之间的细微差别。 3955140 ("upload-pack.c: treat want-ref relative to namespace", 2021-07-30, Git v2.34.0——merge列在批处理#5中)教upload-pack拒绝隐藏引用的want-ref,这是现在提到的。 需要澄清的是,在任何时候隐藏引用的名称都不会显示,但它指向的对象id可能会显示。

Git配置现在包括在它的手册页:

引用,然后再匹配传输。hiderefs模式。在 为了在剥离之前匹配引用,在引用名称前添加^。如果 你结合起来!^, !必须先指定。

Git配置现在包括在它的手册页:

在广告中被省略。如果uploadpack。allowRefInWant已设置, Upload-pack将在协议v2中处理want-ref refs/heads/master 获取命令,就好像refs/namespaces/foo/refs/heads/master不存在一样。 另一方面,Receive-pack仍将通告对象id the Ref指的是没有提到它的名字(一个所谓的“。有“线)。


在Git 2.39 (Q4 2022)中,“Git receive-pack”(man)曾经使用所有本地引用作为边界来检查Git push(man)发送的数据的连通性,但现在它只使用它通告给推送器的引用。 在具有. hiderefs配置的存储库中,这减少了执行检查所需的资源。

参见Patrick Steinhardt (pks-t)的commit bcec678, commit 5ff36c9, commit 8c1bc2a, commit 1e9f273, commit 05b9425, commit 9b67eb6, commit 5eeb9aa(2022年11月17日)。 (由Junio C Hamano合并- gitster -在提交f8828f9, 2022年11月23日)

修正:添加了新的参数来排除隐藏的引用 署名:Patrick Steinhardt 署名:泰勒·布劳

用户可以选择在git-upload-pack(1), git-receive-pack(1)和其他传输中隐藏远程用户的引用。hideRefs,但是现在没有一个简单的方法来获得所有可见或隐藏引用的列表。 我们只需要在连接性检查中提高性能。 添加一个新选项——exclude-hidden=,用于排除下一个伪引用(如——all或——branches)中的任何隐藏引用。

Rev-list-options现在包括在它的手册页:

——exclude-hidden =[收到| uploadpack] 不包括引用,将被git-receive-pack或隐藏 通过咨询适当的接收Git-upload-pack。hideRefs或 uploadpack。hideRefs配置和传输。hideRefs(见 git配置)。该选项会影响下一个伪引用选项 ——all or——glob,并在处理后被清除。

And:

Rev-parse: add——exclude-hidden=选项 署名:Patrick Steinhardt 署名:泰勒·布劳

添加一个新的——exclude-hidden=选项,类似于我们刚刚添加到git-rev-list(1)中的选项。 给定一个section名称uploadpack或receive作为参数,它会导致我们排除所有将被各自的$section隐藏的引用。hideRefs配置。

Git rev-parse现在包含在它的手册页中:

——exclude-hidden =[收到| uploadpack] 不包括引用,将被git-receive-pack或隐藏 通过咨询适当的接收Git-upload-pack。hideRefs或 uploadpack。hideRefs配置和传输。hideRefs(见 git配置)。该选项会影响下一个伪引用选项 ——all or——glob,并在处理后被清除。


你可以简单地获取远程回购:

git fetch <repo>

在那里,

<repo>可以是一个远程回购名称(例如origin),甚至是一个远程回购URL(例如https://git.foo.com/myrepo.git)

例如:

git fetch https://git.foo.com/myrepo.git 

在你获得repo之后,你可以合并你想要的提交(因为这个问题是关于检索一个提交,而不是合并,你可以使用cherry-pick来选择一个提交):

git merge <commit>

<commit>可以是SHA1提交

例如:

git cherry-pick 0a071603d87e0b89738599c160583a19a6d95545

or

git merge 0a071603d87e0b89738599c160583a19a6d95545

如果是你想合并的最新提交,你也可以使用FETCH_HEAD变量:

git cherry-pick (or merge) FETCH_HEAD

最后,我找到了一种方法来克隆特定的提交使用git的樱桃。 假设你在本地没有任何存储库,你要从远程提交特定的文件,

1)在本地和git init中创建空仓库

2) git远程添加url-of-repository

3) git获取原点[这将不会移动您的文件到您的本地工作空间,除非您合并]

4)“输入你需要的”

完成了。这样,您将只有来自特定提交的文件在您的本地。

Enter-long-commit-hash:

你可以使用-> git log——pretty=oneline来获得


这样做效果最好:

git fetch origin specific_commit
git checkout -b temp FETCH_HEAD

将“temp”命名为你想要的任何名称…这个分支可能是孤儿


如果请求的提交是在远程回购的pull请求中,你可以通过它的ID获得它:

# Add the remote repo path, let's call it 'upstream':
git remote add upstream https://github.com/repo/project.git

# checkout the pull ID, for example ID '60':
git fetch upstream pull/60/head && git checkout FETCH_HEAD

在一个项目中,我们遇到了一个问题,所以我们必须恢复到某个提交。我们成功地使用以下命令:

git reset --hard <commitID>

# make sure you fetch from the origin first
$ git fetch origin

# view code at COMMIT_ID (abc123)
$ git checkout abc123

# bring only COMMIT_ID (abc123)
# to your branch
# assuming your branch is master
$ git checkout master
$ git cherry-pick abc123

# bring all changes up to 
# COMMIT_ID (abc123) to your branch
# assuming your branch is master
$ git checkout master
$ git merge abc123

参考资料- https://unfuddle.com/stack/tips-tricks/git-pull-specific-commit/