如何使用Git实现数字版本控制方案?


131

我的组织正在考虑从SVN迁移到Git。反对搬迁的一种论据如下:

我们如何进行版本控制?

我们有一个基于NetBeans平台的SDK发行版。由于SVN修订版是简单的数字,因此我们可以使用它们来扩展我们的插件和SDK构建的版本号。转移到Git时如何处理?

可能的解决方案:

  • 使用Hudson的内部版本号(问题:您必须检查Hudson才能将其与实际的Git版本相关联)
  • 手动升级版本以保持夜间稳定(问题:学习曲线,人为错误)

如果其他人遇到了类似的问题并解决了该问题,我们将很乐意听听如何解决。


3
每次成功构建后,您能否使hudson(不是jenkins?)服务器自动添加git标签?这将具有额外的优势,因为它可以使那些git提交保持未标记状态,因此可以真正弄清哪些提交存在构建问题或测试失败。
Mark Booth 2012年


另外,您可以通过跟踪构建时间将构建计数添加到标签中。
Shahbaz 2014年

不确定是否可行,但是在每次构建之前从git导出到svn repo怎么样?然后只需从svn存储库构建-如果我们需要集中式存储,则只需使用它即可。
乔尼2015年

Answers:


152

使用标签以版本号标记提交:

git tag -a v2.5 -m 'Version 2.5'

向上游推送标签-默认情况下不执行此操作:

git push --tags

然后使用describe命令:

git describe --tags --long

这为您提供了以下格式的字符串:

v2.5-0-gdeadbee
^    ^ ^^
|    | ||
|    | |'-- SHA of HEAD (first seven chars)
|    | '-- "g" is for git
|    '---- number of commits since last tag
|
'--------- last tag

同意-如果需要的话,应该很容易实现夜间标签编号的自动化,无论如何,要手动升级到稳定版本是可行的。
没用的2012年

20
小改进:git describe --long --tags --dirty --always。“ dirty”会告诉您“ describe”完成后是否发生了局部更改(这意味着它无法完全描述存储库的状态)。“始终”表示在没有标签的情况下不会出错。它将回退到仅提交哈希。因此,您可以76001f2-dirty举一个例子。显然,看到“肮脏”意味着有人搞砸了。
Mike Weller 2013年

1
最后生成标签时,该如何工作。通常,您希望以后的版本具有产品的下一版本。但是在这种情况下,他们将始终被迫使用最新版本。只有最终交付的内部版本具有正确的编号。
void.pointer 2015年

@ void.pointer:当然,此版本号回答了“此提交基于哪个版本?”而不是“此提交将位于哪个版本?”的问题。但是,您可以自由地以不同的方式解释标签。例如,如果将标记HEADv2.5,则可以将其解释为2.5发布周期的开始,然后标记v2.5-release或任何您喜欢的内容。
乔恩·普迪

8
另一个小改进。如果您还希望拥有其他标签,但使用特定模式的标签进行修订生成,则可以使用以下--match选项:git describe --long --tags --dirty --always --match 'v[0-9]\.[0-9]'
Alexander Amelkin

41

对我来说,这已经涉及了一些项目。到目前为止,我最好的解决方案是生成这样的版本号:

xy <提交数> .r <git-hash>

通常,它是由我们的构建系统使用一些静态文件或标记的组合生成的,以获取主要的修订版本号git rev-list HEAD | wc -l(比使用更快git log)和git rev-parse HEAD。推理如下:

  1. 我们需要具有明确进行高级版本控制的能力(即ixy)
  2. 当并行开发发生时,我们永远不需要生成相同的版本号。
  3. 我们想要轻松地跟踪版本的来源。
  4. 合并平行线时,我们希望新版本的解析度高于任何一个分支。

对于大多数人来说,数字2是看不见的,但是它确实很重要,并且对于分布式源代码控制来说确实很困难。SVN通过为您提供一个修订号来帮助您实现这一目标。事实证明,提交计数与您所能获得的尽可能接近,同时还神奇地解决了#4。在存在分支的情况下,这仍然不是唯一的,在这种情况下,我们添加了哈希,它也巧妙地解决了#3。

其中大部分是为了适应通过Python的pip进行部署。这保证了pip install在并行开发过程中可能会有些奇怪(即,来自不同分支机构的人员的软件包会混合在一起,但是以确定性的方式混合在一起),但是合并后,一切都整理了。除非存在公开的基础变更或修改,否则对于上述要求而言,这很好。

如果您想知道,我们选择将r放在散列前面是由于Python包装如何处理版本号中的字母(即ae小于0,这将使“ 1.3.10.a1234” < “ 1.3.10” <“ 1.3.10.1234”)。


1
顺便说一句,您如何处理在签入之前确定git-hash的鸡肉问题?您是否使用了某种形式的.gitignore或其他技巧?
kfmfe04 2012年

