Git 的修订版号相当于什么?

发布于 2024-10-01 05:33:29 字数 214 浏览 2 评论 0原文

我们在工作中使用 SVN,但对于我的个人项目,我决定使用 Git。所以我昨天安装了 Git,我想知道 Git 中的修订号相当于什么。

假设我们使用的是 3.0.8 版本,每个错误修复都有自己的修订号,当我们谈论此错误修复时可以使用。那么,如果我将 Git 中的代码标记为 3.0.8,那么我可以使用什么作为修订号或其他更详细的标识?我发现哈希值对人类来说不太友好。

We use SVN at work, but for my personal projects I decided to use Git. So I installed Git yesterday, and I wonder what is the revision number equivalent in Git.

Let's say we work on version 3.0.8 and every bug fix has its own revision number we can use when we talk about this bug fix. So if I tag the code in Git to 3.0.8 what then I can use as a revision number or some other more detailed kind of identification? I find the hash not so user friendly for humans.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(19

余生共白头 2024-10-08 05:33:29

使用现代 Git(我的例子是 1.8.3.4)并且不使用分支,您可以这样做:

$ git rev-list --count HEAD
68

但这有各种各样的问题,并且可能不容易重现或容易返回到提交哈希(如果您需要)。因此,请尽量避免使用它或仅将其用作提示。

With modern Git (1.8.3.4 in my case) and not using branches you can do:

$ git rev-list --count HEAD
68

But this has all kinds of issues and might not be easy to reproduce or easy to get back to the commit hash in case you need to. So try to avoid it or use it only as a hint.

微暖i 2024-10-08 05:33:29

对您来说是好消息还是坏消息,该哈希值就是修订号。当我从 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

这样,您就有了一个单独的特定于版本的错误修复分支,但您仍然将错误修复更改拉入主开发主干。

Good or bad news for you, that hash IS the revision number. I also had trouble with this when I made the switch from SVN to git.

You can use "tagging" in git to tag a certain revision as the "release" for a specific version, making it easy to refer to that revision. Check out this blog post.

The key thing to understand is that git cannot have revision numbers - think about the decentralized nature. If users A and B are both committing to their local repositories, how can git reasonably assign a sequential revision number? A has no knowledge of B before they push/pull each other's changes.

Another thing to look at is simplified branching for bugfix branches:

Start with a release: 3.0.8. Then, after that release, do this:

git branch bugfixes308

This will create a branch for bugfixes. Checkout the branch:

git checkout bugfixes308

Now make any bugfix changes you want.

git commit -a

Commit them, and switch back to the master branch:

git checkout master

Then pull in those changes from the other branch:

git merge bugfixes308

That way, you have a separate release-specific bugfix branch, but you're still pulling the bugfix changes into your main dev trunk.

也只是曾经 2024-10-08 05:33:29

git describe 命令创建一个稍微更容易理解的名称指的是特定的提交。例如,从文档中:

使用 git.git 当前树之类的东西,我得到:

[torvalds@g5 git]$ git 描述父级
v1.0.4-14-g2414721

即我的“父”分支的当前头基于 v1.0.4,但由于它上面有一些提交,所以描述添加了额外提交的数量(“14”)和缩写的对象名称最后是提交本身(“2414721”)。

只要您使用合理命名的标签来标记特定版本,就可以认为这大致相当于 SVN“修订号”。

The git describe command creates a slightly more human readable name that refers to a specific commit. For example, from the documentation:

With something like git.git current tree, I get:

[torvalds@g5 git]$ git describe parent
v1.0.4-14-g2414721

i.e. the current head of my "parent" branch is based on v1.0.4, but since it has a few commits on top of that, describe has added the number of additional commits ("14") and an abbreviated object name for the commit itself ("2414721") at the end.

As long as you use sensibly named tags to tag particular releases, this can be considered to be roughly equivalent to a SVN "revision number".

护你周全 2024-10-08 05:33:29

其他海报是对的,没有“修订号”。

我认为最好的方法是使用标签来“发布”!

但我使用以下内容来伪造修订号(只是为了让客户看到修订和进度,因为他们希望从 git 获得与 subversion 相同的不断增加的修订)。

显示“HEAD”的“当前修订版”是通过使用以下

命令模拟的: git rev-list HEAD | wc -l

但是如果客户告诉我“revision”1302 有错误怎么办?

为此,我将以下内容添加到 ~/.gitconfig 的 [alias] 部分:

show-rev-number = !sh -c 'git rev-list --reverse HEAD |荷兰 | awk \"{ if(\\$1 == "$0") { print \\$2 }}\"'

使用 git show-rev-number 1302 将打印 哈希“修订”:)

我做了一个博客文章(德语)关于不久前的“技术”。

