我们使用git来管理我们的项目,每个都有一个分支: 开发 分期 生产
我想使用git标签来管理软件的版本。据我所知,如果我在一个分支上并添加一些提交,那么我必须运行: git tag 1.0
使用我们最新的版本号重新调整1.0,然后我可以使用以下命令推送标记: git push origin 1.0
我可以用以下内容更新分支: git push --tags
但我现在如何重复使用标签?如果我将更多代码提交到我的本地存储库并希望它很容易成为1.0版本?或者你只是添加一个新的标签,如1.1?
此外,如果我的同事在其本地存储库中使用相同的标记名称并且我们都推送相同标记的代码,会发生什么?
最后,如果我们在没有运行git标记来标记提交的情况下意外推送我们的代码会发生什么。
我并没有真正了解标签是如何工作的,我认为它们会像标记博客文章或其他东西一样工作 - 您可以使用相同的标记标记许多不同的提交并重复使用标记等类似于分支我想。
答案 0 :(得分:9)
但我现在如何重复使用标签?如果我将更多代码提交到我的本地存储库并希望它很容易成为1.0版本?或者你只是添加一个新的标签,如1.1?
您可以使用git tag -d 1.0
删除代码,然后使用git push origin :refs/tags/1.0
将其删除。
但最佳做法是仅标记版本,然后在创建标记的位置为该版本创建维护分支。在那个分支上,你推送修复程序,并在生成更新版本时标记1.1,1.2,....在将代码提供给客户后移动标签是不好的做法。
此外,如果我的同事在其本地存储库中使用相同的标记名称并且我们都推送相同标记的代码,会发生什么?
我很确定推送标签的第二个人会收到错误。亲自尝试看看会发生什么:
git checkout -b testbranch
git tag test1
git push origin tag test1
git tag -d test1
touch testfile
git add testfile
git commit -m "Added testfile"
git push origin testbranch
git tag test1
git push origin tag test1
最后,如果我们在没有运行git标记来标记提交的情况下意外推送我们的代码会发生什么。
在推送提交后,您应该推送标签。你不能同时做两件事(git push --tags
不推送提交,只推送标签)。如果先按下标签,遥控器将有悬空参考,直到您按下提交。所以你应该这样做
git push origin master
git push origin --tags
或类似的,视您的情况而定。
我并没有真正了解标签是如何工作的,我认为它们会像标记博客文章或其他东西一样工作 - 您可以使用相同的标记标记许多不同的提交并重复使用标记等类似于分支我想。
标签就像提交标签一样,因此您可以将某些提交标记为“特殊”。最常见的是,这用于标记版本,因此如果客户报告错误,您可以随时返回并准确查看该版本中的内容。
答案 1 :(得分:8)
我之前遇到过类似的问题。以下是我发现的有用信息:
答案 2 :(得分:2)
标记信息的绝佳资源位于gitref.org
请勿尝试重复使用版本号。最好是去1.1或1.0a。这在man page中详细讨论。
对于你的问题:
最后,如果我们发生了什么 不小心推了我们的代码 运行git标签来标记提交?
您可以通过将commit ref放在命令中来标记旧提交:
git tag 1.1 HEAD~3
答案 3 :(得分:2)
简单地回答标题问题,我想出了一个半专业的解决方案(可能对某些人有用),它会自动用我指向的git版本标签标记我的代码,所以我没有必须(记得)每次构建时手动更新版本号。我目前在一个小组(< 5开发人员)工作,我们的配置管理仍在进行中。但在此成熟之前,这是一个适合我的解决方案。
高级视图,这些是以下步骤:
我编写了一个脚本,用于查询当前版本标记(using the beginning parts of this answer)的git。
自动生成#define
提取的版本及其部分的头文件。
#include
这个头文件(不是存储库的一部分),瞧,版本是自动包含的,没有任何人工输入。更详细:
我目前使用的是3号版本控制方案, major.minor.build ,其中 build 可能是一个字符串(例如,v1.8.3b)。请注意,使用echo -e
打印换行符对我有用,但也许printf
is the better option
# queries git for the version tag I'm currently pointed at. Throughout SO there
# are different versions of this command, but this one works for me. And in fact
# all my tags are annotated, so I could just use "git describe"
VERSION=`git describe --tags`
# replace all the '.' with ' ', then split the array based on the spaces.
# Obviously this will have its limitations if there are spaces in your
# version tag, or maybe even wildcard characters, but that should never
# be the case for me
VER_ARRAY=(${VERSION//./ })
# pull out the major, minor, and build components. These can be used to
# pre-processor check different versions of my code for certain compatibility,
# should the need arise
V_MAJOR=${VER_ARRAY[0]}
V_MINOR=$(VER_ARRAY[1]}
V_BUILD=${VER_ARRAY[2]}
# all of my build tags are preceded by a 'v', so remove that simply by taking
# the substring starting at position 1
V_MAJOR=${V_MAJOR:1}
# define the path and header file
VERSION_HEADER=./path/to/codeVer.h
# write these to file. > creates the file and >> appends to the file
echo -e "// Auto-generated version header on " `date` "\n\n" > $VERSION_HEADER
echo -e "#define MY_CODE_VERSION \""$VERSION"\"\n\n" >> $VERSION_HEADER
echo -e "#define MY_CODE_MAJOR "$V_MAJOR >> $VERSION_HEADER
echo -e "#define MY_CODE_MINOR "$V_MINOR >> $VERSION_HEADER
echo -e "#define MY_CODE_BUILD \""$V_BUILD"\"\n\n" >> $VERSION_HEADER
在我的makefile顶部,我有$(shell ./genVer.sh)
。这告诉make运行shell命令,./genVer.sh
是脚本的路径和名称。更好的方法是为脚本创建一个.PHONY
目标,然后将该目标作为相关目标的先决条件,但我有很多目标,这是一个单行捕获所有
现在,在所有相关的源/头文件中,我只需要
#include "codeVer.h"
....
#ifndef MY_CODE_VERSION
// although if codeVer.h cannot be found we will get a fatal error before
// this warning
#warning "Unable to find code version, defaulting to v0.0.0"
#define MY_CODE_VERSION "v0.0.0"
#endif
现在,只要我make
,就会提取当前版本,生成标题,我的代码#include
是文件,我得到正确的版本号而不做任何手工操作。请注意,这不仅适用于最新版本,如果您签出旧版本的标签,这也可以正常工作(当然,提供实现此版本的更改是在该版本中)。
这确实有它的缺点。最值得注意的是
codeVer.h
添加到.gitignore列表中,因为我不想在回购中跟踪它。这意味着您可能会将代码丢失给缺少此文件的人,并且他们不知道它是什么版本。但是如果他们正在使用git(就像他们应该做的那样!)并且他们git pull/clone
你的东西,那么无论如何所有的标签都会附带它。make clean
也会生成此文件(这似乎与直觉相反),但如果您以正确的方式执行并使用上述.PHONY
目标,则不会出现问题。< / LI>