从远程Git存储库中检索特定提交

Var*_*tre 178 git git-fetch

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

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

Von*_*onC 103

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

提交68ee628弗雷德里克混合泳(moroten),5月21日2015年
(由合并JUNIOÇ滨野- gitster-提交a9d3493,2015年6月1日)

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

uploadpack.allowReachableSHA1InWant
Run Code Online (Sandbox Code Playgroud)

允许upload-pack接受获取请求,该请求请求可从任何ref tip访问的对象.但是,请注意,计算对象可达性在计算上是昂贵的.
默认为false.

如果将服务器端配置与浅克隆(git fetch --depth=1)结合使用,则可以请求单个提交(请参阅t/t5516-fetch-push.sh:

git fetch --depth=1 ../testrepo/.git $SHA1
Run Code Online (Sandbox Code Playgroud)

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

git cat-file commit $SHA1
Run Code Online (Sandbox Code Playgroud)

" git upload-pack"服务" git fetch"可以被告知服务于不在任何引用的尖端的提交,只要它们可以从具有uploadpack.allowReachableSHA1InWant 配置变量的ref到达.


完整的文档是:

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

通过uploadpack.allowReachableSHA1InWant在服务器端设置配置选项," git fetch"可以使用"want"行创建一个请求,该行命名一个尚未公布的对象(可能是在带外或从子模块指针获得的).
只处理从分支提示可到达的对象,即广告分支和隐藏的分支的并集transfer.hideRefs.
请注意,必须返回历史记录以检查可达性的相关成本.

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

有用的例子是例如

  • 包含历史记录中的大文件的存储库,
  • 仅获取子模块结帐所需的数据,
  • 当共享一个sha1而不告诉它属于哪个精确的分支时,如果你在提交而不是改变数字的情况下考虑.
    (Gerrit案例已经解决,allowTipSHA1InWant因为每个Gerrit变更都有一个参考.)

Git 2.6(2015年第3季度)将改进该模型.
请参阅提交2bc31d1,提交cc118a6(2015年7月28日)作者:Jeff King(peff).
(由Junio C gitsterHamano合并- -提交824a0be,2015年8月19日)

refs:支持否定 transfer.hideRefs

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

所以你现在可以这样做:

git config --system transfer.hideRefs refs/secret
git config transfer.hideRefs '!refs/secret/not-so-secret'
Run Code Online (Sandbox Code Playgroud)

隐藏refs/secret在所有回购中,除了一个特定回购中的一个公共位.


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

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

config.txt:记录hideRefswith namespaces 的语义

目前,没有明确的定义在transfer.hideRefs设置命名空间时应该如何表现.在这种情况下,
解释hideRefs前缀匹配剥离的名称.这就是hideRefs当前在receive-pack中处理模式的方式.

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

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

因此新的文件:

transfer.hideRefs:
Run Code Online (Sandbox Code Playgroud)

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


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

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

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

在我们信任用户完全访问存储库中的所有内容的情况下,进行重新检查似乎有点愚蠢.

此外,它在分布式系统中很活跃 - 也许一个服务器通告一个ref,但是另一个服务器已经强制推送到该ref,并且可能两个HTTP请求最终被定向到这些不同的服务器.

  • 您能否提供一个更完整的示例,说明如何使用此单一提交创建repo克隆?我试过但失败了..谢谢! (4认同)
  • @LarsBilke我们正在谈论克隆或拉动这里,而不是推.而且我很确定GitHub在服务器端没有Git 2.5. (2认同)
  • 现在更好的是,有 `uploadpack.allowAnySHA1InWant` 没有可达性计算惩罚(和 DoS 向量)。 (2认同)

Cha*_*esB 95

您只能克隆一次,因此如果您已经拥有远程存储库的克隆,则从中删除它将不会再次下载所有内容.只需指出要提取的分支,或者获取更改并签出所需的提交.

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

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


但是,为了减少下载大小,您可以要求git仅获取与特定分支或提交相关的对象:

git fetch origin refs/heads/branch:refs/remotes/origin/branch
Run Code Online (Sandbox Code Playgroud)

这将仅下载远程分支中包含的提交branch (并且仅下载您错过的提交),并将其存储在其中origin/branch.然后,您可以合并或结帐.

您还可以仅指定SHA1提交:

git fetch origin 96de5297df870:refs/remotes/origin/foo-commit
Run Code Online (Sandbox Code Playgroud)

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

  • 现在这已经过时了.我们都有能力执行[浅克隆](http://stackoverflow.com/questions/1778088/how-to-clone-a-single-branch-in-git),以及[获取单个提交](http://stackoverflow.com/a/30701724/1055489).现在允许Shallow克隆正常推送和获取,而不必知道项目的完整历史记录,因此如果没有它的祖先,提交不能单独存在就不再正确了.在初始克隆之后你对提取的看法是非常正确的,但我们也有更便宜的选择. (8认同)
  • 最后一个命令(使用SHA1提交)对我不起作用.该命令默默地执行"某事"一段时间,然后退出,没有消息或明显的副作用. (6认同)
  • 看起来你对克隆意味着什么感到困惑.从远程仓库获取更改时,如果没有克隆它,则只需在历史记录中获取提交.然后,您可以选择要签出的提交,或将其合并到历史记录中 (3认同)
  • 它仍然使用 git fetch 下载大量数据(430mb)。所需的提交只有几 kbs。真的没有特殊的命令可以做到这一点吗?如果我想删除 'git fetched' 存储库怎么办?它存储在哪里? (2认同)
  • `git fetch origin` 仅适用于**未缩写的**哈希。使用 gerrit Remote 在 Ubuntu 18.04 上进行了测试。 (2认同)

小智 60

我对我的git repo做了一个拉动:

git pull --rebase <repo> <branch>
Run Code Online (Sandbox Code Playgroud)

允许git拉入分支的所有代码然后我去重置到我感兴趣的提交.

git reset --hard <commit-hash>

希望这可以帮助.

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

Flo*_*low 48

您只需使用即可获取远程仓库的单个提交

git fetch <repo> <commit>
Run Code Online (Sandbox Code Playgroud)

哪里,

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

例如

git fetch https://git.foo.com/myrepo.git 0a071603d87e0b89738599c160583a19a6d95545
Run Code Online (Sandbox Code Playgroud)

在您获取提交(和缺少的祖先)之后,您只需将其签出即可

git checkout FETCH_HEAD
Run Code Online (Sandbox Code Playgroud)

请注意,这将使您处于"独立头"状态.

  • 当我尝试像你那样"获取"一个特定的转速时,git失败,错误代码为1,没有输出.这是过去版本中常用的东西吗?(我是v2.0.2.) (10认同)
  • 编辑:如果我已经在本地进行了提交,那么它确实可以工作,就像我已经完成了一个完整的“提取”操作一样,尽管在这种情况下我不确定其用途。 (2认同)
  • 确实,在git 2.0.2中,这似乎对我也不再起作用。:( (2认同)
  • git checkout FETCH_HEAD可以帮助。 (2认同)
  • 这种方法不适用于浅取(例如`--depth=1`)! (2认同)

Sér*_*gio 16

您只需使用以下命令获取远程仓库即可:

git fetch <repo>
Run Code Online (Sandbox Code Playgroud)

哪里,

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

例如:

git fetch https://git.foo.com/myrepo.git 
Run Code Online (Sandbox Code Playgroud)

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

git merge <commit>
Run Code Online (Sandbox Code Playgroud)
  • <commit> 可以是SHA1提交

例如:

git cherry-pick 0a071603d87e0b89738599c160583a19a6d95545
Run Code Online (Sandbox Code Playgroud)

要么

git merge 0a071603d87e0b89738599c160583a19a6d95545
Run Code Online (Sandbox Code Playgroud)

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

git cherry-pick (or merge) FETCH_HEAD
Run Code Online (Sandbox Code Playgroud)


Ale*_*lls 5

这效果最好:

git fetch origin specific_commit
git checkout -b temp FETCH_HEAD
Run Code Online (Sandbox Code Playgroud)

随意命名“temp”......不过这个分支可能是孤立的