The other posters are right, there is no "revision-number".

I think the best way is to use Tags for "releases"!

But I made use of the following to fake revision numbers (just for clients to see revisions and the progress, as they wanted to have the same increasing revisions from git as they where use to by subversion).

Show the "current revision" of "HEAD" is simulated by using this:

git rev-list HEAD | wc -l

But what if the client tells me that there is a bug in "revision" 1302 ?

For this I added the following to the [alias] section of my ~/.gitconfig:

show-rev-number = !sh -c 'git rev-list --reverse HEAD | nl | awk \"{ if(\\$1 == "$0") { print \\$2 }}\"'

using git show-rev-number 1302 will then print the hash for the "revision" :)

I made a Blog Post (in german) about that "technique" some time ago.

上课铃就是安魂曲 2024-10-08 05:33:29

Git 没有与 subversion 相同的修订号概念。相反,通过提交创建的每个给定快照都由 SHA1 校验和标记。为什么?在分布式版本控制系统中运行 revno 存在几个问题:

首先,由于开发根本不是线性的,因此数字的附加问题很难以满足程序员需求的方式解决。当数字的行为不符合您的预期时,尝试通过添加数字来解决此问题可能很快就会出现问题。

其次,修订号可能在不同的机器上生成。这使得数字同步变得更加困难 - 特别是因为连接是单向的;您甚至可能无法访问拥有该存储库的所有计算机。

第三,在 git 中,在某种程度上是由现已不复存在的 OpenCM 系统开创的,提交的身份(提交是什么)相当于其名称(SHA id)。这个命名=身份的概念非常强烈。当您手头有提交名称时,它还会以不可伪造的方式标识该提交。这反过来又可以让您使用 git fsck 命令检查所有提交回到第一个初始提交是否损坏。

现在,由于我们有修订版的 DAG(有向无环图)并且它们构成了当前树,因此我们需要一些工具来解决您的问题:我们如何区分不同的版本。首先,如果给定的前缀(例如 1516bd)唯一标识您的提交,您可以省略部分哈希值。但这也是相当做作的。相反,技巧是使用标签和/或分支。标签或分支类似于您附加到给定提交 SHA1-id 的“黄色便笺”。本质上,标签是不移动的,而当新的提交提交到分支的 HEAD 时,分支就会移动。有多种方法可以引用标签或分支周围的提交,请参阅 git-rev-parse 的手册页。

通常,如果您需要处理特定的代码片段,那么该代码片段正在进行更改,因此应该是一个具有特定主题名称的分支。创建大量分支(每个程序员 20-30 个分支并非闻所未闻,其中发布了 4-5 个分支供其他人使用)是有效 git 的秘诀。每一项工作都应该作为自己的分支开始,然后在测试时合并。未发布的分支可以完全重写,这部分破坏历史就是 git 的力量。

当改变被主人接受时,它就会冻结并成为考古学。此时,您可以对其进行标记,但更常见的是通过 sha1 和在错误跟踪器或问题跟踪器中对特定提交进行引用。标签往往保留用于版本升级和维护分支(对于旧版本)的分支点。

Git does not have the same concept of revision numbers as subversion. Instead each given snapshot made with a commit is tagged by a SHA1 checksum. Why? There are several problems with a running revno in a distributed version control system:

First, since development is not linear at all, the attachment of a number is rather hard as a problem to solve in a way which will satisfy your need as a programmer. Trying to fix this by adding a number might quickly become problematic when the number does not behave as you expect.

Second, revision numbers may be generated on different machines. This makes synchronization of numbers much harder - especially since connectivity is one-way; you may not even have access to all machines that has the repository.

Third, in git, somewhat pioneered by the now defunct OpenCM system, the identity of a commit (what the commit is) is equivalent to its name (the SHA id). This naming = identity concept is very strong. When you sit with a commit name in hand it also identifies the commit in an unforgeable way. This in turn lets you check all of your commits back to the first initial one for corruption with the git fsck command.

Now, since we have a DAG (Directed Acyclic Graph) of revisions and these constitute the current tree, we need some tools to solve your problem: How do we discriminate different versions. First, you can omit part of the hash if a given prefix, 1516bd say, uniquely identifies your commit. But this is also rather contrived. Instead, the trick is to use tags and or branches. A tag or branch is akin to a "yellow stick it note" you attach to a given commit SHA1-id. Tags are, in essence, meant to be non-moving whereas a branch will move when new commits are made to its HEAD. There are ways to refer to a commit around a tag or branch, see the man page of git-rev-parse.

