有什么方法可以从远程Git存储库中仅检索一个特定的提交,而无需将其克隆到我的PC上吗?远程回购的结构与我的完全相同,因此不会有任何冲突,但是我不知道如何执行此操作,并且我也不想克隆该庞大的存储库。

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

评论

您现有的存储库是否已经是远程存储库的克隆,还是完全不同?

好吧,仓库是Linux内核源代码,它几乎相同

那么它是克隆还是否?

不完全是。考虑到这一点,让远程仓库位于D头,而我的仓库位于A头,然后由B,C,D提交落后。我希望合并一个仓库中的提交B和另一个仓库中的C以及另一个仓库中的D的合并,因为这些仓库中的B,C,D提交具有各自的特长

@VarunChitre您可以接受VonC的其他回答吗?

#1 楼

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

请参阅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 $SHA1


您可以使用git cat-file命令查看是否已提取该提交:

git cat-file commit $SHA1



告诉服务“ git upload-pack”的“ git fetch”服务
不在任何引用尖端的提交,只要它们是
带有uploadpack.allowReachableSHA1InWant
配置变量的参考。



完整的文档是:



upload-pack :可选地允许获取可访问的sha1

在服务器端设置了uploadpack.allowReachableSHA1InWant配置选项后,“ git fetch”可以使用“ want”行发出请求,该行命名未发布的对象(可能具有从带外或从子模块pointe获得r)。
仅处理分支提示中可到达的对象,即,已通告的分支和被transfer.hideRefs隐藏的分支的并集。
请注意,必须追溯历史到检查可达性。

在获取sha1已知的特定提交的内容时可以使用此功能,而无需克隆整个
存储库,尤其是在使用浅层抓取的情况下。

有用的例子是


历史记录中包含大文件的存储库,
仅在共享sha1而不知道它属于哪个确切分支以及在Gerrit中时,才获取子模块检出所需的数据,

(Gerrit案例已经通过allowTipSHA1InWant得到解决,因为每个Gerrit更改都有参考。)



>
Git 2.6(2015年第三季度)将改进该模型。
请参见Jeff King(peff)提交的commit 2bc31d1,cc118a6(2015年7月28日)(由Junio C Hamano合并-gitster-在824a0be,2015年8月19日提交)



refs:支持负数transfer.hideRefs


如果您使用transfer.hideRefs隐藏引用的层次结构config,以后没有办法覆盖该配置以“取消隐藏”。
此修补程序实现了“负”隐藏,即使其他匹配项将其隐藏,该匹配也会立即将匹配项标记为未隐藏。 >我们会谨慎申请配置工具以相反的顺序匹配它们,因为这使我们通常的“最后一个获胜”配置优先级起作用(例如,.git/config中的条目将覆盖/etc/gitconfig)。

因此,您现在可以执行以下操作:


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



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





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

请参阅commit 948bfa2,00b293e(11月5日) 2015),commit 78a766a,commit 92cab49,commit 92cab49,commit 92cab49(2015年11月3日),commit 00b293e,commit 00b293e(2015年11月5日),commit 92cab49,commit 92cab49,commit 92cab49,commit 92cab49(2015年11月3日) Fleischer(lfos)。
帮助人:Eric Sunshine(sunshineco)(由Jeff King-peff合并-in commit dbba85e,2015年11月20日)



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

目前,还没有明确定义transfer.hideRefs在设置命名空间时应如何表现。
解释hideRefs前缀与剥离名称匹配的情况。这是目前在接收包中处理hideRefs模式的方式。

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

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


因此有了新文档:

transfer.hideRefs:



如果正在使用命名空间,则在与transfer.hiderefs模式匹配之前,将从每个引用中删除该命名空间前缀。 。
例如,如果在refs/heads/master中指定了transfer.hideRefs,并且
当前名称空间是foo,则广告中省略了refs/namespaces/foo/refs/heads/master
,但是refs/heads/master
refs/namespaces/bar/refs/heads/master仍然被广告为-称为
“有”行。
为了在剥离之前匹配参考,请在参考名称的前面添加一个^。如果将!^结合使用,则必须首先指定!



