最好的方式来版本化不同的git分支 [英] best way to versionize different git branches

查看:143
本文介绍了最好的方式来版本化不同的git分支的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我们有以下情况:我们有几个基本版本的OpenLieroX游戏;现在0.57,0.58和0.59。对于每个基本版本,我们有一个单独的分支。每个这样的基础版本都有几个版本(比如0.57 beta1-beta8和rc1,0.58 beta1-beta9)。



当我们在研究新东西时,我们正在最高的基本版本分支(现在是0.59)。当我们正在修复一些报告的错误时,我们会在最早的版本(大部分是0.58)中执行此操作。我们会不时将0.58中的所有变化合并到0.59中(只要我们仍然保留旧的分支并对其进行更改)。

这一切都是真的有效直到它发生一些我们只想在0.58而不是0.59发生的变化。这种情况仅适用于目前的一种情况:版本号。我们有一些Version.cpp文件(还有一些其他文件),它们包含版本号。所以,当我们想要推出一个0.58的新版本时,我们将其中的版本字符串更改为0.58 beta10(或其他)。现在,当我们通常从0.58合并到0.59时,这种改变也将被应用。我们现在修复这种情况,只需使用正确的版本号再次覆盖它(或者在其他错误提交的情况下,可能是回复)。



关于这样的详细信息不想要的改变对我来说似乎有点难看。我们管理这种方式一般不好/不常见?最简单的方法是如何获得相同的结果?在0.59中挑选0.58的所有提交者将会工作得多。




另外还有一个细节可能会使它更复杂:在处理代码时,我必须设置即将到来的版本号。这是因为我们有一个网络引擎,并且我们可能已经引入了一些新功能,并且在代码中检查'if(client-> version()> =版本(X,Y,Z))...'。现在,当我们介绍新的东西时,通常这在某些方面也意味着这种检查。 (但我们正试图避免在旧分支中发生这些变化。)另一个问题是,我们不只是计算版本(比如0.58.1,0.58)。 2,...),但我们这样计算:0.58 beta1,0.58 beta2,...,0.58 betaX,0.58 rc1,...,0.58,0.58.1,0.58.2,...这是因为我们想要将其标记为开始时的实验(测试阶段),然后将其标记为大部分稳定或稳定。在极少数情况下,甚至在两个不同的测试版本之间可能会发生严重的变化(可能是网络协议)(当然,我们试图避免它们,但有时不可能)。



0.59从0.58发散后,您可以为版本使用单独的发布分支数字在0.58变化。每个版本(最新除外)都有自己的release分支,它只包含来自基本分支的合并和更新外部版本号的更改。分支结构可能如下所示:

  A -------- o  -  B 0.58-release 
/
... - o - o - o - o - o - o - o - o 0.58
\ \ \ \
\\\\\\ C 0.59-释放
\\\\\ $ $ $ $ $ $ $ $ $ $ $ $ $ $% o - o - o - o - o - o 0.59
\\\
o - o - o 0.60




  • 标签软件0.58 beta9
  • B标签软件0.58 rc1
  • 0.58有尚未发布的更改

  • C标记软件0.59 beta1 0.59有尚未发布的更改

  • 0.60尚未完全更新至0.59



或者,如果您对A,B,C等更改外部版本号的更改非常严格(没有重大代码更改,则属于基本分支:0.58,0.59,等等),那么你可以不用发布分支。相反,您可以使用分离的HEAD或临时分支(在发布版本后将其删除)以进行外部版本更新提交并将其保存在标记中。



<$ p $ AB
/ /
... - o - o - o - o - o - o - o - o 0.58
\\\\\
\\\\\\\\\\\\\\\\\\\\\\\\\\\ b b b b b C $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ -o - o - o - o - o - o - o - o 0.59
\\\
o - o - o 0.60




  • 标签为软件0.58 beta9,标签为0.58-beta9

  • B将软件标记为0.58 rc1并且标记为0.58-rc1
  • C标记软件0.59 beta1并且标记为0.59-beta1