Usually, if you need to work on a specific piece of code, that piece is undergoing changes and should as such be a branch with a saying topic name. Creating lots of branches (20-30 per programmer is not unheard of, with some 4-5 published for others to work on) is the trick for effective git. Every piece of work should start as its own branch and then be merged in when it is tested. Unpublished branches can be rewritten entirely and this part of destroying history is a force of git.

When the change is accepted into master it somewhat freezes and becomes archeology. At that point, you can tag it, but more often a reference to the particular commit is made in a bug tracker or issue tracker via the sha1 sum. Tags tend to be reserved for version bumps and branch points for maintenance branches (for old versions).

稀香 2024-10-08 05:33:29

如果您有兴趣,我会从 git infos 此处 自动管理版本号,格式为

<major>.<minor>.<patch>-b<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)

If you're interested, I managed version numbers automatically from git infos here under the format

<major>.<minor>.<patch>-b<build>

where build is the total number of commits. You'll see the interesting code in the Makefile. Here is the relevant part to access the different part of the version number:

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)
呆橘 2024-10-08 05:33:29

Bash 函数:

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

A Bash function:

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}
}

outputs something like

$ git_rev
2:0f8e14e:20130220

That is

commit_count:last_abbrev_commit:date_YYmmdd
你穿错了嫁妆 2024-10-08 05:33:29

提交的 SHA1 哈希 相当于 Subversion 修订版号。

The SHA1 hash of the commit is the equivalent to a Subversion revision number.

无需解释 2024-10-08 05:33:29

这是我根据其他解决方案在 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

This is what I did in my makefile based on others solutions. Note not only does this give your code a revision number, it also appends the hash which allows you to recreate the release.

# 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
浅暮の光 2024-10-08 05:33:29

使用 git hash 作为构建号的问题是它不是单调递增的。 OSGi 建议对内部版本号使用时间戳。看起来分支的提交数量可以用来代替颠覆或强制更改数量。

The problem with using the git hash as the build number is that it's not monotonically increasing. OSGi suggests using a time-stamp for the build number. It looks like the number of commits to the branch could be used in place of the subversion or perforce change number.

一个人的夜不怕黑 2024-10-08 05:33:29

我编写了一些 PowerShell 实用程序,用于从 Git 检索版本信息并简化标记

功能:Get-LastVersion、Get-Revision、Get-NextMajorVersion、Get-NextMinorVersion、TagNextMajorVersion、TagNextMinorVersion:

# 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
}

I wrote some PowerShell utilities for retrieving version information from Git and simplifying tagging

functions: Get-LastVersion, Get-Revision, Get-NextMajorVersion, Get-NextMinorVersion, TagNextMajorVersion, TagNextMinorVersion:

# 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
}
简单 2024-10-08 05:33:29

每个提交都有一个唯一的哈希值。除此之外,git 中没有修订号。如果您想要更多的用户友好性,您必须自己标记提交。

Each commit has a unique hash. Other than that there are no revision numbers in git. You'll have to tag commits yourself if you want more user-friendliness.

夏の忆 2024-10-08 05:33:29

我只想指出另一种可能的方法 - 那就是使用 git git-notes(1),自 v 1.6.6 起存在(自我注释 - Git)(我使用的是 git 版本 1.7.9.5)。

基本上,我使用 git svn 克隆具有线性历史记录的 SVN 存储库(没有标准布局,没有分支,没有标签),并且我想比较克隆的 git 中的修订号> 存储库。这个 git 克隆默认情况下没有标签,所以我无法使用 gitdescribe。这里的策略可能只适用于线性历史 - 不确定合并等会如何结果;但这是基本策略:

  • 向 git rev-list 询问所有提交历史记录的列表
    • 由于 rev-list 默认情况下按“逆时间顺序”排列,因此我们将使用其 --reverse 开关来获取按最旧的顺序排序的提交列表< /里>
  • 使用 bash shell 来
    • 在每次提交时增加一个计数器变量作为修订计数器,
    • 为每次提交生成并添加“临时”git 注释
  • 然后,使用 git log-- 来浏览日志Notes,这也会转储提交的注释,在这种情况下将是“修订号”
  • 完成后,删除临时注释(注意:我不确定这些注释是否已提交;它们并没有真正显示在 git status 中)

首先,让我们注意 git 有一个默认的注释位置 - 但您也可以指定一个 >ref(erence) 用于注释 - 它将它们存储在 .git 下的不同目录中;例如,在 git repo 文件夹中,您可以调用 git Notes get-ref 来查看该目录:

$ git notes get-ref
refs/notes/commits
$ git notes --ref=whatever get-ref
refs/notes/whatever

需要注意的是,如果您 < code>notes add 带有 --ref,之后您还必须再次使用该引用 - 否则您可能会收到类似“找不到对象 XXX 的注释...< /em>”。

