语义版本控制:小改动还是大改动?

Posted

技术标签:

【中文标题】语义版本控制:小改动还是大改动?【英文标题】:Semantic versioning: minor or major change? 【发布时间】:2019-07-31 22:52:14 【问题描述】:

在semantic versioning 中,一般规则是仅在引入向后兼容的功能时才增加次要编号,否则必须增加主要编号。 libtool 使用same approach,但算法不同。

我有一个问题,关于什么被认为是向后兼容的变化,什么不是。

假设我编写了一个库,该库的公共头文件包含一个名为foo 的数据类型的typedef。在 1.0.0 版中,typedef 看起来像这样:

typedef struct foo_t 
    int x;
    int y;
 foo;

然后我决定改变数据类型,下个版本会是这样的:

typedef struct foo_t 
    int x;
    int y;
    int z;
 foo;

我只向结构foo_t 添加了一个字段。这似乎是一个向后兼容的变化,但是上面的结构现在是 de facto 另一个结构。我所做的不是引入一个新功能,其余的都保持不变,而是我改变了一些已经存在的东西。

上述数据类型通常用于与库函数交换数据,但用户可能将其用于其他目的。如果用户使用 1.0.0 版本编写了程序,并且最后一次更改构成向后兼容的更改,则用户的程序也必须使用这个新版本进行编译。

这个新版本怎么叫,1.1.0还是2.0.0?

编辑

您可以阅读此讨论的进一步发展here。

【问题讨论】:

【参考方案1】:

这将是一个主要的版本更改。结构布局被烘焙到最终用户程序中。添加 删除成员是一项重大更改;无论哪种方式,布局都发生了变化。

引用Linux Program Library HOWTO — §3.6。不兼容的库:

当新版本的库与旧版本二进制不兼容时,soname 需要更改。在 C 语言中,库不再兼容二进制有四个基本原因:

    函数的行为发生变化,使其不再符合其原始规范,

    导出的数据项发生变化(例外:将可选项添加到结构的末尾是可以的,只要这些结构仅在库中分配)。

    李>

    导出的函数被移除。

    导出函数的接口发生变化。

您说,“上面的数据类型通常用于与库的函数交换数据,但是用户可能已将其用于其他目的。”如果该结构仅在内部使用并且未在公共 API 中公开,则可以。但听起来用户可以自己分配一个结构变量,这意味着这是一个突破性的变化。

您可以使用opaque structs 保护您的图书馆免受此类流失的影响。隐藏结构的内容,让用户只传递指针。这正是 FILE * 的工作原理:C 标准没有定义 FILE 的布局,我们作为最终用户不知道其中的内容。

【讨论】:

感谢您提供非常好的答案。我不能向用户隐藏我的struct,所以不透明的结构不是一种选择。主要版本改变吧! 请注意,您可以通过使大小动态化(因此用户需要查询库以获取要分配的大小)或包含大小甚至动态来避免需要主要版本更改对象本身的版本 ID。对于后者,库将需要检查该大小/版本以了解它正在处理的对象版本(更多工作),但如果您预计将来想要更改结构,这可能是值得的。

以上是关于语义版本控制:小改动还是大改动?的主要内容,如果未能解决你的问题,请参考以下文章

版本控制最佳实践

版本控制SVN

关于的svn版本控制的问题

版本控制

Git workflow

Git使用过程