我们在工作中使用SVN,但是对于我的个人项目,我决定使用Git。所以昨天我安装了Git,并想知道在Git中等同于修订号的内容是什么。
假设我们正在处理版本3.0.8,每个漏洞修复都有自己的修订号,我们在谈论此漏洞修复时可以使用这个修订号。那么,如果我在Git中将代码标记为3.0.8,那么我可以使用哪个修订号或其他更详细的标识?我认为哈希值对于人类来说不太友好。
我们在工作中使用SVN,但是对于我的个人项目,我决定使用Git。所以昨天我安装了Git,并想知道在Git中等同于修订号的内容是什么。
假设我们正在处理版本3.0.8,每个漏洞修复都有自己的修订号,我们在谈论此漏洞修复时可以使用这个修订号。那么,如果我在Git中将代码标记为3.0.8,那么我可以使用哪个修订号或其他更详细的标识?我认为哈希值对于人类来说不太友好。
使用现代Git(例如我的版本为1.8.3.4),并且不使用分支,您可以执行以下操作:
$ git rev-list --count HEAD
68
但这种方法存在各种问题,可能不容易复制或在需要时回到提交哈希值。因此,请尽量避免使用它或仅将其用作提示。
git rev-list --count --first-parent HEAD
。 - Flimmgit rev-list --count HEAD
中计入。 - Jason--first-parent
的评论是否解决了你的问题?如果有一种同样简单的解决方法或者能够使其更加健壮的方法,我不想因为一种罕见的边缘情况而避开这个看似最简单的解决方案。 - MarkHu对你来说是好消息还是坏消息,那个哈希码就是版本号。当我从SVN转到Git时,我也遇到了这个问题。
你可以在Git中使用“标签”将某个修订版本标记为特定版本的“发布”,使其易于引用该修订版本。请查看此博客文章。
关键是要理解Git不能有修订版本号——考虑去中心化的性质。如果用户A和B都提交到他们各自的本地仓库,Git如何合理地分配顺序修订版本号呢?A在推送/拉取彼此的更改之前不知道B的任何信息。
另一个要看的东西是简化缺陷修复分支的分支:
从发布版本3.0.8开始。然后,在该发布版之后,执行以下操作:
git branch bugfixes308
这将创建一个用于修复错误的分支。检出该分支:
git checkout bugfixes308
现在进行您想要的任何错误修复更改。
git commit -a
提交它们,然后切换回主分支:
git checkout master
然后从另一个分支拉取这些更改:
git merge bugfixes308
这样做,你就有了一个单独的发布特定的 bug 修复分支,但仍然将 bug 修复更改合并到主要的开发主干中。
git log
来做到这一点。 - Cole Tobingit describe
命令可以创建一个稍微更易读的名称,用于指向特定的提交。例如,根据文档:
使用类似 git.git 当前树的东西,我会得到:
[torvalds@g5 git]$ git describe parent v1.0.4-14-g2414721
例如,我的“父”分支当前的头部基于v1.0.4,但因为它在其之上有几个提交,所以 describe 在末尾添加了附加提交数(“14”)和缩写的提交对象名称(“2414721”)。
只要您使用合理命名的标签来标记特定版本,这可以被视为大致等同于 SVN 的“修订号”。
git
代码库中已经有标签的情况下才适用;如果没有,则可能会出现 git describe fails with "fatal: No names found, cannot describe anything." - Stack Overflow 的错误提示,这意味着您需要自己设置标签。 - sdaaugit describe
永远不会失败,请使用git describe --always
选项。 - Greg Hewgillgit describe
的输出能否用于找到源提交?我的意思是,除了手动计算日志中的提交次数之外。 - Liiv1.0.4
)和最新的提交ID(2414721
)都已经包含在git describe输出中。 - Greg Hewgillgit rev-list HEAD | wc -l
但是,如果客户告诉我在"修订版(revision)" 1302中存在一个错误呢?show-rev-number = !sh -c 'git rev-list --reverse HEAD | nl | awk \"{ if(\\$1 == "$0") { print \\$2 }}\"'
然后使用git show-rev-number 1302
将打印出该"修订版(revision)"的哈希值 :)git rev-list --reverse HEAD | awk "{ print NR }" | tail -n 1
。 - Gerry<hash>
,使 git rev-list <hash> | wc -l
显示确切的提交号来确保。 - John McGeheesnr = !sh -c'git rev-list --reverse HEAD | sed -n“$0p”'
- MoonCactusGit没有像Subversion那样的版本号概念。相反,每个通过提交所做的给定快照都被标记为SHA1校验和。为什么?在分布式版本控制系统中,使用运行中的版本号存在几个问题:
首先,由于开发不是线性的,因此给一个数字命名很难解决,以一种满足程序员需求的方式。尝试通过添加数字来解决这个问题时,当数字的行为与您预期的不同时,可能会很快出现问题。
其次,版本号可能在不同机器上生成。这使得数字同步变得更加困难-特别是因为连通性是单向的;您甚至可能无法访问具有存储库的所有机器。
第三,在Git中,某种程度上是由现已不再支持的OpenCM系统首创的,提交的标识(即提交的内容)等同于其名称(SHA ID)。这种命名=标识概念非常强大。当你手持一个提交名称时,它也以无法伪造的方式标识了提交。这反过来让您使用git fsck
命令检查从第一个初始提交开始的所有提交是否存在损坏。
现在,由于我们有一个修订版本的DAG(有向无环图),它们构成了当前的树,所以我们需要一些工具来解决您的问题:如何区分不同版本。首先,如果给定前缀,比如1516bd唯一地标识您的提交,则可以省略哈希的一部分。但这也相当牵强。相反,诀窍是使用标记和/或分支。标记或分支类似于您附加到给定提交SHA1 ID的“黄色便签”。标记本质上是不动的,而分支将在其HEAD添加新提交时移动。有多种方法可以引用标记或分支周围的提交,请参阅git-rev-parse的手册页面。
通常,如果你需要处理特定的代码片段,那么这部分代码正在经历变化,并且应该作为一个具有说明性主题名称的分支。创建大量的分支(每个程序员通常会有20-30个分支,其中一些有4-5个可以供其他人使用)是使用Git进行有效工作的技巧。每个工作部分都应该从自己的分支开始,然后在测试后合并。未发布的分支可以被完全重写,这种销毁历史记录的方式是Git的一种功能。<major>.<minor>.<patch>-b<build>
其中build是提交的总数。您可以在Makefile
中看到有趣的代码。以下是访问版本号不同部分的相关部分:
LAST_TAG_COMMIT = $(shell git rev-list --tags --max-count=1)
LAST_TAG = $(shell git describe --tags $(LAST_TAG_COMMIT) )
TAG_PREFIX = "latex-tutorial-v"
VERSION = $(shell head VERSION)
# OR try to guess directly from the last git tag
#VERSION = $(shell git describe --tags $(LAST_TAG_COMMIT) | sed "s/^$(TAG_PREFIX)//")
MAJOR = $(shell echo $(VERSION) | sed "s/^\([0-9]*\).*/\1/")
MINOR = $(shell echo $(VERSION) | sed "s/[0-9]*\.\([0-9]*\).*/\1/")
PATCH = $(shell echo $(VERSION) | sed "s/[0-9]*\.[0-9]*\.\([0-9]*\).*/\1/")
# total number of commits
BUILD = $(shell git log --oneline | wc -l | sed -e "s/[ \t]*//g")
#REVISION = $(shell git rev-list $(LAST_TAG).. --count)
#ROOTDIR = $(shell git rev-parse --show-toplevel)
NEXT_MAJOR_VERSION = $(shell expr $(MAJOR) + 1).0.0-b$(BUILD)
NEXT_MINOR_VERSION = $(MAJOR).$(shell expr $(MINOR) + 1).0-b$(BUILD)
NEXT_PATCH_VERSION = $(MAJOR).$(MINOR).$(shell expr $(PATCH) + 1)-b$(BUILD)
git_rev ()
{
d=`date +%Y%m%d`
c=`git rev-list --full-history --all --abbrev-commit | wc -l | sed -e 's/^ *//'`
h=`git rev-list --full-history --all --abbrev-commit | head -1`
echo ${c}:${h}:${d}
}
输出类似于
$ git_rev
2:0f8e14e:20130220
那就是
commit_count:last_abbrev_commit:date_YYmmdd
提交的SHA1哈希相当于Subversion的版本号。
这是我根据他人的解决方案在我的makefile中所做的。请注意,这不仅为您的代码提供了修订号,还附加了哈希值,使您能够重新创建发布版本。
# Set the source control revision similar to subversion to use in 'c'
# files as a define.
# You must build in the master branch otherwise the build branch will
# be prepended to the revision and/or "dirty" appended. This is to
# clearly ID developer builds.
REPO_REVISION_:=$(shell git rev-list HEAD --count)
BUILD_BRANCH:=$(shell git rev-parse --abbrev-ref HEAD)
BUILD_REV_ID:=$(shell git rev-parse HEAD)
BUILD_REV_ID_SHORT:=$(shell git describe --long --tags --dirty --always)
ifeq ($(BUILD_BRANCH), master)
REPO_REVISION:=$(REPO_REVISION_)_g$(BUILD_REV_ID_SHORT)
else
REPO_REVISION:=$(BUILD_BRANCH)_$(REPO_REVISION_)_r$(BUILD_REV_ID_SHORT)
endif
export REPO_REVISION
export BUILD_BRANCH
export BUILD_REV_ID
git describe --always --dirty --long --tags
似乎是避免错误的最安全的方法,这适用于我能想到的所有情况。 - MarkHu# Returns the last version by analysing existing tags,
# assumes an initial tag is present, and
# assumes tags are named v{major}.{minor}.[{revision}]
#
function Get-LastVersion(){
$lastTagCommit = git rev-list --tags --max-count=1
$lastTag = git describe --tags $lastTagCommit
$tagPrefix = "v"
$versionString = $lastTag -replace "$tagPrefix", ""
Write-Host -NoNewline "last tagged commit "
Write-Host -NoNewline -ForegroundColor "yellow" $lastTag
Write-Host -NoNewline " revision "
Write-Host -ForegroundColor "yellow" "$lastTagCommit"
[reflection.assembly]::LoadWithPartialName("System.Version")
$version = New-Object System.Version($versionString)
return $version;
}
# Returns current revision by counting the number of commits to HEAD
function Get-Revision(){
$lastTagCommit = git rev-list HEAD
$revs = git rev-list $lastTagCommit | Measure-Object -Line
return $revs.Lines
}
# Returns the next major version {major}.{minor}.{revision}
function Get-NextMajorVersion(){
$version = Get-LastVersion;
[reflection.assembly]::LoadWithPartialName("System.Version")
[int] $major = $version.Major+1;
$rev = Get-Revision
$nextMajor = New-Object System.Version($major, 0, $rev);
return $nextMajor;
}
# Returns the next minor version {major}.{minor}.{revision}
function Get-NextMinorVersion(){
$version = Get-LastVersion;
[reflection.assembly]::LoadWithPartialName("System.Version")
[int] $minor = $version.Minor+1;
$rev = Get-Revision
$next = New-Object System.Version($version.Major, $minor, $rev);
return $next;
}
# Creates a tag with the next minor version
function TagNextMinorVersion($tagMessage){
$version = Get-NextMinorVersion;
$tagName = "v{0}" -f "$version".Trim();
Write-Host -NoNewline "Tagging next minor version to ";
Write-Host -ForegroundColor DarkYellow "$tagName";
git tag -a $tagName -m $tagMessage
}
# Creates a tag with the next major version (minor version starts again at 0)
function TagNextMajorVersion($tagMessage){
$version = Get-NextMajorVersion;
$tagName = "v{0}" -f "$version".Trim();
Write-Host -NoNewline "Tagging next majo version to ";
Write-Host -ForegroundColor DarkYellow "$tagName";
git tag -a $tagName -m $tagMessage
}