对于此示例,我选择将注释的 ref 称为“linrev”(用于线性修订) - 这也意味着该过程不太可能干扰已有的注释。我还使用 --git-dir 开关,因为作为 git 新手,我在理解它时遇到了一些问题 - 所以我想“稍后记住” <代码>:);我还使用 --no-pager 在使用 git log 时抑制 less 的产生。

因此,假设您位于一个目录中,其子文件夹 myrepo_git 是一个 git 存储库;可以这样做:

### check for already existing notes:

$ git --git-dir=./myrepo_git/.git notes show
# error: No note found for object 04051f98ece25cff67e62d13c548dacbee6c1e33.
$ git --git-dir=./myrepo_git/.git notes --ref=linrev show
# error: No note found for object 04051f98ece25cff67e62d13c548dacbee6c1e33.

### iterate through rev-list three, oldest first,
### create a cmdline adding a revision count as note to each revision

$ ix=0; for ih in $(git --git-dir=./myrepo_git/.git rev-list --reverse HEAD); do \
  TCMD="git --git-dir=./myrepo_git/.git notes --ref linrev"; \
  TCMD="$TCMD add $ih -m \"(r$((++ix)))\""; \
  echo "$TCMD"; \
  eval "$TCMD"; \
done

# git --git-dir=./myrepo_git/.git notes --ref linrev add 6886bbb7be18e63fc4be68ba41917b48f02e09d7 -m "(r1)"
# git --git-dir=./myrepo_git/.git notes --ref linrev add f34910dbeeee33a40806d29dd956062d6ab3ad97 -m "(r2)"
# ...
# git --git-dir=./myrepo_git/.git notes --ref linrev add 04051f98ece25cff67e62d13c548dacbee6c1e33 -m "(r15)"

### check status - adding notes seem to not affect it:

$ cd myrepo_git/
$ git status
# # On branch master
# nothing to commit (working directory clean)
$ cd ../

### check notes again:

$ git --git-dir=./myrepo_git/.git notes show
# error: No note found for object 04051f98ece25cff67e62d13c548dacbee6c1e33.
$ git --git-dir=./myrepo_git/.git notes --ref=linrev show
# (r15)

### note is saved - now let's issue a `git log` command, using a format string and notes:

$ git --git-dir=./myrepo_git/.git --no-pager log --notes=linrev --format=format:"%h: %an: %ad:  >>%s<< %N" HEAD
# 04051f9: _user_: Sun Apr 21 18:29:02 2013 +0000:  >>test message 15 << (r15)
# 77f3902: _user_: Sun Apr 21 18:29:00 2013 +0000:  >>test message 14<< (r14)
# ...
# 6886bbb: _user_: Sun Apr 21 17:11:52 2013 +0000:  >>initial test message 1<< (r1)

### test git log with range:

$ git --git-dir=./myrepo_git/.git --no-pager log --notes=linrev --format=format:"%h: %an: %ad:  >>%s<< %N" HEAD^..HEAD
# 04051f9: _user_: Sun Apr 21 18:29:02 2013 +0000:  >>test message 15 << (r15)

### erase notes - again must iterate through rev-list

$ ix=0; for ih in $(git --git-dir=./myrepo_git/.git rev-list --reverse HEAD); do \
  TCMD="git --git-dir=./myrepo_git/.git notes --ref linrev"; \
  TCMD="$TCMD remove $ih"; \
  echo "$TCMD"; \
  eval "$TCMD"; \
done
# git --git-dir=./myrepo_git/.git notes --ref linrev remove 6886bbb7be18e63fc4be68ba41917b48f02e09d7
# Removing note for object 6886bbb7be18e63fc4be68ba41917b48f02e09d7
# git --git-dir=./myrepo_git/.git notes --ref linrev remove f34910dbeeee33a40806d29dd956062d6ab3ad97
# Removing note for object f34910dbeeee33a40806d29dd956062d6ab3ad97
# ...
# git --git-dir=./myrepo_git/.git notes --ref linrev remove 04051f98ece25cff67e62d13c548dacbee6c1e33
# Removing note for object 04051f98ece25cff67e62d13c548dacbee6c1e33

### check notes again:

$ git --git-dir=./myrepo_git/.git notes show
# error: No note found for object 04051f98ece25cff67e62d13c548dacbee6c1e33.
$ git --git-dir=./myrepo_git/.git notes --ref=linrev show
# error: No note found for object 04051f98ece25cff67e62d13c548dacbee6c1e33.

因此,至少在我没有分支的完全线性历史的特定情况下,修订号似乎与这种方法相匹配 - 另外,这种方法似乎允许使用 git log 。具有修订范围,同时仍然获得正确的修订号 - YMMV 具有不同的上下文,但是......

