分类 PM 下的文章

二进制文件如何进行版本控制

难以避免的烦扰

通常在项目开发过程大多数代码是以文本形式存在在版本管理系统中。但是难免有一些二进制数据需要进行版本管理,比如 图片、数据库文件、其他二进制可执行程序等。

存在的问题

  • 二进制文件通常无法进行直接diff,导致版本控制功能弱化。
  • 二进制文件通常比较大,特别是git存储方式(镜像存储)占用大量磁盘空间。
  • 二进制文件通常是有特定的需求比如patch过后编译出来的。后期无法跟踪。
  • 二进制可执行程序,无法做到跨平台运行,可能依赖特定环境。
  • 二进制文件,无法直接进行代码审计。无法做到行级别跟踪。

某场景

我们项目中有一个sqlite3的数据库文件用来存放规则信息。在维护过程这个数据库文件每次都被整体更新。进行主干稳定代码库发现紧急一个问题,需要临时修复并立马二次发布。但是这个sqlite3数据文件在开发分支。已经被完整更新过许多次了。但是我只需要其中某一次提交。这时候不淡定了。魂淡,为什么不存储xml格式?啊啊啊啊。实在没办法,把sqlite3数据文件手动转换成sql文件,人肉小心翼翼的进行sql文件 diff & merge。最后终于发布紧急版本。

BOSS问:为什么紧急版本发布比平时版本还慢,客户意见很大。 偶:我容易吗。。

合理存储二进制

有很多场景确实让人无奈,比如老项目维护,必须把二进制存放版本库。给大家一些建议降低维护成本。

  • Web前端图片

    • 尽量合并多张图片到单个图片文件,避免图片文件碎片化。参考CSS Image Sprites
    • 推荐对不同模块静态资源进行区分目录存储。参考 Django managing static files
    • 进行图片文件commit的时候写上清晰明确messags,后期维护的主要依据 (适用于任何场景)。
    • 定期确认和清理已经不在使用的图片。
  • 数据库文件

    • 善用git提供的gitattributes主要用到filter和diff两种方式,

      • filter可以做到开发模式和存储模式过滤转化。实现开发看到的是文本,存储的是二进制。
      • diff 可以对二进制文件进行差异比较,比如sqlite数据文件,在diff情况下看到就是sql文本文件差异。
  • 二进制程序或其他进制程序。

    • 再次确认,不推荐二进制可执行程序直接行版本库。
    • 进行文件commit的时候写上清晰明确messags,后期维护的主要依据 (适用于任何场景)。
    • 善用Linux提供的strings程序。必要的时候调用strings 把二进制转换成文本。

使用文本替代二进制存储

大多数场景下除了图片资源外,不建议在版本库中存放其他二进制文件。但是这些程序又必须被管理起来。如何才能解决呢?

  • 数据库文件

    • 数据量不是非常大的情况,能否用xml或其他文本文件代替。
    • 能否转换成原生的sql文件再存储。
    • 善用git提供的 gitattributes filter功能,在提交到暂存区时自动把它转化成sql文本文件。
  • Word和文档类型文件

    • 推荐用 Sphinxmarkdown方式进行文档编写与存储,必要时生成PDF。
    • 使用 DocBook进行文档编写与存储支持生成Word.
  • 二进制程序

    • 采用git提供submodule功能,直接进行跨项目依赖。
    • 采用svn提供svn:externals property进行跨项目依赖。
    • 提供工程化程度足够的安装脚本主动进行依赖处理。
    • 如果有进行patch操作,必须在版本库中保留patch文件,patch文件名需要足够清晰,并且用Quilt管理起来。
  • 压缩包

    • 根据实际压缩内容,再针对性处理。

总结

要做一个有洁癖的开发者,善用手上的工具。你遇到的哪怕是一点点困难,也已经无数前人踩过坑。