Git中的文件限制是多少(数量和大小)?

Ale*_*ker 170 git

有谁知道文件数量和文件大小的Git限制是什么?

Von*_*onC 157

来自Linus本人的这条消息可以帮助您解决其他一些限制

[...] CVS,即它真的最终面向"一次一个文件"模型.

这很好,因为你可以有一百万个文件,然后只查看其中一些文件 - 你甚至都看不到其他999,995文件的影响.

从根本上说,Git从来没有真正看过不到整个回购.即使你稍微限制一些事情(即只检查一部分,或者让历史记录稍微回顾一下),git最终仍然关心整个事情,并传授知识.

因此,如果你强迫它将一切看作一个巨大的存储库,那么git会非常糟糕 .虽然我们可以改进它,但我不认为这部分是可以修复的.

是的,然后是"大文件"问题.我真的不知道如何处理大文件.我知道,我们很害羞.

在我的另一个答案中看到更多:Git的限制是每个存储库必须代表一个" 连贯的文件集 ","所有系统"本身(你不能标记"存储库的一部分").
如果您的系统由自主(但相互依赖)的部件组成,则必须使用子模块.

Talljoe的回答所示,限制可以是系统(大量文件),但是如果你确实理解Git的性质(关于由SHA-1键表示的数据一致性),你将意识到真正的"限制"是一个用法:即,您不应该尝试将所有内容存储在Git存储库中,除非您准备好总是获取或标记所有内容.对于一些大型项目来说,没有任何意义.


有关git限制的更深入了解,请参阅" git with large files "
(其中提到了git-lfs:一种在git repo之外存储大文件的解决方案.GitHub,2015年4月)

限制git repo的三个问题:

  • 大文件(文件xdelta仅在内存中,对大文件不好)
  • 大量的文件,这意味着,每个blob一个文件,慢git gc一次生成一个packfile.
  • large packfiles,packfile索引无法从(巨大的)packfile中检索数据.

最近的一个主题(2015年2月)说明了Git仓库的限制因素:

来自中央服务器的一些同时克隆是否会减慢其他用户的其他并发操作?

克隆时服务器中没有锁,因此理论上克隆不会影响其他操作.克隆虽然可以使用大量内存(以及大量的cpu,除非你打开可达性位图功能,你应该这样做).

git pull慢吗?

如果我们排除服务器端,树的大小是主要因素,但你的25k文件应该没问题(linux有48k文件).

' git push'?

这个不受你的回购历史有多深,或你的树有多宽的影响,所以应该很快..

啊参考的数量可能会影响git-pushgit-pull.
我认为Stefan在这方面比我更清楚.

' git commit'?(它在参考文献3中列为慢速.)' git status'?(参考文献3再次放慢,虽然我没有看到它.)
(另外git-add)

再次,你的树的大小.按照您的回购协议的规模,我认为您不必担心它.

有些操作似乎不是日常的,但如果它们经常被Web前端调用到GitLab/Stash/GitHub等,那么它们就会成为瓶颈.(例如' git branch --contains'似乎受到大量分支的极大不利影响.)

git-blame 当文件被大量修改时可能会很慢.

  • @ Thr4wn:有关GitPro子模块页面的更多信息,另请参阅http://stackoverflow.com/questions/1979167/git-submodule-update/1979194#1979194.对于较短的版本:http://stackoverflow.com/questions/2065559/using-two-git-repos-in-one-folder/2065749#2065749 (4认同)

Tal*_*joe 32

没有实际限制 - 所有内容都以160位名称命名.文件的大小必须以64位数字表示,因此也没有实际限制.

但是有一个实际的限制.我有一个大约8GB的存储库,大于880,000,git gc需要一段时间.工作树相当大,因此检查整个工作目录的操作需要相当长的时间.这个repo仅用于数据存储,所以它只是一堆处理它的自动化工具.从repo中提取更改比使用相同的数据快得多.

%find . -type f | wc -l
791887
%time git add .
git add .  6.48s user 13.53s system 55% cpu 36.121 total
%time git status
# On branch master
nothing to commit (working directory clean)
git status  0.00s user 0.01s system 0% cpu 47.169 total
%du -sh .
29G     .
%cd .git
%du -sh .
7.9G    .
Run Code Online (Sandbox Code Playgroud)

  • 虽然上面有一个“更正确”的答案谈论理论限制,但这个答案似乎对我更有帮助,因为它允许将自己的情况与您的情况进行比较。谢谢。 (2认同)
  • @bluenote10 `.git` 目录中的内容被压缩。因此,提交相对较少的存储库可能比未压缩的工作目录具有更小的压缩历史记录。我的经验表明,在实践中,对于 C++ 代码,整个历史记录通常与工作目录的大小大致相同。 (2认同)

Bri*_*ton 28

如果你添加太大的文件(在我的情况下是GB,Cygwin,XP,3 GB RAM),那么期待这个.

致命:内存不足,malloc失败了

更多细节在这里

更新3/2/11:使用Tortoise Git在Windows 7 x64中看到类似的内容.使用大量内存,系统响应非常慢.


Cha*_*esB 17