希望这对某人有帮助,
干杯!


编辑:好的,这里更容易一些,使用上述循环的 git 别名,称为 setlinrev 和 unsetlinrev ;在 git 存储库文件夹中时,执行 (注意令人讨厌的 bash 转义,另请参阅 #16136745 - 添加包含分号的 Git 别名):

cat >> .git/config <<"EOF"
[alias]
  setlinrev = "!bash -c 'ix=0; for ih in $(git rev-list --reverse HEAD); do \n\
      TCMD=\"git notes --ref linrev\"; \n\
      TCMD=\"$TCMD add $ih -m \\\"(r\\$((++ix)))\\\"\"; \n\
      #echo \"$TCMD\"; \n\
      eval \"$TCMD\"; \n\
    done; \n\
    echo \"Linear revision notes are set.\" '"

  unsetlinrev = "!bash -c 'ix=0; for ih in $(git rev-list --reverse HEAD); do \n\
      TCMD=\"git notes --ref linrev\"; \n\
      TCMD=\"$TCMD remove $ih\"; \n\
      #echo \"$TCMD\"; \n\
      eval \"$TCMD 2>/dev/null\"; \n\
    done; \n\
    echo \"Linear revision notes are unset.\" '"
EOF

...这样你就可以简单地调用 git setlinrev在尝试做涉及线性修订笔记的日志之前;完成后使用 git unsetlinrev 删除这些注释; git repo 目录内部的一个示例:

$ git log --notes=linrev --format=format:"%h: %an: %ad:  >>%s<< %N" HEAD^..HEAD
04051f9: _user_: Sun Apr 21 18:29:02 2013 +0000:  >>test message 15 <<

$ git setlinrev
Linear revision notes are set.
$ git log --notes=linrev --format=format:"%h: %an: %ad:  >>%s<< %N" HEAD^..HEAD
04051f9: _user_: Sun Apr 21 18:29:02 2013 +0000:  >>test message 15 << (r15)
$ git unsetlinrev
Linear revision notes are unset.

$ git log --notes=linrev --format=format:"%h: %an: %ad:  >>%s<< %N" HEAD^..HEAD
04051f9: _user_: Sun Apr 21 18:29:02 2013 +0000:  >>test message 15 <<

shell 完成这些别名所需的时间取决于存储库历史记录的大小。

I'd just like to note another possible approach - and that is by using git git-notes(1), in existence since v 1.6.6 (Note to Self - Git) (I'm using git version 1.7.9.5).

Basically, I used git svn to clone an SVN repository with linear history (no standard layout, no branches, no tags), and I wanted to compare revision numbers in the cloned git repository. This git clone doesn't have tags by default, so I cannot use git describe. The strategy here likely would work only for linear history - not sure how it would turn out with merges etc.; but here is the basic strategy:

  • Ask git rev-list for list of all commit history
    • Since rev-list is by default in "reverse chronological order", we'd use its --reverse switch to get list of commits sorted by oldest first
  • Use bash shell to
    • increase a counter variable on each commit as a revision counter,
    • generate and add a "temporary" git note for each commit
  • Then, browse the log by using git log with --notes, which will also dump a commit's note, which in this case would be the "revision number"
  • When done, erase the temporary notes (NB: I'm not sure if these notes are committed or not; they don't really show in git status)

First, let's note that git has a default location of notes - but you can also specify a ref(erence) for notes - which would store them in a different directory under .git; for instance, while in a git repo folder, you can call git notes get-ref to see what directory that will be:

$ git notes get-ref
refs/notes/commits
$ git notes --ref=whatever get-ref
refs/notes/whatever

The thing to be noted is that if you notes add with a --ref, you must also afterwards use that reference again - otherwise you may get errors like "No note found for object XXX...".

For this example, I have chosen to call the ref of the notes "linrev" (for linear revision) - this also means it is not likely the procedure will interfere with already existing notes. I am also using the --git-dir switch, since being a git newbie, I had some problems understanding it - so I'd like to "remember for later" :); and I also use --no-pager to suppress spawning of less when using git log.

So, assuming you're in a directory, with a subfolder myrepo_git which is a git repository; one could do:

### check for already existing notes:

$ git --git-dir=./myrepo_git/.git notes show
# error: No note found for object 04051f98ece25cff67e62d13c548dacbee6c1e33.
$ git --git-dir=./myrepo_git/.git notes --ref=linrev show
# error: No note found for object 04051f98ece25cff67e62d13c548dacbee6c1e33.

### iterate through rev-list three, oldest first,
### create a cmdline adding a revision count as note to each revision

