如何维护受git源代码控制的bash脚本的版本号?

如何维护受git源代码控制的bash脚本的版本号?,git,bash,version,Git,Bash,Version,我刚刚完成了一个更复杂的bash脚本的第一个工作版本,我正在研究如何维护这个脚本版本 为什么我需要这个?下面我添加了一个版本选项,在许可证和版权标题中显示当前版本 不过,我不知道如何保持版本“最新” 到目前为止,我的想法是使用git标记发布主补丁,并以某种方式替换脚本中包含的变量 因此,如果我有一个名为1.1.0的标记,那么 $ myscript --version 应该输出如下内容: myscript 1.1.0 该脚本包含此脚本的shell变量: version=1.1.0 不过,我现

我刚刚完成了一个更复杂的bash脚本的第一个工作版本,我正在研究如何维护这个脚本版本

为什么我需要这个?下面我添加了一个版本选项,在许可证和版权标题中显示当前版本

不过,我不知道如何保持版本“最新”

到目前为止,我的想法是使用git标记发布主补丁,并以某种方式替换脚本中包含的变量

因此,如果我有一个名为
1.1.0
的标记,那么

$ myscript --version
应该输出如下内容:

myscript 1.1.0
该脚本包含此脚本的shell变量:

version=1.1.0

不过,我现在不知道如何使版本与最新标记保持同步?

使用提交后挂钩,而不是自己创建标记。其思想是检查HEAD是否包含修改版本分配的行,如果是,则创建一个新标记。这只是一个粗略的例子;它可能是有车的,而且肯定没有它可能的那么有效

#!/bin/bash

before=$( git log HEAD | awk -F= '/-version=/ {print $1}' )
after=$( git log HEAD | awk -F= '/+version=/ {print $1}' )

if [[ $before != $after ]]; then
    git tag myscript-$after
fi

据我所知,你想要的是不可能的。为了将版本号提交到版本控制软件中,您必须编辑版本号,提交,然后标记;而不是相反。不过,您可以让流程稍微简化一点

我们可以通过编写一个post-commit钩子来实现这一点,该钩子将读取脚本的版本号,如果它与上次的版本号不同,则编写一个新的标记。为此,请从项目目录将cd放入
.git/hooks
,创建一个名为
post commit
(或移动
post commit.sample
)的文件,并使其可执行。然后编辑它,使其看起来像这样:

#!/bin/bash

NEWEST_TAG=$(git describe --abbrev=0 --tags)

SCRIPT_VERSION=$(grep "^version=" myscript | awk -F= '{print $2}')

if [ x$NEWEST_TAG != x$SCRIPT_VERSION ]; then
    git tag -a $SCRIPT_VERSION -m "version $SCRIPT_VERSION"
fi
下一次,当您更改脚本的版本号并提交更改时,您将看到在最新提交中添加了一个新标记

不过,我不知道如何保持版本“最新”


我确实喜欢后钩子的建议。然而,另一种方法是,如果已经有一个构建系统可用,也可以使用它。你们有自动生成系统吗?詹金斯还是竹子?我们的构建系统为通过所有单元测试的每个成功构建创建一个新标记。假设这是一个脚本,所以您可能只需要运行单元测试(如果您有)。您可以在构建作业中添加任务,以增加或匹配版本与运行并通过任何测试的成功构建或最新提交的标记。

先前给出的基于钩子的答案将版本字符串的同步与
git提交紧密耦合。
;但是,听起来您希望它以另一种方式工作,即从手动创建的
git标记
元数据中提取版本。事实证明,这几乎就是它本身使用的方法,因此,让我们通过检查它的方法来了解如何采用类似的方法:

  • 它有一个shell脚本,试图智能地确定当前版本。从本质上讲,它试图通过git descripe来提取版本字符串,但如果不起作用,则返回到硬编码的默认值。版本将写入源代码树顶部的GIT-version-FILE
  • 调用此脚本并包含生成的文件:

    GIT-VERSION-FILE: FORCE
            @$(SHELL_PATH) ./GIT-VERSION-GEN
    -include GIT-VERSION-FILE
    
    现在,
    Makefile的其余部分可以通过
    $(GIT\u版本)
    访问该版本

  • 然后,各种Make规则使用它对需要硬编码版本字符串的任何文件执行替换,例如各种Perl脚本:

    $(patsubst %.perl,%,$(SCRIPT_PERL)): % : %.perl GIT-VERSION-FILE
            $(QUIET_GEN)$(RM) $@ $@+ && \
            INSTLIBDIR=`MAKEFLAGS= $(MAKE) -C perl -s --no-print-directory instlibdir` && \
            sed -e '1{' \
                [... snipped other substitutions ...]
                -e 's/@@GIT_VERSION@@/$(GIT_VERSION)/g' \
                $@.perl >$@+ && \
            chmod +x $@+ && \
            mv $@+ $@
    
    例如,如果您查看的开头附近,您将看到:

    $VERSION = '@@GIT_VERSION@@';
    
在我的源代码树中,此规则已编译为一个文件
git svn
,其中包含以下行:

    $VERSION = '1.7.11.rc0.55.gb2478aa';
因此,如果我检查本地编译的git svn的版本,我会看到:

    $ git svn --version
    git-svn version 1.7.11.rc0.55.gb2478aa (svn 1.6.17)
然而,如果我运行基于rpm的安装,我会看到:

    $ /usr/bin/git svn --version
    git-svn version 1.7.6.5 (svn 1.6.17)
最后一个输出表明,即使源代码是从发布的tarball编译的,而tarball在
.git/
子目录中不包含任何版本控制元数据,该方法仍然有效。这意味着版本字符串很好地区分了稳定版本和开发快照


虽然
git svn
是一个Perl脚本,但显然同样的替换方法也适用于您的shell脚本。

也有一些指针+1我非常喜欢这种方法,并欣赏这种令人敬畏的解释,但对于一个包含大约100行的脚本来说,这是非常有用的。。。还是很好的答案!