R ..在注释中提到了uploadpack.allowAnySHA1InWant配置,该配置允许upload-pack接受询问的fetch请求对于任何物体。 (默认为false)。

请参阅David“ novalis” Turner的commit f8edeaa(2016年11月,Git v2.11.1)(novalis):



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

在我们
信任用户绝对访问存储库中的所有内容的情况下,进行可达性检查似乎有些愚蠢。 />
而且,它在分布式系统中非常流行-也许一台服务器
广告了一个引用,但是另一台服务器随后对该引用进行了强制推送,
也许这两个HTTP请求最终将定向到这些不同的服务器。


评论


您能否给出一个更完整的示例,说明如何仅通过一次提交即可创建回购克隆?我尝试了但是失败了..谢谢!

– Lars Bilke
15年8月6日在12:55

我想推送到GitHub。也许他们不允许这样做。

– Lars Bilke
15年8月6日在12:57

@LarsBilke我们在这里谈论克隆或拉动,而不是推。而且我很确定GitHub在服务器端还没有Git 2.5。

–VonC
15年8月6日在12:58

现在更好的是,没有没有可达性计算惩罚(和DoS向量)的uploadpack.allowAnySHA1InWant。

–R .. GitHub停止帮助ICE
18年6月26日在16:46

谢谢!我觉得有趣的是,他们将其描述为“信任用户访问”,而不是“信任回购作者不要随意散发他们不打算公开的废话”。

–R .. GitHub停止帮助ICE
18年6月27日在0:27

#2 楼

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

从新存储库中获取带宽非常便宜,因为它只会下载您不需要的更改有。考虑一下用最小的负载使Git做正确的事情。

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


要减小下载大小,您可以要求git只提取与特定分支或提交有关的对象:

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


这将仅下载远程分支branch中包含的提交(以及仅丢失的提交),并将其存储在origin/branch中。然后可以合并或签出。

还可以仅指定SHA1提交:

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


这将仅下载指定的提交。 SHA-1 96de5297df870(及其缺少的祖先),并将其存储为(不存在的)远程分支origin/foo-commit

评论


您似乎对克隆的含义感到困惑。从远程存储库中获取更改时,您不会克隆它,而只是在历史记录中获得提交。然后选择要签出的提交,或将其合并到历史记录中

–CharlesB
13年2月14日在10:44



它仍然使用git fetch下载大量数据(430mb)。所需的提交只有几kbs。真的没有特殊命令可以执行此操作吗?如果我想删除“ git fetched”仓库,该怎么办?它存储在哪里?

–Varun Chitre
13年2月14日在11:23

现在这已经过时了。我们既可以执行浅克隆,又可以获取单个提交。现在允许浅克隆正常进行推送和获取,而不必了解项目的完整历史记录,因此说没有祖先不能单独提交就不再正确。您说的是在初始克隆之后进行取回的说法是正确的,但我们还有更便宜的选择。

–西奥多·默多克(Theodore Murdock)
2015年10月12日在22:03



最后一条命令(使用SHA1提交)对我不起作用。该命令会静默执行“某些操作”一段时间,然后退出,没有任何消息或明显的副作用。

–HRJ
16-8-26在5:32



@HRJ是的,我也在Ubuntu 16.04的Git 2.7.4-0ubuntu1.3上遇到过。但是,当使用git-core PPA中的2.16.2-0ppa1〜ubuntu16.04.1时,此方法应能正常工作。听起来像个已修复的错误。不能通过快速搜索找到对此的引用。如果有人可以帮我指点一下,我很乐意将此修补程序向后移植。

– Gertvdijk
18-2-27在12:46

#3 楼

我在git repo上做了一个pull:

git pull --rebase <repo> <branch>


允许git提取分支的所有代码,然后我进行了一次重置以提交对我感兴趣。

git reset --hard <commit-hash>

希望对您有所帮助。

