有什么方法可以从远程 Git 存储库中只检索一个特定的提交而不在我的 PC 上克隆它?远程仓库的结构和我的完全一样,因此不会有任何冲突,但我不知道怎么做,我不想克隆那个巨大的仓库。
我是git新手,有什么办法吗?
从 Git 版本 2.5+(2015 年第二季度)开始,实际上可以获取单个提交(无需克隆完整的 repo)。
请参阅Fredrik Medley ( )的提交 68ee628,2015年5 月 21 日。(由Junio C Hamano 合并 -- --在提交 a9d3493中,2015 年 6 月 1 日)moroten
gitster
您现在有一个新配置(在服务器端)
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 upload-pack
" that services "git fetch
" 可以被告知为不在任何 ref 顶端的提交提供服务,只要它们可以通过uploadpack.allowReachableSHA1InWant
配置变量从 ref 访问。
注意 SHA 必须是完整的未缩写的 SHA,否则 Git 会声称它找不到提交
完整的文档是:
upload-pack
: 可选地允许获取可达的 sha1
在
uploadpack.allowReachableSHA1InWant
服务器端设置配置选项后,“git fetch
”可以使用“want”行发出请求,该行命名尚未公布的对象(可能已从带外或从子模块指针获得)。
只有从分支提示可到达的对象,即广告分支和被隐藏的分支的并集transfer.hideRefs
,才会被处理。
请注意,必须回溯历史记录以检查可达性会产生相关成本。当获取某个提交的内容时,可以使用此功能,其中 sha1 是已知的,而无需克隆整个存储库,尤其是在使用浅获取的情况下。
有用的案例是例如
- 历史中包含大文件的存储库,
- 仅获取子模块结帐所需的数据,
- 在共享 sha1 而不告诉它属于哪个确切分支以及在 Gerrit 中时,如果您考虑的是提交而不是更改编号。
(Gerrit 案例已经解决,allowTipSHA1InWant
因为每个 Gerrit 更改都有一个参考。)
Git 2.6(2015 年第三季度)将改进该模型。
请参阅Jeff King ( )的提交 2bc31d1和提交 cc118a6(2015 年 7 月 28 日) 。(由Junio C Hamano 合并 -- --在824a0be 提交中,2015 年 8 月 19 日)peff
gitster
refs
: 支持否定transfer.hideRefs
如果您使用配置隐藏参考层次结构
transfer.hideRefs
,则无法稍后覆盖该配置以“取消隐藏”它。
这个补丁实现了一个“负面”隐藏,这会导致匹配立即被标记为未隐藏,即使另一个匹配会隐藏它。
我们注意以与配置机制提供给我们的方式相反的顺序应用匹配项,因为这让我们通常的“最后一个获胜”配置优先级起作用(.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 月)将再次改进:
请参阅提交 948bfa2、提交 00b293e(2015 年 11 月 5 日)、提交 78a766a、提交 92cab49、提交 92cab49、提交 92cab49(2015 年 11 月 3 日)、提交 00b293e、提交 00b293e (2015年11 月 5日)和提交 92cab49、提交92cab49 Lukas Fleischer ( )提交 92cab49(2015 年 11 月 3 日) 。
帮助者:Eric Sunshine ( )。(由Jeff King 合并 -- --在提交 dbba85e中,2015 年 11 月 20 日)lfos
sunshineco
peff
config.txt
hideRefs
: 记录命名空间的语义
目前,对于
transfer.hideRefs
设置命名空间时的行为方式还没有明确的定义。
说明hideRefs
在这种情况下前缀匹配剥离的名称。这就是hideRefs
当前在接收包中处理模式的方式。
hideRefs:添加对匹配完整参考的支持
除了匹配剥离的 ref 之外,现在还可以添加
hideRefs
与完整(未剥离的)ref 匹配的模式。
为了区分剥离匹配和完全匹配,这些新模式必须以抑扬符 (^
) 为前缀。
因此,新文档:
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
作为所谓的“拥有”行进行广告。
为了在剥离之前匹配 refs,^
请在 ref 名称前添加一个。如果组合!
和^
,!
必须首先指定。
R..在评论中提到了 config uploadpack.allowAnySHA1InWant
,它允许upload-pack
接受一个fetch
请求任何对象的请求。(默认为false
)。
请参阅David "novalis" Turner ( )的提交 f8edeaa(2016 年 11 月,Git v2.11.1 ) :novalis
upload-pack
:可选地允许获取任何 sha1
在我们相信用户绝对可以访问存储库中的所有内容的情况下,进行可访问性检查似乎有点愚蠢。
此外,它在分布式系统中很活跃——也许一个服务器发布了一个 ref,但另一台服务器已经强制推送到该 ref,也许这两个 HTTP 请求最终被定向到这些不同的服务器。
使用 Git 2.34(2021 年第四季度),在 ( man ) 的另一侧运行的 " " ( man )git upload-pack
在处理want - ref 请求时忘记考虑 ref 命名空间。git fetch
请参阅Kim Altintop () 的commit 53a66ec、commit 3955140、commit bac01c6(2021 年 8 月 13 日)。(由Junio C Hamano 合并——在提交 1ab13eb中,2021 年 9 月 10 日)kim
gitster
docs
: 阐明 transfer.hideRefs 和命名空间的交互签字人:Kim Altintop
审核人:Jonathan Tan
展开文档中关于命名空间的部分
transfer.hideRefs
,指出 和 之间的细微upload-pack
差别receive-pack
。3955140(“
upload-pack.c
:对待希望引用相对于命名空间”,2021-07-30,Git v2.34.0 -批次 #5中列出的合并)教导拒绝s 隐藏引用,现在提到。 需要澄清的是,隐藏的 ref 的名称在任何时候都不会显示,但它指向的对象 id 可能。upload-pack
want-ref
git config
现在在其手册页中包含:
在与模式匹配之前引用
transfer.hiderefs
。为了在剥离之前匹配 refs,^
请在 ref 名称前添加一个。如果组合!
和^
,!
必须首先指定。
git config
现在在其手册页中包含:
从广告中省略。如果
uploadpack.allowRefInWant
设置,upload-pack
将want-ref refs/heads/master
在协议 v2fetch
命令中视为refs/namespaces/foo/refs/heads/master
不存在。receive-pack
另一方面,仍然会宣传 ref 指向的对象 id 而不会提及其名称(所谓的“.hav
e”行)。
您只克隆一次,因此如果您已经克隆了远程存储库,则从其中提取不会再次下载所有内容。只需指出您要提取的分支,或获取更改并签出您想要的提交。
从新存储库获取带宽非常便宜,因为它只会下载您没有的更改。考虑 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
。
您可以简单地获取远程仓库的单个提交
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 repo:
git pull --rebase <repo> <branch>
允许 git 提取分支的所有代码,然后我去重置我感兴趣的提交。
git reset --hard <commit-hash>
希望这可以帮助。
您可以简单地使用以下方法获取远程仓库:
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 fetch origin specific_commit
git checkout -b temp FETCH_HEAD
将“temp”命名为您想要的任何名称......虽然这个分支可能是孤立的
我认为'git ls-remote'(http://git-scm.com/docs/git-ls-remote)应该做你想做的事。无需强制获取或拉动。
最后,我找到了一种使用git cherry-pick克隆特定提交的方法。假设您在本地没有任何存储库并且您正在从远程提取特定提交,
1)在本地和git init中创建空存储库
2) git remote add origin " url-of-repository "
3) git fetch origin [这不会将您的文件移动到您的本地工作区,除非您合并]
4) git cherry-pick " Enter-long-commit-hash-that-you-need "
完成。这样,您将只在本地拥有来自该特定提交的文件。
你可以使用 -> git log --pretty=oneline
如果请求的提交在远程仓库的拉取请求中,您可以通过其 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>