2
我没有 在签入后很长的程序包构建时间之前,我不会使用哈希。不同的语言有不同的注入方式。对于Python,我使用'./setup.py egg_info -b“。$ {BUILD_VERSION}” sdist'。对于C和C ++,我在编译时用'CFLAGS = -D“ $ {BUILD_VERSION}”“定义了一个宏。对于Go,我在链接时使用'go install -ldflags appmodule.BuildVersion“ -X。$ {BUILD_VERSION}”“定义了一个符号。
杰森(Jayson)2013年

1
这应该是最好的答案。
alvinabad

很好的答案
haelix


8

这可能有点矫kill过正,但我​​会让您知道我们如何做到。

我们使用与非常相似的分支结构。

Hudson建立了我们的“ develop”分支,并从0开始递增内部版本号。内部版本号对于每个项目都是唯一的,并在版本控制中进行标记。原因是这样,例如,您可以准确分辨出哪个开发分支内部版本42来自(每个项目可以并行具有多个开发分支,因为每个项目可以有多个团队在项目的不同方面工作)。

当我们确定某个特定的构建足以发布时,触发该构建的提交将被标记有发布版本号,该版本号由行销决定。这意味着开发团队不在乎最终版本号是什么,市场营销部门可以自由选择合适的版本号。最终版本号和内部版本号都在发行的产品中。

示例:2.1.0版本1337

这意味着,对于特定的产品发行版,您可以确定是哪个团队进行了最后的工作,并且可以在git中查询导致发行的所有提交,以根据需要诊断问题。


0

乔恩·普迪(Jon Purdy)有正确的想法。git flow也使这些分支的实际管理变得容易,分支管理是转移到的论据git

让我们从开始进行基本剖析git,因为您来自svn-to- git透视图。考虑git以下内容:

master--...............-.....-..............-
        \             /     /              /
         ---develop---------............../
                            \            /
                             --feature---

在上面,您分支masterdevelop(由表示\),然后分支develop到一个feature分支。我们将这些分支合并起来(由表示/),并-沿分支提交()。(如果没有提交,但是合并在右边,则有.指示符表明下一个-是下一个提交)。

很简单。如果我们的主版本中有修复程序怎么办?

master--...............-.....-................-...........-.........-
        \             /     /                / \         /|        /
         \           /     /                /   -hotfix-- V       /
          ---develop---------............../..............-...----
                             \            / \             V   /
                              --feature---   --feature2...----

develop从上方分支mastermaster通过从中分支master,修复并合并到中,修复了其中发现的错误master。然后,我们合并masterdevelop,然后再develop进入feature2,从推出新的代码hotfix到这些分支。

当您合并feature2回时develop,其历史记录将包含develop在中hotfix。同样,developfeature2与中的新代码合并到一起master,因此合并develop回去master将毫不费力,因为它基于当时的提交master(就像您从那时开始分支一样)master

所以这是另一种方法。

master--..........-........-
        \        /\       /
         ---1.0--  --1.1-- 

你的1.0版本中得到tagged- 1.0.11.0.21.0.3,等等。

现在,这里有个窍门:您在1.0中发现了一个bug,它会影响1.1、1.2和1.3。你是做什么?

您从最新或最早维护的版本中分支并对其进行修复。然后您合并新hotfix科进1.3-和成1.21.11.0。不要从每个维护版本分支中分支;不要合并1.0master或合并master1.0。选择一个hotfix分支并将其合并到所有版本分支中。如果有冲突,它将告诉您。查看您的代码以确保更改正确(git diff是您的朋友)。

现在,该特定更改已应用于所有地方。血统是分支的,但是还可以。这不是偶然的。将1.3头部标记为1.3.17,将其合并到从分支的每个进行中的功能中1.3,然后继续进行。

git flow扩展帮助您管理这些维护,功能和修补程序分支。一旦您降低了工作流程,这将是微不足道的,并且会给源代码管理带来很多麻烦。

我已经在编程团队中看到了这一点,但是作为一名程序员,我并没有做那么深入的工作,因此我自己仍在处理日常工作流程。


-6

“关键字”扩展部分的第7.2节“ Git属性”中的Pro Git 包含使用污点和清除过滤器生成RCS样式关键字的一个很好的示例。您可以使用相同的技术将some-version-string嵌入代码中,并根据规则进行格式化和计算。您仍然可以将其git describe用作凝视点,但是您可以转换为任何更合适的形式并从v2.5-14-feebdaed中获取,例如,干净的2.5.14


9
-1完全不叫作ad hominem攻击而破坏了一个好的答案。
约尔格W¯¯米塔格

9
谁说这是混血男孩投票赞成你。可能容易有人喜欢一点礼貌
Mark Booth 2012年

仅供参考,我刚刚编辑了答案。
Keith Thompson

git describe输出标签名,除非--long已通过,否则自上一个标签以来已有提交,因此已经很干净了。如果您不更改默认值,它将完全满足您的需求。
strcat
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.