是否可以在Git和Mercurial中仅克隆一个分支(或来自给定的提交)?我的意思是,我想要克隆一个中央回购,但由于它很庞大,我只想获得它的一部分,并且仍能够回馈我的变化。可能吗?比如,我只想从Tag 130开始或类似的东西?
若然,怎么样?
答案 0 :(得分:75)
在Git中你谈论的是三种不同类型的部分克隆:
浅层克隆: 我想要修订点X以后的历史记录。
使用git clone --depth <n> <url>
,但请记住,浅克隆在与其他存储库交互方面有些限制。您将能够生成补丁并通过电子邮件发送。
按文件路径进行部分克隆: 我希望在某个目录/path
中包含所有修订历史记录。
不可能。使用现代Git,你可以拥有稀疏结账,即你有完整的历史记录,但你只能查看(在工作区域内)所有文件的子集。
仅克隆选定的分支: 我想只克隆一个分支(或选定的分支子集)。
可能,
在git 1.7.10之前并不简单:你需要手动完成克隆的工作,即git init [<directory>]
,然后git remote add origin <url>
,编辑.git/config
替换*
in {{ 1}}通过请求的分支(可能是'master'),然后是remote.origin.fetch
。
as of git 1.7.10 git fetch
提供了--single-branch
选项,似乎只是为了这个目的而添加的,看起来很简单。
但请注意,由于分支通常共享其大部分历史记录,因此仅克隆分支子集的收益可能比您想象的要小。
您也可以仅对选定的分支子集进行浅层克隆。
如果您知道人们希望如何通过文件路径(同一存储库中的多个项目)来解决问题,您可以使用子模块(类似于svn:externals)将repo预分割为单独的可复制部分。
答案 1 :(得分:49)
在善变的土地上,你谈论的是三种不同类型的部分克隆:
hg help sparse
)。如果您知道人们希望如何通过文件路径解决问题(同一个仓库中的多个项目(羞辱你)),您可以使用子存储库(类似于svn externals)将repo预拆分为可单独克隆的部分
另外,关于“如此巨大,我只想得到它的一部分”:你真的只需要这样做一次。只是在你吃午饭时克隆它,然后你永远拥有它。随后你可以pull
并有效地继续前进。如果你想要它的另一个克隆,只需克隆你的第一个克隆。你得到一个克隆并不重要(本地克隆不占用额外的磁盘空间,因为它们是封面下的硬链接)。
答案 2 :(得分:9)
所选答案提供了一个很好的概述,但缺少一个完整的例子。
git clone --no-checkout --depth 1 --single-branch --branch (name) (repo) (folder)
cd (folder)
git config core.sparseCheckout true
echo "target/path/1" >>.git/info/sparse-checkout
echo "target/path/2" >>.git/info/sparse-checkout
git checkout
定期优化本地存储库占用空间 (c) (可选,小心使用):
git clean --dry-run # consider and tweak results then switch to --force
git gc
git repack -Ad
git prune
答案 3 :(得分:5)
此方法创建一个没有子存储库的无版本存档:
hg clone -U ssh://machine//directory/path/to/repo/project projecttemp
cd projecttemp
hg archive -r tip ../project-no-subrepos
没有子存储库的无版本源代码位于project-no-subrepos目录中
答案 4 :(得分:2)
关于Git,Linus Torvalds可能具有历史意义,从2007年的概念角度回答了这个问题,这个问题已被记录并可在线获取。
问题是,是否可以仅从Git存储库中检出一些文件。
Tech Talk: Linus Torvalds on git t=43:10
总而言之,他说Git的设计决策之一是将其与其他源管理系统区分开来(他引用BitKeeper和SVN)是Git管理内容而不是文件。其含义是,例如通过首先获取整个差异然后仅将其修剪到所请求的文件来计算两个修订中的文件子集的差异。另一个是你必须查看整个历史;以一种全有或全无的方式。出于这个原因,他建议在多个存储库之间拆分松散相关的组件,并提到当时正在努力实现用于管理存储库的用户界面,该存储库被构造为包含较小存储库的超级项目。
据我所知,这个基本的设计决定今天仍然是苹果。超级项目的东西可能变成现在的submodules。
答案 5 :(得分:0)
如果,如在 Brent Bradburn'answer 中,您在 Git 部分克隆中重新打包,请确保:
read-tree
, not checkout
;git clone --filter=blob:none --no-checkout https://github.com/me/myRepo
cd myRepo
git sparse-checkout init
# Add the expected pattern, to include just a subfolder without top files:
git sparse-checkout set /mySubFolder/
# populate working-tree with only the right files:
git read-tree -mu HEAD
关于部分克隆中的局部优化,如:
git clean --dry-run # consider and tweak results then switch to --force
git gc
git repack -Ad
git prune
使用 Git 2.32(2021 年第二季度),其中部分克隆中的“git repack -A -d
”(man) 在 2.32 之前不必要地松开了承诺包中的对象:已修复。 >
请参阅 commit a643157 的 Rafael Silva (raffs
)(2021 年 4 月 21 日)。
(2021 年 5 月 10 日于 Junio C Hamano -- gitster
-- 被 commit a0f521b 合并)
repack
:避免松散部分克隆中的承诺对象报告人:SZEDER Gábor
帮助:Jeff King
帮助:Jonathan Tan
签字人:拉斐尔席尔瓦
当 git repack -A -d
(man) 在部分克隆中运行时,pack-objects
被调用两次:一次重新打包所有承诺对象,一次重新打包所有非承诺对象。
后一个 pack-objects
调用与 --exclude-promisor-objects
和 --unpack-unreachable
一起使用,这会释放此调用期间未使用的所有对象。
不幸的是,这包括承诺对象。
因为 git repack
(man) 的 -d
参数随后删除了包中的所有松散对象,所以这些刚刚松散的承诺对象将被立即删除.
但是,这种额外的磁盘变动首先是不必要的。
例如,在过滤所有 blob 对象(例如 --filter=blob:none
)的新克隆部分存储库中,repack
最终解包所有树并提交到文件系统中,因为在这种特殊情况下,每个对象都是一个允诺对象。
根据存储库大小,这会显着增加磁盘使用量:在我的 linux.git 副本中,对象目录的磁盘使用量达到了 26GB 的峰值。
为了避免这种额外的磁盘变动,将承诺包文件的名称作为 --keep-pack
参数传递给 pack-objects
的第二次调用。
这会通知 pack-objects
,promisor 对象已经在一个安全的包文件中,因此不需要松开。
为了测试,我们需要验证是否有任何物体被松开。
但是,“证据”(松散的对象)在此过程中被删除,从而阻止我们检查对象目录。
相反,让我们教 pack-objects
计算松动的对象并通过 trace2 发出,从而允许在进程完成后检查调试事件。
这个新事件用于添加的回归测试。
最后,添加一个新的性能测试来评估此更改对性能的影响(在 git.git 上测试):
Test HEAD^ HEAD
----------------------------------------------------------
5600.3: gc 134.38(41.93+90.95) 7.80(6.72+1.35) -94.2%
对于更大的存储库,例如 linux.git,改进更大:
Test HEAD^ HEAD
-------------------------------------------------------------------
5600.3: gc 6833.00(918.07+3162.74) 268.79(227.02+39.18) -96.1%
这些改进特别重要,因为新克隆的部分存储库中的每个对象都是一个承诺对象。
答案 6 :(得分:-1)
在mercurial中,您应该可以使用以下方法:
hg convert --banchmap FILE SOURCEDEST REVMAP
您可能还需要:
--config convert.hg.startrev=REV
源可以是git,mercurial或其他各种系统。
我没有尝试过,但转换非常丰富。