就像Git做的那样



你也可能会看看Git自己进行版本控制的方式。



对于使用Git工作树完成的构建,版本号是从 git描述HEAD Makefile 知道如果版本号改变,哪些文件需要重新编译/重建,并且它总是运行 GIT-VERSION-GEN 脚本来确保它具有最新的版本号。通过包含生成的版本文件,版本号在Makefile中可用。它通过参数传递给C文件( -DGIT_VERSION = ... ),并通过使用 sed 将其替换为脚本。 p>

有一些规定可以覆盖烧入构建的版本号,但它们通常只用于在工作树之外完成的构建(例如,从树从$ tar文件中提取)问题,你声明你需要在开发时调整版本号。首先,我认为我已经描述的0.58版本分支机制仍然适用于您。它只是需要更多的纪律来分隔你的改变。如果您考虑将发布用于内部测试而不是发布给客户(或用于外部测试)的* - 发布分支,那么它仍然有意义。总是在基础分支上进行开发(例如0.58),并且在构建需要特定版本号的构建之前,总是将基础分支合并到发布分支中(例如0.58版本)合并发布分支)。

如果您坚持在同一行历史记录中进行版本号更改和(非合并)代码更改,那么在我看来,你将别无选择,只能在合并时处理冲突(除非你使用 git cherry-pick )(根据Damien Wilson或自动编辑脚本以<$ c

如果您的版本文件 包含版本信息,那么您可以通过使用 .gitattributes 来标记您的 Version.cpp 文件为unmergable来缓解冲突解决。 p>

.gitattributes在包含Version.cpp的目录中



  / Version。 cpp -merge 

将它标记为(与 merge = binary 相同)将会在合并分支之间文件不同时始终引起冲突。合并后的工作树版本将默认为您检出的分支的版本(不是您正在合并的分支中的版本),因此您可以 git add Version.cpp &安培;&安培; git commit 来完成合并(假设所有其他冲突也已解决)。


We have the following scenario: We have several base versions of our game OpenLieroX; right now 0.57, 0.58 and 0.59. For each base version, we have a seperate branch. Each such base version has several releases (like 0.57 beta1-beta8 and rc1, 0.58 beta1-beta9).

When we are working on new stuff, we are working in the highest base version branch (right now that is 0.59). When we are fixing some reported bugs, we do that in the earliest version (mostly 0.58) where that occured. From time to time, we always merge all changes in 0.58 into 0.59 (as long as we will still maintain and do changes on the old branch).

This all works really fine until it comes to some changes which we want to have only in 0.58 but not in 0.59. This happend only for one case so far: The version number. We have some Version.cpp file (and also some other files) which contains the version number. So, when we want to push a new release for 0.58, we change the versionstring in there to "0.58 beta10" (or whatever). Now, when we do the usual merging from 0.58 into 0.59, this change will also be applied. We fix such cases at the moment by just overwriting it again with the right version number (or in cases for other bad commits, probably a revert).

This detail about such unwanted changes seems to be a bit ugly to me. Is the way we manage this in general bad/uncommon? How would be the easiest way to do this to get the same result? Cherry-picking all commits of 0.58 in 0.59 would be much more work.


There is also one further detail which probably makes it more complicated: While working on the code, I have to set already the upcoming version number. This is because we have a network engine and we may have introduced some new functionality and there are checks in the code like 'if(client->version() >= Version(X,Y,Z)) ...'. Now, when we introduce something new, usually it means at some points also such checks. (But we are trying to avoid these changes in older branches.)

Another problem is that we don't just count the version up (like 0.58.1, 0.58.2, ...) but we count like this: 0.58 beta1, 0.58 beta2, ..., 0.58 betaX, 0.58 rc1, ..., 0.58, 0.58.1, 0.58.2, ... This is because we want to mark it as experimental for the beginning (beta stage) and then as mostly stable or stable. In some rare cases, there may be serious changes (maybe network protocol) even between two different beta releases (of course, we try to avoid them, but sometimes it's not possible without).