$ ix=0; for ih in $(git --git-dir=./myrepo_git/.git rev-list --reverse HEAD); do \
  TCMD="git --git-dir=./myrepo_git/.git notes --ref linrev"; \
  TCMD="$TCMD add $ih -m \"(r$((++ix)))\""; \
  echo "$TCMD"; \
  eval "$TCMD"; \
done

# git --git-dir=./myrepo_git/.git notes --ref linrev add 6886bbb7be18e63fc4be68ba41917b48f02e09d7 -m "(r1)"
# git --git-dir=./myrepo_git/.git notes --ref linrev add f34910dbeeee33a40806d29dd956062d6ab3ad97 -m "(r2)"
# ...
# git --git-dir=./myrepo_git/.git notes --ref linrev add 04051f98ece25cff67e62d13c548dacbee6c1e33 -m "(r15)"

### check status - adding notes seem to not affect it:

$ cd myrepo_git/
$ git status
# # On branch master
# nothing to commit (working directory clean)
$ cd ../

### check notes again:

$ git --git-dir=./myrepo_git/.git notes show
# error: No note found for object 04051f98ece25cff67e62d13c548dacbee6c1e33.
$ git --git-dir=./myrepo_git/.git notes --ref=linrev show
# (r15)

### note is saved - now let's issue a `git log` command, using a format string and notes:

$ git --git-dir=./myrepo_git/.git --no-pager log --notes=linrev --format=format:"%h: %an: %ad:  >>%s<< %N" HEAD
# 04051f9: _user_: Sun Apr 21 18:29:02 2013 +0000:  >>test message 15 << (r15)
# 77f3902: _user_: Sun Apr 21 18:29:00 2013 +0000:  >>test message 14<< (r14)
# ...
# 6886bbb: _user_: Sun Apr 21 17:11:52 2013 +0000:  >>initial test message 1<< (r1)

### test git log with range:

$ git --git-dir=./myrepo_git/.git --no-pager log --notes=linrev --format=format:"%h: %an: %ad:  >>%s<< %N" HEAD^..HEAD
# 04051f9: _user_: Sun Apr 21 18:29:02 2013 +0000:  >>test message 15 << (r15)

### erase notes - again must iterate through rev-list

$ ix=0; for ih in $(git --git-dir=./myrepo_git/.git rev-list --reverse HEAD); do \
  TCMD="git --git-dir=./myrepo_git/.git notes --ref linrev"; \
  TCMD="$TCMD remove $ih"; \
  echo "$TCMD"; \
  eval "$TCMD"; \
done
# git --git-dir=./myrepo_git/.git notes --ref linrev remove 6886bbb7be18e63fc4be68ba41917b48f02e09d7
# Removing note for object 6886bbb7be18e63fc4be68ba41917b48f02e09d7
# git --git-dir=./myrepo_git/.git notes --ref linrev remove f34910dbeeee33a40806d29dd956062d6ab3ad97
# Removing note for object f34910dbeeee33a40806d29dd956062d6ab3ad97
# ...
# git --git-dir=./myrepo_git/.git notes --ref linrev remove 04051f98ece25cff67e62d13c548dacbee6c1e33
# Removing note for object 04051f98ece25cff67e62d13c548dacbee6c1e33

### check notes again:

$ git --git-dir=./myrepo_git/.git notes show
# error: No note found for object 04051f98ece25cff67e62d13c548dacbee6c1e33.
$ git --git-dir=./myrepo_git/.git notes --ref=linrev show
# error: No note found for object 04051f98ece25cff67e62d13c548dacbee6c1e33.

So, at least in my specific case of fully linear history with no branches, the revision numbers seem to match with this approach - and additionally, it seems that this approach will allow using git log with revision ranges, while still getting the right revision numbers - YMMV with a different context, though...

Hope this helps someone,
Cheers!