早在2012年2月,来自Joshua Redstone 的Git邮件列表中就有一个非常有趣的帖子,这是一个Facebook软件工程师在一个巨大的测试库上测试Git:

测试repo有400万次提交,线性历史和大约130万个文件.

运行的测试显示,对于这样的回购,Git是无法使用的(冷操作持续几分钟),但这可能在将来发生变化.基本上,性能受到stat()内核FS模块调用次数的影响,因此它将取决于repo中的文件数量和FS缓存效率.另见本要点以供进一步讨论.

  • +1有趣.这回应了[我自己关于git限制的答案](http://stackoverflow.com/a/19494211/6309),详细说明了对大文件/文件/包文件数量的限制. (2认同)

Gab*_*les 5

截至 2023 年,我的经验法则是尝试使您的存储库总文件数(文件 + 目录)< 524288 个,也许几百 GB ...但它只为我提供了107 GB210 万(210 万)个文件

524288 数字似乎是 Linux 一次可以跟踪更改的最大索引节点数(通过“索引节点监视”),我认为这就是通过索引节点通知git status或其他方式快速找到已更改文件的速度。更新:来自@VonC,如下

当您收到有关没有足够inotify监视的警告时,这是因为存储库中的文件数量已超出当前inotify限制。增加限制允许inotify(以及扩展,Git)跟踪更多文件。然而,这并不意味着 Git 不会在超出此限制的情况下工作:如果达到限制,git status或者git add -A不会“错过”更改。相反,这些操作可能会变得更慢,因为 Git 需要手动检查更改,而不是从 inotify 机制获取更新。

因此,您可以超过 524288 个文件(我下面的存储库是 210 万个文件),但速度会变慢。

我的实验:

我刚刚将2095789 (~2.1M) 个文件(包括~107 GB)添加到一个新的存储库中。这些数据基本上只是一块 300 MB 的代码和构建数据,多年来重复了数百次,每个新文件夹都是之前文件夹的稍微更改的版本。

Git 做到了,但它不喜欢这样。我使用的是一台非常高端的笔记本电脑(20 核,快速,Dell Precision 5570 笔记本电脑,64 GB RAM,高速真实世界 3500 MB/秒 m.2 2 TB SSD),运行 Linux Ubuntu 22.04.2,这是我的结果:

  1. git --version显示git version 2.34.1.

  2. git init是即时的。

  3. time git add -A耗时 17 分 37 秒 621 秒。

  4. time git commit花了大约 11 分钟,因为它显然必须运行git gc来打包东西。

    1. 我建议time git commit -m "Add all files"改为使用,以避免文本编辑器打开 210 万行文件。按照我的说明, Sublime Text 被设置为我的 git 编辑器,它处理得很好,但需要几秒钟才能打开,而且它没有像通常那样的语法突出显示。

    2. 当我的提交编辑器仍然打开并且我正在输入提交消息时,我看到了这个 GUI 弹出窗口:

      在此输入图像描述

      文本:

      您的系统没有配置足够的 inotify 监视,这意味着我们将无法跟踪文件系统更改,并且某些功能可能无法工作。我们可以尝试为您将限制从 65536 增加到 524288。这需要 root 权限。
      错误:授权失败

      因此,我单击“更改限制”并输入我的 root 密码。

      这似乎表明,如果您的存储库有超过 524288 (~500k) 个文件和文件夹,那么 git 不能保证注意到更改的文件git status,不是吗?

    3. 我的提交编辑器关闭后,以下是我的计算机在提交和打包数据时所考虑的内容:

      请注意,我的基准 RAM 使用量约为 17 GB,因此我猜测此 RAM 使用量中只有约 10 GB 来自git gc. 实际上,“目测”下面的内存图显示我的 RAM 使用量从提交前的约 25% 上升到提交期间的峰值约 53%,总使用量约为 53-23 = 28% x 67.1 GB = 18.79 GB内存使用情况。

      这是有道理的,因为事实上,我看到我的主包文件是 10.2 GB,在这里:.git/objects/pack/pack-0eef596af0bd00e16a9ba77058e574c23280e28f.pack因此,从逻辑上讲,至少需要那么多内存才能将该文件加载到 RAM 中并使用它来打包它。

      在此输入图像描述

    4. 这是 git 打印到屏幕上的内容:

      $ time git commit
      Auto packing the repository in background for optimum performance.
      See "git help gc" for manual housekeeping.
      
      Run Code Online (Sandbox Code Playgroud)

      大约需要11分钟才能完成。

  5. time git status现在已经干净了,但是大约需要2~3秒。有时它会打印出一条正常的消息,如下所示:

    $ time git status
    On branch main
    nothing to commit, working tree clean
    
    real    0m2.651s
    user    0m1.558s
    sys 0m7.365s
    
    Run Code Online (Sandbox Code Playgroud)

    有时它会打印出其他类似警告/通知消息的内容:

    $ time git status
    On branch main
    
    It took 2.01 seconds to enumerate untracked files. 'status -uno'
    may speed it up, but you have to be careful not to forget to add
    new files yourself (see 'git help status').
    nothing to commit, working tree clean
    
    real    0m3.075s
    user    0m1.611s
    sys 0m7.443s
    
    Run Code Online (Sandbox Code Playgroud)

    ^^^ 我猜这就是@VonC 在他的评论中所说的内容,我把它放在这个答案的最上面:因为我没有足够的“inode 手表”来一次跟踪所有文件,所以需要更长的时间。

  6. 压缩效果非常好,如下du -sh .git所示:

    $ du -sh .git
    11G .git
    
    Run Code Online (Sandbox Code Playgroud)

    因此,.git包含所有内容(所有 210 万个文件和 107 GB 数据)的目录仅占用 11 GB。

    Git 确实尝试消除重复文件之间的重复数据(请参阅此处我的答案),所以这很好。

    再次运行git gc大约需要 43 秒,并且对我的目录大小没有额外影响.git,可能是因为我的存储库只有 1 个提交,并且它只是在几分钟前第一次运行git gc时运行。git commit有关输出,请参阅上面我的答案。

    总目录大小:活动文件系统 + .gitdir,为 123 GB:

    $ time du -sh
    123G    .
    
    real    0m2.072s
    user    0m0.274s
    sys 0m1.781s
    
    Run Code Online (Sandbox Code Playgroud)
  7. 这是我的 SSD 的速度。这就是为什么只花了 11 分钟的部分git gc原因(其余的是我的 CPU):

    Gnome 磁盘速度基准显示读取速度为 3.5 GB/s。我预计写入速度约为 75%:

    在此输入图像描述

    我相信,上述测试是在块级别进行的,低于文件系统级别。我预计文件系统级别的读取和写入速度是上述速度的 1/10(与块级别的速度从 1/5 到 1/20 不等)。

我在 git 中的实际数据测试到此结束。我建议您坚持使用< 500k 文件。至于尺寸,我不知道。只要您的文件数量接近 50 万个文件或更少,您也许可以选择 50 GB、2 TB 或 10 TB。

更进一步:

1. 通过我的 11 GB.git目录向某人提供我的 107 GB 存储库

现在 git 已经将我的 107 GB 的 2.1M 文件压缩到一个 11 GB 的.git目录中,我可以轻松地重新创建或与我的同事共享这个.git目录,为他们提供整个存储库!不要复制整个 123 GB 的存储库目录。相反,如果您的存储库被调用my_repo,只需my_repo在外部驱动器上创建一个空目录,将目录复制.git到其中,然后将其交给同事即可。他们将其复制到计算机上,然后在存储库中重新实例化整个工作树,如下所示:

cd path/to/my_repo

# Unpack the whole working tree from the compressed .git dir.
# - WARNING: this permanently erases any changes not committed, so you better 
#   not have any uncommitted changes lying around when using `--hard`!
time git reset --hard
Run Code Online (Sandbox Code Playgroud)

对我来说,在同一台高端计算机上,time git reset --hard解包命令花费了7 分 32 秒,并且git status再次干净了。

如果.git目录被压缩在.tar.xz文件中my_repo.tar.xz,则说明可能如下所示:

如何my_repo从 恢复整个 107 GB 存储库my_repo.tar.xz,其中仅包含 11 GB.git目录:

# Extract the archive (which just contains a .git dir)
mkdir -p my_repo
time tar -xf my_repo.tar.xz --directory my_repo

# In a **separate** terminal, watch the extraction progress by watching the
# output folder grow up to ~11 GB with:
watch -n 1 'du -sh my_repo'

# Now, have git unpack the entire repo
cd my_repo
time git status | wc -l  # Takes ~4 seconds on a high-end machine, and shows 
                         # that there are 1926587 files to recover.
time git reset --hard    # Will unpack the entire repo from the .git dir!; 
                         # takes about 8 minutes on a high-end machine.
Run Code Online (Sandbox Code Playgroud)

2. 比较复制的文件夹修订之间的更改meld

做这个:

meld path/to/code_dir_rev1 path/to/code_dir_rev2
Run Code Online (Sandbox Code Playgroud)

Meld 打开文件夹比较视图,就像您在文件资源管理器中一样。更改的文件夹和文件将被着色。向下单击进入文件夹,然后单击更改的文件,即可打开文件并排比较视图以查看更改。Meld 在新选项卡中打开它。完成后关闭选项卡,然后返回到文件夹视图。找到另一个已更改的文件,然后重复。这使我能够快速比较这些已更改的文件夹修订版本,而无需先将它们手动输入到线性 git 历史记录中,就像它们本来应该放在首位一样。

也可以看看:

  1. 我的答案:如何dos2unix使用多个进程在所需的目录或路径上递归运行(或任何其他命令)
  2. git 会消除文件之间的重复吗?
    1. 我的答案
  3. Microsoft 的 Brian Harry 谈“地球上最大的 Git 存储库” - 微软显然拥有一个巨大的300 GB mono-repo,其中包含350 万个文件,其中包含几乎所有代码。(我不想成为一名远程工作者并尝试做到这一点......)
  4. @VonC 关于提交图链,以及 git 的速度如何


归档时间:

查看次数:

106699 次

最近记录:

6 年,3 月 前