评论


没有任何答案有效,尽管这个答案挽救了我的生命!谢谢一群!

–michaeltintiuc
2014年12月8日23:19

重置-克隆后为我辛苦了!谢谢。

–尼克-ACNB
15年3月20日在20:33

-1:诸如git reset --hard之类的“破坏性”命令在通用解决方案中共享时,可能导致人们陷入陷阱,从而丢失数据(或者在这种情况下:处于无法收回数据的状态)。

– Ry Biesemeyer
19年2月7日在18:47

#4 楼

您只需使用

git fetch <repo> <commit>


即可获取远程回购的单个提交,其中,




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

<commit>可以是SHA1提交

,例如

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


获取提交(和丢失的祖先)后,您只需使用

git checkout FETCH_HEAD


签出它,请注意,这将带您进入“头分离”状态。

评论


当我尝试像在此处那样获取特定版本时,git失败,错误代码为1,并且没有输出。这在过去的版本中曾经有用吗? (我是v2.0.2。)

–杰克·奥康纳(Jack O'Connor)
2014年8月1日15:55

编辑:如果我已经在本地进行了提交,那么它确实可以工作,就像我已经完成了完全提取一样,尽管在这种情况下,我不确定用途是什么。

–杰克·奥康纳(Jack O'Connor)
2014年8月1日在16:01

确实,在git 2.0.2中,这似乎对我也不再起作用。 :(

–流程
2014年8月2日在8:52

git checkout FETCH_HEAD会有所帮助。

–lzl124631x
15年5月27日在13:24

此方法不适用于浅层抓取(例如--depth = 1)!

–kingmakerking
18年1月12日在16:06

#5 楼

您可以使用以下命令简单地获取远程仓库:

git fetch <repo>


其中,




<repo>可以是远程仓库名称(例如origin)甚至是远程仓库URL(例如https://git.foo.com/myrepo.git

,例如:

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


合并您想要的提交(因为问题是关于检索一个提交,而是合并,您可以使用cherry-pick来选择一个提交):

git merge <commit>




<commit>可以是SHA1提交

,例如:

git cherry-pick 0a071603d87e0b89738599c160583a19a6d95545




git merge 0a071603d87e0b89738599c160583a19a6d95545


如果是要合并的最新提交,则还可以使用FETCH_HEAD变量:

git cherry-pick (or merge) FETCH_HEAD


评论


这需要在计算机上设置Git帐户。它在测试帐户下不起作用。在测试帐户下,您是否有可以使用的功能?

– jww
17年6月2日在6:26

你是什​​么意思 ?你不能做git fetch吗?

–塞尔吉奥
17年6月2日在10:35

嗯,所以命令将是git config set uploadpack.allowReachableSHA1InWant吗?

–亚历山大·米尔斯(Alexander Mills)
19年5月16日在22:44



#6 楼

最好的方法是:

git fetch origin specific_commit
git checkout -b temp FETCH_HEAD


随便你想要的名字是“ temp” ...尽管这个分支可能被孤立了

评论


显然不支持1.8.x等较旧的git版本

–索林
19年11月7日19:33

#7 楼

终于我找到了一种使用git cherry-pick克隆特定提交的方法。
假设您在本地没有任何存储库,并且要从远程提取特定的提交,

1)创建空本地存储库和git init

2)git remote add origin“库的URL”

3)git fetch origin [这不会将文件移动到本地工作空间,除非您合并]

4)git cherry-pick“ Enter-long-commit-hash-that-ne所需”

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

Enter-long-commit-hash:

您可以使用-> git log --pretty = oneline

#8 楼

我认为'git ls-remote'(http://git-scm.com/docs/git-ls-remote)应该可以满足您的要求。无需力取或拉动。

#9 楼

如果请求的提交在远程仓库的拉取请求中,则可以通过其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


#10 楼

在一个项目中,我们遇到了问题,因此我们不得不恢复到某个提交。我们使用以下命令成功完成了该任务:
git reset --hard <commitID>