代码之家  ›  专栏  ›  技术社区  ›  Boris Guéry

如何编写一个简单的版本控制系统?

  •  22
  • Boris Guéry  · 技术社区  · 16 年前

    我想做一个简单的版本控制系统,但我不知道如何构造数据和代码。

    下面是一个简短的例子:

    1. 用户登录
    2. 用户在上载文件时有两个选项:
      • 提交新文件
      • 提交文件的新版本

    树最多只能有两个级别:

    |
    |--File_A_0
     \--File_A_1
     \--File_A_2
     \--File_A_3
     \--File_A_4
    

    还有两种类型的文件,一种是最终版本(即最新批准的版本),另一种是草稿版本(即最新上传的文件) 该文件将物理存储在服务器上。 每个文件都由一个(或多个)用户拥有,并且只有一个组。

    组表示一组文档,文档一次只能由一个组拥有。用户不依赖于组。

    开始编辑:

    id_article | relative_group_id | id_group | title | submited | date | abstract | reference | draft_version | count | status
    
    id_draft | id_file | version | date
    

    但这很难管理,很难扩展。 我想这是因为这个团体的参数。。。

    结束编辑

    因此,问题是:

    • 如何对数据库进行模式化?
    • 什么样的信息应该是有用的
    • 这是一个什么样的结构
    • 你有什么建议和提示 做这种工作?

    13 回复  |  直到 15 年前
        1
  •  50
  •   Michael Dorfman    15 年前

    看在上帝的份上, 不要 . 你真的不想走这条路。

    停下来想一想大局。您希望保留文档的早期版本,这意味着在某个时候,有人会希望看到一些早期版本,对吗?然后他们会问, “第三版和第七版有什么不同?”? 然后他们会说,

    版本控制是非常重要的,不需要重新发明轮子——有很多可行的版本控制系统,其中一些甚至是免费的。

    从长远来看,学习其中一个系统的API,编写一个web前端代码,为用户提供他们正在寻找的功能子集(现在)会容易得多

        2
  •  18
  •   glmxndr    15 年前

    there .


    关于你的评论:

    对于数据库结构,您可以尝试这种结构(MySQL sql):

    CREATE TABLE `Users` (
           `UserID` INT NOT NULL AUTO_INCREMENT
         , `UserName` CHAR(50) NOT NULL
         , `UserLogin` CHAR(20) NOT NULL
         , PRIMARY KEY (`UserID`)
    );
    
    CREATE TABLE `Groups` (
           `GroupID` INT NOT NULL AUTO_INCREMENT
         , `GroupName` CHAR(20) NOT NULL
         , PRIMARY KEY (`GroupID`)
    );
    
    CREATE TABLE `Documents` (
           `DocID` INT NOT NULL AUTO_INCREMENT
         , `GroupID` INT NOT NULL
         , `DocName` CHAR(50) NOT NULL
         , `DocDateCreated` DATETIME NOT NULL
         , PRIMARY KEY (`DocID`)
         , INDEX (`GroupID`)
         , CONSTRAINT `FK_Documents_1` FOREIGN KEY (`GroupID`)
                      REFERENCES `Groups` (`GroupID`)
    );
    
    CREATE TABLE `Revisions` (
           `RevID` INT NOT NULL AUTO_INCREMENT
         , `DocID` INT
         , `RevUserFileName` CHAR(30) NOT NULL
         , `RevServerFilePath` CHAR(255) NOT NULL
         , `RevDateUpload` DATETIME NOT NULL
         , `RevAccepted` BOOLEAN NOT NULL
         , PRIMARY KEY (`RevID`)
         , INDEX (`DocID`)
         , CONSTRAINT `FK_Revisions_1` FOREIGN KEY (`DocID`)
                      REFERENCES `Documents` (`DocID`)
    );
    
    CREATE TABLE `M2M_UserRev` (
           `UserID` INT NOT NULL
         , `RevID` INT NOT NULL
         , INDEX (`UserID`)
         , CONSTRAINT `FK_M2M_UserRev_1` FOREIGN KEY (`UserID`)
                      REFERENCES `Users` (`UserID`)
         , INDEX (`RevID`)
         , CONSTRAINT `FK_M2M_UserRev_2` FOREIGN KEY (`RevID`)
                      REFERENCES `Revisions` (`RevID`)
    );
    

    文档是一个逻辑容器,修订版包含到文件的实际链接。 每当有人更新新文件时,在每个表中创建一个条目,修订版中的条目包含指向文档中插入的条目的链接。

    M2M_UserRev表允许将多个用户与文档的每个版本相关联。

    更新文档时,仅在修订中插入,并与相应文档保持链接。要知道要链接到哪个文档,可以使用命名约定,或者要求用户选择正确的文档。

        3
  •  13
  •   friol    15 年前

    数据库模式


    为了保持非常简单,我会选择以下数据库设计。我要把这条路分开“ 文件 (与文件系统文件相同)的概念 文件 “(gerarchic文件组)概念。

    • 用户ID

    实体:

    • 组名

    文件 实体:

    • fileId(一个序列)

    • 文件系统完整路径
    • 上传时间
    • uploaderId(上传程序用户的id)

    文件 实体:

    • 文档ID
    • 父文档ID

    • 版本号
    • 创作时间
    • 我同意

    每次上传一个新文件时,都会创建一个“文件”记录,以及一个新的“文档”。如果是第一次上载该文件,则该文档的parentDocumentId将为空。否则,新的文档记录将指向第一个版本。

    “isApproved”字段(布尔值)将处理草稿或已批准修订的文档。
    您只需按版本号或上载时间降序即可获得文档的最新草稿。

    提示


    根据您对问题的描述,在转到数据库架构设计之前,您应该更好地分析这些方面:

    • “集团”实体的角色是什么?
    • 组/用户/文件的关系如何?
    • 你需要文件夹吗?(您可能会这样做;我的解决方案仍然有效,为“文档”实体提供类型“文件夹”或“文档”)

        4
  •  9
  •   David Thornley    15 年前

    现有版本控制解决方案是否比您自己的版本控制解决方案更好?Subversion可以做你想做的大部分事情,它就在那里。

        5
  •  6
  •   Jamie Rumbelow    15 年前

    在传统关系数据库(如MySQL)中创建丰富的数据结构通常很困难,而且有更好的方法。在使用具有层次结构的基于路径的数据结构时,我喜欢创建一个基于平面文件的系统,该系统使用数据序列化格式(如JSON)来存储有关特定文件、目录或整个存储库的信息。

    通过这种方式,您可以使用当前可用的工具轻松导航和操纵结构,并且可以阅读、编辑和编辑 该结构易于安装。XML在这方面也很好——它比JSON稍微详细一点,但易于阅读,也适用于消息传递和其他基于XML的系统。

    一个简单的例子。如果我们有一个包含一个目录和三个文件的存储库。从正面看,它将如下所示:

    /repo
      /folder
        code.php
      file.txt
      image.jpg
    

    我们可以在每个目录的根目录下有一个元数据文件夹,其中包含对操作系统隐藏的JSON文件,描述该目录的内容。传统的版本控制系统就是这样工作的,只是它们使用自定义语言而不是JSON。

    /repo
      */.folderdata*
      /code
        */.folderdata*
        code.php
      file.txt
      image.jpg
    

    .folderdata 文件夹可以包含它自己的结构,我们可以使用它来正确组织文件夹的数据。每个 然后可以压缩文件夹以节省磁盘空间。如果我们看看 .folderdata /code目录中的文件夹:

    */.folderdata*
      /revisions
        code.php.r1
        code.php.r2
        code.php.r3
      folderstructure.json
      filerevisions.json
    

    {
      '.':        'code',
      '..':       'repo',
      'code.php': {
        'author_id': 11543,
        'author_name': 'Jamie Rumbelow',
        'file_hash': 'a26hb3vpq22'
        'access': 'public'
      }
    }
    

    这使我们能够关联关于该文件的元数据,检查真实性和完整性,保留持久数据,指定文件属性,以及做更多的事情。然后,我们可以在filerevisions.json文件中保留有关特定修订的信息:

    {
      'code.php': [
        1: {
          'commit': 'ah32mncnj654oidfd',
          'commit_author_id': 11543,
          'commit_author_name': 'Jamie Rumbelow',
          'commit_message': 'Made some changes to code.php',
          'additions': 2,
          'subtractions': 4
        },
        2: {
          'commit': 'ljk4klj34khn5nkk5',
          'commit_author_id': 18676,
          'commit_author_name': 'Jo Johnson',
          'commit_message': 'Fixed Jamie\'s bad code!',
          'additions': 2,
          'subtractions': 0
        },
        3: {
          'commit': '77sdnjhhh4ife943r',
          'commit_author_id': 11543,
          'commit_author_name': 'Jamie Rumbelow',
          'commit_message': 'Whoah, showstopper found and fixed',
          'additions': 8,
          'subtractions': 5
        },
      ]
    }
    

    这是一个文件版本控制系统的基本大纲计划——我喜欢这个想法和它的工作原理,我过去曾在像这样的丰富数据结构中使用JSON,效果非常好。这种类型的数据不适合像MySQL这样的关系数据库——当你得到更多的版本和更多的文件时,数据库会变得越来越大,这样你就可以在多个文件之间错开版本,保存所有内容的备份,确保你有跨接口和平台的持久数据等等。

    希望这给了你一些见解,也希望它能为社区提供一些思考的食物!

        6
  •  2
  •   gapple    16 年前

    对于数据库模式,您可能需要两组信息:文件和文件版本。存储新文件时,也会创建初始版本。必须显式存储最新批准的版本,而可以从版本表中选择最新版本(通过查找与文件相关的最高版本或最新日期,如果您存储了文件的创建日期)

    files(id,name,approved_version)
    file_versions(id,fileId)
    

        7
  •  2
  •   Michael Dausmann    15 年前

    我最近为一些静态数据实体构建了一个简单的版本控制系统。要求具有“活动”版本和0或1个“挂起”版本。

    最后,我的版本化实体具有以下与版本化相关的属性。

    版本号(整数/长)

    其中:-

    • 只有1个实体可以是ActiveVersionFlag='Y'

    我允许的手术是

    • 如果已有版本,则失败>“活动”版本的版本号
    • 将所有数据复制到新版本

    激活挂起版本

    • 查找“活动”版本并将其ActiveVersionFlag设置为“N”
    • 将“挂起”版本的ActiveVersionFlag设置为“Y”

    • 删除挂起的实体

    这相当成功,我的用户现在一直在克隆和激活:)

        8
  •  1
  •   maxwellb    15 年前

    从现有的 content management system ,在PHP和MySQL中完成,如果这些是您的需求,例如 eZ Publish Knowledgetree . 为了快速测试这些应用程序, Bitnami stacks “这些也一样(WAMP堆叠在类固醇上)。

    然后,您可以根据组织的需要定制这些应用程序,并及时了解上游的变化。

        9
  •  1
  •   maxwellb    15 年前

    服务器将有其数据根目录,您可以将组(文件)存储在文件夹中,每个文件夹中都有一个根元数据条目。(也许是XML?)

    然后,您可以使用包装在API中的现有修订控制工具,或滚动自己的工具,将文件的修订保留在修订文件夹中的项目下的修订文件夹中。检查修订,并使用文件I/O命令执行文件I/O。将API公开给Web应用程序或其他客户端应用程序,并让服务器通过XML文件确定文件权限和用户映射。

    迁移服务器?压缩并复制。

    例如,我喜欢Mercurial DVCS的平面文件后端。

    当然,在这个小示例中,.rev文件可以在revisions.xml文件中定义日期、时间、压缩等。当您想要访问其中一个修订版时,您将公开一个AccessFile()方法,服务器应用程序将查看该方法的revisions.xml,并确定如何打开该文件、是否授予访问权限等。

    DATA
    | + ROOT
    | | . metadata.xml
    | | |
    | | + REVISIONS
    | | | . revisionsdata.xml
    | | | . documenta.doc.00.rev
    | | | . documenta.doc.01.rev
    | | | . documentb.ppt.00.rev
    | | | . documentb.ppt.03.rev
    | | |___
    | | |
    | | . documenta.doc
    | | . documentb.ppt
    | | |
    | | + GROUP_A
    | | | . metadata.xml
    | | | |
    | | | + REVISIONS
    | | | | . revisionsdata.xml
    | | | | . documentc.doc.00.rev
    | | | | . documentc.doc.01.rev
    | | | | . documentd.ppt.00.rev
    | | | | . documentd.ppt.03.rev
    | | | |___
    | | |
    | | | . documentc.doc
    | | | . documentd.ppt
    | | |___
    | | |
    | | + GROUP_B
    | | | . metadata.xml
    | | |___
    | |
    | |___
    |
    |___
    
        10
  •  0
  •   Ryan Schumacher    16 年前

    退房 ProjectPier ActiveCollab ).它有一个类似的系统,你可以看看它们的来源。

        11
  •  0
  •   Alexander Kosenkov    15 年前

    正在将文件上载到(ty=) 看看谷歌浪潮!您可以围绕其“版本控制”框架构建整个应用程序。

        12
  •  0
  •   Rad    15 年前

    它不像看上去那么简单。阅读 this article Eric Sink介绍了存储这些文件的存储含义。

    也许更好的问题是加载的是什么类型的文件,它们是否适合版本控制(如文本文件)

        13
  •  0
  •   Ram    15 年前

    我认为这描述了版本控制的完美系统

    http://tom.preston-werner.com/2009/05/19/the-git-parable.html