你不能得到你想要的。你可以得到一些近似值。
Git 存储库由 commits 组成。他们不保存文件——至少不直接保存。 commits 保存文件,但提交本身是存储单元。这就是git log 向您显示提交哈希 ID 的原因:每个都是可用的东西,完全独立。
每个提交都存储一个每个文件的完整快照。您可能认为这会占用大量空间。它会,除了聪明:Git 压缩和重复每个提交中的文件。它们不像常规文件那样存储在您的计算机上。它们是只有 Git 可以读取的特殊形式,实际上没有任何东西(甚至 Git 本身)可以覆盖。
这个只读属性实际上是每个内部 Git 对象的属性。因此,不仅提交中包含的文件是只读的,提交本身也是只读的。 Git 以多种方式利用了这一点。特别是,标识每个提交的哈希 ID 对于那个特定的提交是唯一的,并且由提交内容的加密校验和组成。这意味着任何两个实现 Git 传输协议的软件都可以相互连接,然后一个可以实际上对另一个说:我已经提交 _____(用哈希 ID 填写空白) ,你喜欢吗?另一个 Git 可以通过检查哈希 ID 来判断它是否有 那个 提交。如果它确实有那个提交,它有每个文件。
不仅如此,在除了 shallow 存储库之外的所有存储库中,如果潜在接收者有 that 提交,它也有 every early commit 和发件人现在完成了:没有什么要发送了。如果接收方没有该提交,则发送方有义务提供该提交的父提交。这种情况一直持续到发送方提供了所有提交,或者发送方和接收方达到了共享提交点。这就是发送者和接收者如何通过交换一些哈希 ID 来协商最小的文件集和提交发送。
无论如何,这一切的重点是发送者发送——接收者接收——整个提交。文件去重技巧意味着发送者知道接收者是否已经有一些文件,因为发送者知道接收者有哪些提交,并且那些提交(发送者也有)有文件哈希其中的 ID。所以发送者只需要发送任何 new 提交和 new 文件,接收者会根据需要自动使用重复的文件来填写新收到的提交。这是一个非常聪明的系统,但它从根本上取决于这个散列系统以及提交永远不会改变并且存储库只交换整个提交的想法。1
这对你意味着什么是git push 发送了一些提交,然后就是这样。您不能将提交的部分发送到其他地方。每个提交都包含每个文件的完整快照。发送包含较少文件的提交的唯一方法是...进行包含较少文件的提交。
有一些工具可以做到这一点,例如git-subtree。当前未维护子树代码。请参阅When to use git subtree? 如果我正在考虑使用它,我会担心缺乏维护。
另一个维护的工具是Git的子模块。这些在同一个链接的 SO 问题中进行了简单描述,但基本上子模块是一种说法,在一个 Git 存储库中:克隆另一个 Git 存储库,到我将使用的工作树中的子目录中。 一旦你的 Git 将另一个 Git 存储库克隆到该位置,你的 Git 在子模块中使用 分离的 HEAD 模式将该子模块保留在一个特定的提交中in其他 Git 存储库。
这种设置有点僵硬和脆弱,并不能让许多用户满意。2虽然它确实工作,但它可以解决实际问题。将其视为一种选择。
1最近有人故意用 Git 所谓的部分克隆来削弱这个系统,但它们还没有真正准备好用于日常使用。将弱化视为一种叠叠乐游戏,我们在其中抽出一些坚固的结构以使一切变得更轻。如果我们拔错了,整个事情就会崩溃:哎呀!
2我个人得出的结论是子模块是错误的,并且我有一些关于如何“正确”执行它们的想法,但是这些想法还有很长的路要走以任何可用代码的形式实现。