EDIT: Ok, here it is a bit easier, with git aliases for the above loops, called setlinrev and unsetlinrev; when in your git repository folder, do (Note the nasty bash escaping, see also #16136745 - Add a Git alias containing a semicolon):

cat >> .git/config <<"EOF"
[alias]
  setlinrev = "!bash -c 'ix=0; for ih in $(git rev-list --reverse HEAD); do \n\
      TCMD=\"git notes --ref linrev\"; \n\
      TCMD=\"$TCMD add $ih -m \\\"(r\\$((++ix)))\\\"\"; \n\
      #echo \"$TCMD\"; \n\
      eval \"$TCMD\"; \n\
    done; \n\
    echo \"Linear revision notes are set.\" '"

  unsetlinrev = "!bash -c 'ix=0; for ih in $(git rev-list --reverse HEAD); do \n\
      TCMD=\"git notes --ref linrev\"; \n\
      TCMD=\"$TCMD remove $ih\"; \n\
      #echo \"$TCMD\"; \n\
      eval \"$TCMD 2>/dev/null\"; \n\
    done; \n\
    echo \"Linear revision notes are unset.\" '"
EOF

... so you can simply invoke git setlinrev before trying to do log involving linear revision notes; and git unsetlinrev to delete those notes when you're done; an example from inside the git repo directory:

$ git log --notes=linrev --format=format:"%h: %an: %ad:  >>%s<< %N" HEAD^..HEAD
04051f9: _user_: Sun Apr 21 18:29:02 2013 +0000:  >>test message 15 <<

$ git setlinrev
Linear revision notes are set.
$ git log --notes=linrev --format=format:"%h: %an: %ad:  >>%s<< %N" HEAD^..HEAD
04051f9: _user_: Sun Apr 21 18:29:02 2013 +0000:  >>test message 15 << (r15)
$ git unsetlinrev
Linear revision notes are unset.

$ git log --notes=linrev --format=format:"%h: %an: %ad:  >>%s<< %N" HEAD^..HEAD
04051f9: _user_: Sun Apr 21 18:29:02 2013 +0000:  >>test message 15 <<

The time it would take the shell to complete these aliases, would depend on the size of the repository history.

因为看清所以看轻 2024-10-08 05:33:29

对于拥有 Ant 构建过程的人,您可以在 git 上为项目生成版本号使用此目标:

<target name="generate-version">

    <exec executable="git" outputproperty="version.revisions">
        <arg value="log"/>
        <arg value="--oneline"/>
    </exec>

    <resourcecount property="version.revision" count="0" when="eq">
        <tokens>
            <concat>
                <filterchain>
                    <tokenfilter>
                        <stringtokenizer delims="\r" />
                    </tokenfilter>
                </filterchain>
            <propertyresource name="version.revisions" />
            </concat>
        </tokens>
    </resourcecount>
    <echo>Revision : ${version.revision}</echo>

    <exec executable="git" outputproperty="version.hash">
        <arg value="rev-parse"/>
        <arg value="--short"/>
        <arg value="HEAD"/>
    </exec>
    <echo>Hash : ${version.hash}</echo>


    <exec executable="git" outputproperty="version.branch">
        <arg value="rev-parse"/>
        <arg value="--abbrev-ref"/>
        <arg value="HEAD"/>
    </exec>
    <echo>Branch : ${version.branch}</echo>

    <exec executable="git" outputproperty="version.diff">
        <arg value="diff"/>
    </exec>

    <condition property="version.dirty" value="" else="-dirty">
        <equals arg1="${version.diff}" arg2=""/>
    </condition>

    <tstamp>
        <format property="version.date" pattern="yyyy-mm-dd.HH:mm:ss" locale="en,US"/>
    </tstamp>
    <echo>Date : ${version.date}</echo>

    <property name="version" value="${version.revision}.${version.hash}.${version.branch}${version.dirty}.${version.date}" />

    <echo>Version : ${version}</echo>

    <echo file="version.properties" append="false">version = ${version}</echo>

</target>

结果如下所示:

generate-version:
    [echo] Generate version
    [echo] Revision : 47
    [echo] Hash : 2af0b99
    [echo] Branch : master
    [echo] Date : 2015-04-20.15:04:03
    [echo] Version : 47.2af0b99.master-dirty.2015-04-20.15:04:03

当您在生成版本号时有未提交的文件时,脏标志就会出现。因为通常,当您构建/打包应用程序时,每个代码修改都必须位于存储库中。

For people who have an Ant build process, you can generate a version number for a project on git with this target:

<target name="generate-version">

    <exec executable="git" outputproperty="version.revisions">
        <arg value="log"/>
        <arg value="--oneline"/>
    </exec>

    <resourcecount property="version.revision" count="0" when="eq">
        <tokens>
            <concat>
                <filterchain>
                    <tokenfilter>
                        <stringtokenizer delims="\r" />
                    </tokenfilter>
                </filterchain>
            <propertyresource name="version.revisions" />
            </concat>
        </tokens>
    </resourcecount>
    <echo>Revision : ${version.revision}</echo>

    <exec executable="git" outputproperty="version.hash">
        <arg value="rev-parse"/>
        <arg value="--short"/>
        <arg value="HEAD"/>
    </exec>
    <echo>Hash : ${version.hash}</echo>


    <exec executable="git" outputproperty="version.branch">
        <arg value="rev-parse"/>
        <arg value="--abbrev-ref"/>
        <arg value="HEAD"/>
    </exec>
    <echo>Branch : ${version.branch}</echo>

    <exec executable="git" outputproperty="version.diff">
        <arg value="diff"/>
    </exec>

    <condition property="version.dirty" value="" else="-dirty">
        <equals arg1="${version.diff}" arg2=""/>
    </condition>

    <tstamp>
        <format property="version.date" pattern="yyyy-mm-dd.HH:mm:ss" locale="en,US"/>
    </tstamp>
    <echo>Date : ${version.date}</echo>

    <property name="version" value="${version.revision}.${version.hash}.${version.branch}${version.dirty}.${version.date}" />

    <echo>Version : ${version}</echo>

    <echo file="version.properties" append="false">version = ${version}</echo>

</target>

The result looks like this:

generate-version:
    [echo] Generate version
    [echo] Revision : 47
    [echo] Hash : 2af0b99
    [echo] Branch : master
    [echo] Date : 2015-04-20.15:04:03
    [echo] Version : 47.2af0b99.master-dirty.2015-04-20.15:04:03

The dirty flag is here when you have file(s) not committed when you generate the version number. Because usually, when you build/package your application, every code modification has to be in the repository.

一刻暧昧 2024-10-08 05:33:29

我们正在使用此命令从 git 获取版本和修订版:

git describe --always --tags --dirty

它返回

  • 当未使用标记时(例如 gcc7b71f),
  • 提交哈希作为修订版)标签名称作为标签上的版本(例如 v2.1.0 code>,用于发布)
  • 标签名称、自上一个标签以来的修订号以及在标签(例如 v5.3.0-88-gcc7b71f)之后的提交哈希值,
  • 与上面相同,加上“脏”标签(如果工作树有本地修改(例如v5.3.0-88-gcc7b71f-dirty

另请参阅:https://www.git-scm.com/docs/git-describe#Documentation/git-describe.txt

We're using this command to get version and revision from git:

git describe --always --tags --dirty

It returns

  • commit hash as revision when no tagging is used (e.g. gcc7b71f)
  • tag name as version when on a tag (e.g. v2.1.0, used for releases)
  • tag name, revision number since last tag and commit hash when after a tag (e.g. v5.3.0-88-gcc7b71f)
  • same as above plus a "dirty" tag if the working tree has local modifications (e.g. v5.3.0-88-gcc7b71f-dirty)

See also: https://www.git-scm.com/docs/git-describe#Documentation/git-describe.txt

乙白 2024-10-08 05:33:29

连同提交的 SHA-1 id、服务器时间的日期和时间会有帮助吗?

像这样的东西:

提交发生在 2013 年 8 月 19 日 11:30:25 将显示为
6886bbb7be18e63fc4be68ba41917b48f02e09d7_19aug2013_113025

Along with the SHA-1 id of the commit, date and time of the server time would have helped?

Something like this:

commit happened at 11:30:25 on 19 aug 2013 would show as
6886bbb7be18e63fc4be68ba41917b48f02e09d7_19aug2013_113025

对你的占有欲 2024-10-08 05:33:29

从 Git 手册来看,标签是这个问题的一个很好的答案:

在 Git 中创建带注释的标签很简单。最简单的方法是
运行 tag 命令时指定 -a:

$ git tag -a v1.4 -m '我的版本 1.4'

$ git tag
v0.1
v1.3
v1.4

查看 2.6 Git 基础知识 - 标记

From the Git manual, tags are a brilliant answer to this issue:

Creating an annotated tag in Git is simple. The easiest way is to
specify -a when you run the tag command:

$ git tag -a v1.4 -m 'my version 1.4'

$ git tag
v0.1
v1.3
v1.4

Check out 2.6 Git Basics - Tagging

还不是爱你 2024-10-08 05:33:29

Visual Studio 的构建后事件

echo  >RevisionNumber.cs static class Git { public static int RevisionNumber =
git  >>RevisionNumber.cs rev-list --count HEAD
echo >>RevisionNumber.cs ; }

Post build event for Visual Studio

echo  >RevisionNumber.cs static class Git { public static int RevisionNumber =
git  >>RevisionNumber.cs rev-list --count HEAD
echo >>RevisionNumber.cs ; }
相守太难 2024-10-08 05:33:29

考虑使用

git-rev-label

提供信息关于 Git 存储库修订版,格式如 master-c73-gabc6bec
可以使用来自 Git 的环境变量和信息填充模板字符串或文件。
有助于提供有关程序版本的信息:分支、标签、提交哈希、
提交计数、脏状态、日期和时间。最有用的事情之一是计数
提交,不考虑合并分支 - 仅第一个父级。

Consider to use

git-rev-label

Gives information about Git repository revision in format like master-c73-gabc6bec.
Can fill template string or file with environment variables and information from Git.
Useful to provide information about version of the program: branch, tag, commit hash,
commits count, dirty status, date and time. One of the most useful things is count of
commits, not taking into account merged branches - only first parent.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文