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

Bor*_*éry 22 php sql algorithm code-organization data-structures

我想做一个简单的版本控制系统,但我没有关于如何构建我的数据和我的代码的想法.

这是一个简短的例子:

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

用户应该能够看到树.(不同版本)树最多只能达到2个级别:

|
|--File_A_0
 \--File_A_1
 \--File_A_2
 \--File_A_3
 \--File_A_4
Run Code Online (Sandbox Code Playgroud)

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

编辑:组代表一组文档,文档只能由一个组一次拥有.用户不依赖于组.

开始编辑:

这就是我所做的,但效率并不高!

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

id_draft | id_file | version | date
Run Code Online (Sandbox Code Playgroud)

但是很难管理,扩展.我认为这是因为小组参议员......

结束编辑

所以问题是:

  • 我如何模式化我的数据库?
  • 什么样的信息应该对这项工作的版本有用?
  • 文件夹,文件是什么类型的结构?
  • 有什么样的提示,提示你做这种工作吗?

(该应用程序是用PHP和Zend Framework开发的,数据库应该是mysql或postgresql)

Mic*_*man 49

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

暂时停下来考虑一下大局.你想保留早期版本的文档,这意味着在某些时候,有人会想要看到一些早期版本,对吧?然后他们会问,"版本3和版本7有什么区别"?然后他们会说,"我想回到版本3,但保留我在第5版中所做的一些更改,嗯,好吗?"

版本控制非常重要,并且不需要重新发明轮子 - 那里有许多可行的版本控制系统,其中一些是免费的,甚至是免费的.

从长远来看,学习其中一个系统的API会更加容易,并且可以为您的用户编写一个Web前端代码,为您的用户提供他们正在寻找的功能(现在).

您不会为您的用户编写文本编辑器,是吗?

  • "你不会编写文本编辑器代码",为什么不呢?如果他们付钱 (10认同)
  • 编写文本编辑器是一个很好的练习,每个人都应该在自己的角钱里做(并编写编译器).我不会为客户编写文本编辑器,即使他们为此付费 - 因为它不能很好地利用我的时间或金钱,而这也不是建立长期关系的方式.(此外,为什么编码只能出售一次的东西,如果你可以选择编码具有更多转售价值的东西?) (9认同)
  • "你不会编写文本编辑器代码",为什么不呢?这是一个很好的运动:) (6认同)
  • 你有很多很好的理由,我支持所有这些,但你很幸运能够选择你的代码。事实是,有时,人们没有那么多的自由,只能按照要求编写代码。此外,我恰好正在为 DMS 做这种系统,在其中集成真正的控制版本系统将是一种矫枉过正的行为。 (2认同)
  • 好吧,*某人*正在选择您编码的内容.如果不是你,那么你可以向你的上级提出技术案例.至于文档管理系统 - 这些系统也可以通过现成的API进行定制.我建议不要为一次性项目定制编码引擎; 在成本/效益比方面,这不是一个成功的举措. (2认同)

glm*_*ndr 18

你可以从那里获得灵感.


关于你的评论:

至于数据库结构,你可以尝试这种结构(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`)
);
Run Code Online (Sandbox Code Playgroud)

Documents是一个逻辑容器,Revisions包含指向文件的实际链接.每当一个人更新一个新文件时,在每个表中创建一个条目,Revisions中的条目包含一个插入到Documents中的链接的链接.

表M2M_UserRev允许将多个用户与文档的每个修订相关联.

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

对于文件的文件系统架构,它确实没关系.我只是在将文件存储在服务器上之前将其重命名为独特的文件,并将用户文件名保存在数据库中.只需将重命名的文件存储在任何位置的文件夹中,并在数据库中保留它的路径.这样,您就知道如何在用户请求时重命名它.如果你确定它是唯一的,你也可以保留用户给出的原始名称,但我不会太依赖它.您可能很快就会看到两个不同的版本具有相同的名称,另一个会覆盖您文件系统上的另一个版本.


Gab*_*ona 13

数据库架构


为了保持极其简单,我会选择以下数据库设计.我将" 文件 "(与文件系统文件相同)概念与" 文档 "(文档的gerarchic组)概念分开.

用户实体:

  • 用户身份
  • 用户名

集团实体:

  • 的groupId
  • 团队名字

文件实体:

  • fileId(序列)
  • fileName(用户为文件指定的名称)
  • filesystemFullPath
  • uploadTime
  • uploaderId(上传者用户的ID)
  • ownerGroupId

文件实体:

  • documentId
  • parentDocumentId
  • FILEID
  • VERSIONNUMBER
  • 创建时间
  • 被批准

每次上传新文件时,都会创建"文件"记录,还会创建新的"文档".如果是第一次上传该文件,则该文档的parentDocumentId将为NULL.否则,新文档记录将指向第一个版本.

"isApproved"字段(布尔值)将处理作为草稿或批准修订的文档.
您可以获得文档的最新草稿,只需按版本号或上传时间排序即可.

提示


从描述问题的方式来看,在迁移到数据库模式设计之前,应该更好地分析这些方面:

  • 哪个是"团体"实体的角色?
  • 组/用户/文件如何相关?
  • 如果不同组的两个用户尝试上传同一文档怎么办?
  • 你需要文件夹吗?(可能你会;我的解决方案仍然有效,给"文档"实体提供一个类型,"文件夹"或"文档")

希望这可以帮助.


Dav*_*ley 9

现有的版本控制解决方案可能比滚动自己更好吗?颠覆可以做你想做的大部分,而且就在那里.


Jam*_*low 6

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

这样,您可以使用当前可用的工具轻松地导航和操作结构,并且您可以轻松地阅读,编辑和理解结构.XML也适用于此 - 它比JSON稍微冗长,但易于阅读,也适用于消息传递和其他基于XML的系统.

一个简单的例子.如果我们有一个包含目录和三个文件的存储库.在它前面看它会看起来像这样:

/repo
  /folder
    code.php
  file.txt
  image.jpg
Run Code Online (Sandbox Code Playgroud)

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

/repo
  */.folderdata*
  /code
    */.folderdata*
    code.php
  file.txt
  image.jpg
Run Code Online (Sandbox Code Playgroud)

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

*/.folderdata*
  /revisions
    code.php.r1
    code.php.r2
    code.php.r3
  folderstructure.json
  filerevisions.json
Run Code Online (Sandbox Code Playgroud)

文件夹结构定义了我们文件夹的结构,文件和文件夹彼此相关等.这可能看起来像这样:

{
  '.':        'code',
  '..':       'repo',
  'code.php': {
    'author_id': 11543,
    'author_name': 'Jamie Rumbelow',
    'file_hash': 'a26hb3vpq22'
    'access': 'public'
  }
}
Run Code Online (Sandbox Code Playgroud)

这允许我们关联该文件的元数据,检查真实性和完整性,保留持久数据,指定文件属性以及执行更多操作.然后,我们可以在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
    },
  ]
}
Run Code Online (Sandbox Code Playgroud)

这是文件版本控制系统的基本大纲计划 - 我喜欢这个想法以及它是如何工作的,并且我过去使用过JSON来发挥这样的丰富数据结构的巨大作用.这种类型的数据只是不适合于关系数据库如MySQL - 因为你得到更多的修订和更多的文件数据库将增长越来越大,这样就可以错开多个文件的修订,让一切的备份,使确保你有跨接口和平台等的持久数据.

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