解决方案

With Extra Branches

After 0.59 diverges from 0.58, you could use a separate "release" branch for the version number changes in 0.58. Each version (except the most recent) would have its own "release" branch that only contains merges from the base branch and changes that update the external version number. The branch structure might look something like this:

                A--------o--B                  0.58-release
               /        /
...--o--o--o--o--o--o--o--o                    0.58
      \        \        \  \
       \        \        \  \            C     0.59-release
        \        \        \  \          /
         o--o--o--o--o--o--o--o--o--o--o--o    0.59
                                  \     \
                                   o--o--o     0.60

  • A labels the software "0.58 beta9"
  • B labels the software "0.58 rc1"
  • 0.58 has changes that have not yet been released
  • C labels the software "0.59 beta1"
  • 0.59 has changes that have not yet been released
  • 0.60 is not yet fully up to date with 0.59

Or, if you are very strict in only making changes at A, B, C, etc. that change the external version number (no significant code changes, those belong on the ‘base’ branches: 0.58, 0.59, etc.), then you could do without the "release" branches. Instead you could use a detached HEAD or temporary branch (deleted after the release is versioned) to make the external-version-update commit and save it in a tag.

                A        B
               /        /
...--o--o--o--o--o--o--o--o                    0.58
      \        \        \  \
       \        \        \  \            C
        \        \        \  \          /
         o--o--o--o--o--o--o--o--o--o--o--o    0.59
                                  \     \
                                   o--o--o     0.60

  • A labels the software "0.58 beta9" and is tag 0.58-beta9
  • B labels the software "0.58 rc1" and is tag 0.58-rc1
  • C labels the software "0.59 beta1" and is tag 0.59-beta1

Like Git Does It

You also might look into the way Git does its own versioning.

For builds done out of a Git working tree, the version number is generated from the output of git describe HEAD. The Makefile knows which files need to be recompiled/rebuilt if the version number changes and it always runs the GIT-VERSION-GEN script to make sure it has the most recent version number. The version number is available in the Makefile by inclusion of the generated version file. It is passed to C files by a argument to the compiler (-DGIT_VERSION=…) and it is substituted into scripts by using sed.

There are some provisions for overriding the version number "burned into" a build, but they are generally there only for builds done outside a working tree (e.g. a build done from a tree extracted from a tar file).

Mixing Version-String Changes With Other Changes

In your addendum to your question, you state that you need to adjust the version number while doing development. First, I think that the "0.58-release" branch scheme that seh and I have described can still work for you. It will just take more discipline to separate your changes. If you think about the *-release branches as "released for internal testing" and not just "released to customers (or for external testing)", then it still makes sense. Always do your development on the base branch (e.g. "0.58"), and always merge the base branch into the release branch (e.g. "0.58-release") before doing a build that will require a specific version number (always build from such a merged release branch).

If you insist on putting version-number changes and (non-merge) code changes in the same line of history, then is seems to me that you will have little choice but to deal with the conflict when merging (unless you go with git cherry-pick (per Damien Wilson, or an automated edit script aimed at git rebase -i).

If your "version files" only contain versioning information, you might be able to ease the conflict resolution by using .gitattributes to mark your Version.cpp file as unmergable.

.gitattributes in the dir that contains Version.cpp

/Version.cpp -merge

Marking it like this (same as merge=binary) will always cause a conflict if the file is different between merged branches. The post-merge working-tree version will default to the version from the branch you have checked out (not the one from the branch(es) you are merging), so you can just git add Version.cpp && git commit to finish the merge (assuming all other conflicts are also resolved).

这篇关于最好的方式来版本化不同的git分支的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