4

注意:尽管(从已经发生的讨论中)看起来 GIT 实际上并不适合这个用例,但我已经将这个问题开放给赏金以提示更明确的答案,希望来自在 GIT 方面有丰富的经验。原始问题如下。

我有一种情况,我有大量独立的文件。所谓独立,我的意思是每个文件不依赖于它周围文件的存在、不存在或特定状态。一个很好的类比是一个图像目录,我们的工作流程允许独立创建、编辑和删除每个图像,并且在图像上完成的工作与目录中的其他图像无关。

请注意,这种独立性不仅是偶然的,而且对我们的工作流程至关重要。

这些文件中的每一个都将受益于类似 GIT 的工作流程。如果能够跟踪每个文件的更改,让人们在独立的分支中处理每个文件,然后在完成后合并他们的更改,那就太好了(因此,为了我们的类比,想象这些是 SVG 图像,您可能让艺术家绘制图像和翻译文本内容),并从使用 GIT 的其他项目访问文件。

根据我的经验,当您拥有一组都处于特定状态的文件时,GIT 非常棒。例如,当您在达到“Production Release 1.2”状态后提交 GIT 存储库时,每个文件在该提交时共享“Production Release 1.2”状态。

但是我不确定如何应用 GIT 工作流程,或者当每个文件没有也不能共享它周围的文件的状态时是否可行。您可以将每个文件放在其自己的 GIT 存储库中,但这似乎不切实际。

所以,我的问题是:

  1. 我对 GIT 仅适用于相关文件集合的印象是否正确?
  2. 如果不是,那么在逐个文件的基础上使用 GIT 的克隆/分支/合并功能的过程是什么?

更新

作为对iberbeu的回应:并不是我将版本视为XY,而是我将GIT提交视为假设存储库中的所有文件具有相同的版本或提交点(但是您定义了一个版本)。在这种情况下,GIT 存储库中的文件并不完全独立。

这里的问题是,当您使用包含所有独立文件的单个 repo 时,将其克隆到您自己的本地 repo 并开始在分支上工作。此时假定所有文件都属于该分支,即使从我们拥有的工作流程的角度来看,您只在处理一个文件。但是,现在所有这些独立文件都“顺其自然”,承担与您实际要编辑的单个文件关联的修订历史记录。

因此,Joe 可能会创建一个名为“Joe Working on Image 1”的 repo 分支。他的分支有他想要处理的图像 1,以及他不感兴趣的 10,000 个其他图像。

Jane 可能会创建一个名为“Jane working on Image 987”的相同存储库的分支。她的分支有她想要处理的图像 987,以及她不感兴趣的其他 10,000 张图像。

这很好,只要 Joe 和 Jane 不想开始在他们的分支中编辑一些其他图像。但如果他们这样做了,我们就会失去将每个图像作为独立实体进行编辑的概念模型,并且与其他图像隔离编辑。

因此,如果乔在他应该只编辑图像 1 的分支中编辑了图像 2,并将这些更改合并回 repo,我们现在将图像 2 的显式修订历史记录与图像 1 一起编辑。但是图像 1 和 2 应该完全独立。不应该有图像 2 的概念,因为它是与图像 1 一起编辑的。

所以这是问题的症结所在。GIT 是否支持它控制的文件作为独立实体的概念,其修订版与任何其他文件都不相关?或者这只能通过每个文件的单独 git repos 来实现?

更新 2

看起来子模块可能会替代拥有数千个 GIT 存储库。

4

7 回答 7

3

我真的没有看到问题。我认为您将存储库视为对代码(在本例中为文件)进行版本控制的一种方式。虽然这是对的,但这个想法可能会导致您出错,因为这并不意味着您始终以 XY 形式提交版本

我的意思是,您可以将 repo 视为一个时间线,在该时间线中,您具有文件夹内容的不同状态。文件是否相互关联并不重要。

使用 git,您始终可以获取单个文件的旧版本,而无需返回到 repo 的完整状态。

因此,在您的情况下,一个包含多个独立文件的存储库与每个包含一个文件的多个存储库之间没有任何区别。实际上有很大的不同,第一种选择是负担得起的,第二种是不可能处理的。

实际上,一个正常的项目具有完全独立的文件,但它们都属于同一个 repo。

于 2013-03-03T21:59:35.093 回答
2

我使用 CVS,其中每个文件都独立于存储库中的所有其他文件。

作为奖励,这使您可以对某些文件执行“cvs update”,而让其他文件不理会。

当我可能在本地工作区修改了文件,并且还从另一个工作区签入了更改时,这会派上用场。我经常只想同步存储库中已更改的文件,而不想处理可能需要合并的文件。

这导致了一个我称之为 cvs-update-safe 的脚本,它可以快速、轻松地更新任何可以安全更新的文件,同时将其他文件单独留待以后手动处理。

对于任何复杂的东西,我都不是 CVS 的忠实粉丝(我更喜欢 git),但它具有无处不在的优点,并且允许我选择只更新存储库的一部分。

#!/usr/bin/python

# $Id: cvs-update-safe,v 1.1 2007-11-02 19:47:02 falk Exp $

usage = """Like cvs update, but only updates files which will update cleanly.

Usage:  cvs-update-safe [files...]
"""

import sys
import os
import string
import commands

def main():
  cmd = 'cvs -n update ' + string.join(sys.argv[1:], ' ')
  output = commands.getoutput(cmd).split('\n')
  olist = []
  for line in output:
    line = line.split()
    if line[0] is 'U' and len(line) is 2:
      olist.append(line[1])
  if olist:
    cmd = 'cvs update ' + string.join(olist, ' ')
    os.system(cmd)
  else:
    print 'Nothing to update'



if __name__ == "__main__":
  sys.exit(main())
于 2013-03-09T02:41:33.843 回答
2

Git 对您为单个文件创建存储库没有任何问题。

如果您不想为每个文件创建一个存储库并且不需要同时查看其目录中的所有这些文件,则可以从一个空存储库开始并为每个文件创建一个分支。如果您不在这些独立分支之间进行任何合并,它们将保持独立。您仍然可以从特定文件的分支创建新分支并将更改合并回来。

于 2013-03-03T21:17:58.533 回答
2

正如其他人所说,git 可用于许多单文件存储库,尽管它(正如您所指出的)更多地用于管理一组文件。

要管理数千个单文件存储库,Gitslave 工具可能会有所帮助。该工具允许创建一堆存储库,并统一管理它们。一旦你有了你的存储库,你当然可以独立地使用每个存储库,但是 Gitslave 可以很容易地对它们进行组操作,比如推/拉或提交。

恕我直言,这是一个更好的解决方案,因为有许多 git 子模块,因为子模块可能很难使用。

从主页:

Gitslave 创建了一组相关的存储库——一个超级项目存储库和多个从属存储库——所有这些存储库都是同时开发的,并且所有 git 操作都应该在这些存储库上正常运行;所以当你分支时,项目中的每个仓库都会依次分支。同样,当您提交、推送、拉取、合并、标记、签出、状态、日志等时;每个 git 命令将依次在超级项目和所有从存储库上运行。

[...]

Gitslave 不会接管您的存储库。您可以在 gits 克隆存储库内部和私有 git 克隆存储库外部继续使用旧版 git 命令。

于 2013-03-07T09:40:44.020 回答
0

我想,你以错误的问题开始了这个讨论。

这段落:

这些文件中的每一个 [...] 并从使用 GIT 的其他项目访问这些文件。

(特别是:从使用 GIT 的其他项目访问文件)建议,您想要的只是从其他项目访问的存储库集合。

我认为,最好的解决方案是使用子模块。

为每个“文件”设置一个新的存储库。我将它们称为“一个文件存储库”。

在使用“one-file-repo”存储库的项目中定义子模块。

您的“单文件存储库”存储库包含单个文件这一事实并不重要。

“one-file-repo”中的工作是独立的,但不一定限于单个文件。

于 2013-03-06T08:19:16.230 回答
0

您可以使用单个 repo 并使用 git hooks 来强制执行粒度为 1。

客户端预提交钩子将确保提交对单个文件进行更改,并且可选的 prepare-commit-msg 钩子将自动在提交消息前加上文件名。

服务器端预接收挂钩可以强制执行上述操作。

您仍然会遇到最终拥有大量独立分支的信号噪声问题。

于 2013-03-06T00:53:31.073 回答
0

使用单个存储库,您可以选择一次只提交一个文件,为每个文件提供不同的提交消息。但是当您克隆存储库时,您最终仍将下载整个存储库。Git 是一个分布式版本控制系统,这是它的副作用。

您可以为每个文件提供自己的 git 存储库,并使用子模块将它们导入其他 git 存储库。我可以看到管理起来有些痛苦,但是使用 dvcs 的优点是您始终在计算机上拥有存储库的历史记录。

要考虑的另一件事是您可能使用了错误的工具来完成这项工作。SVN 是一个集中的版本控制系统,它允许您检出单个文件(稀疏检出)而不是克隆整个存储库。您可以使用 git-svn 之类的工具来桥接到您现有的 Git 存储库。

无论哪种方式,这都不是一个有趣的过程。每个文件有一个单独的 git repo 可能是最简单的。

于 2013-03-06T21:32:57.073 回答