【问题标题】:What is the Git equivalent for revision number?修订号的 Git 等价物是什么?
【发布时间】:2011-05-06 10:06:53
【问题描述】:

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

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

【问题讨论】:

  • article 是一种可能的解决方案。它可能看起来有点重,但集成到“git log”输出中,除了“git push/pull/fetch”之外不需要其他命令。
  • 不幸的是,来自@DmitryPavlenko 的链接文章在一个死域上:gitsvn.x10.mx。由于没有指明主题,任何人都很难在别处找到它。
  • 注意:git describe 不再需要缩写:见stackoverflow.com/a/41308073/6309
  • 不,劳伦斯·贡萨尔维斯,这不是“如何获取 git 提交计数?”的重复。 - 这是关于版本号,即使提交计数可以摆弄看起来有点相似 - 哈希版本与提交计数有很大不同:-)

标签: git version-control revision-history version-numbering


【解决方案1】:

使用现代 Git(在我的情况下为 1.8.3.4)而不使用分支,您可以这样做:

$ git rev-list --count HEAD
68

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

【讨论】:

  • 考虑使用git rev-list --count --first-parent HEAD
  • 鉴于此信息(数字 68),有没有办法确定重新获取代码的修订版?假设“版本 68”发布到测试环境,继续开发,随后开发人员需要从源代码控制重新获取“版本 68”。他将如何针对特定版本进行克隆?还是我错过了一些关于 Git 的东西,这使得这变得不必要?
  • 请记住,此解决方案会为不同的开发人员产生不同的结果。此外,从“计数”向后计算到提交会为不同的开发人员产生不同的提交!这是因为 Git 的分布式特性,提交在同一时间段内发生在不同的存储库中,但可能不计入git rev-list --count HEAD,具体取决于最后一次推送和拉取的时间。
  • @Jason,David 关于添加--first-parent 的评论是否解决了您的问题?如果有一个同样简单的解决方法或使其更健壮的方法,我不想避免一个看似最简单的解决方案,因为这种情况很少见。
  • @MarkHu,--first-parent 有帮助。只要不进行变基并且始终使用相同的分支来发布版本(当然还有计算这个版本号),我认为可以使用它。不过,我仍然不确定它是否总是唯一标识发布来自的提交。这里有很多事情可能出错......但目前我想不出肯定会打破这一点的事情(鉴于我上面的“只要”陈述)。另一个答案中提到的git describe 方法是要走的路。如果您想要人类可读的内容,请创建一个标签。
【解决方案2】:

git describe 命令创建了一个更易于人类阅读的名称,用于引用特定的提交。例如,来自文档:

使用 git.git current tree 之类的东西,我得到:

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

即我的“父”分支的当前负责人基于 v1.0.4,但由于它有一些提交,因此描述添加了额外提交的数量(“14”)和提交本身的缩写对象名称("2414721") 结尾。

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

【讨论】:

  • 我只想指出,这在您的git 存储库已经有标签的情况下才有效;如果没有,您可能会收到git describe fails with "fatal: No names found, cannot describe anything." - Stack Overflow;这意味着您必须自己设置标签。
  • @sdaau:如果您在脚本或其他内容中使用它并希望git describe 永远不会失败,请使用git describe --always 选项。
  • git describe 的输出能否用于查找源提交,不知何故?我的意思是,没有手动计算日志中的提交。
  • @Lii:“源提交”是什么意思?最近的标签 (v1.0.4) 和最近的提交 id (2414721) 已经是 git describe 输出的一部分。
  • @GregHewgill:是的,谢谢,当我问这个问题时,我没有意识到 "abbreviated object name" 是一个可用于识别提交的值.太棒了!
【解决方案3】:

We're using这个命令从git获取版本和修订:

git describe --always --tags --dirty

返回

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

另见:https://www.git-scm.com/docs/git-describe#Documentation/git-describe.txt

【讨论】:

    【解决方案4】:

    考虑使用

    git-rev-label

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

    【讨论】:

      【解决方案5】:

      为 Visual Studio 发布构建事件

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

      【讨论】:

        【解决方案6】:

        这是我在基于其他解决方案的 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 来避免错误最安全的方法是使用git describe --always --dirty --long --tags,它适用于我能想到的所有情况。
        【解决方案7】:

        对于拥有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
        

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

        【讨论】:

          【解决方案8】:

          我编写了一些 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
          }
          

          【讨论】:

            【解决方案9】:

            在 Git 手册中,标签是这个问题的绝妙答案:

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

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

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

            查看2.6 Git Basics - Tagging

            【讨论】:

            • 太糟糕了,你必须跳过箍来更改默认值:By default, the git push command doesn’t transfer tags to remote servers.
            【解决方案10】:

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

            类似这样的:

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

            【讨论】:

              【解决方案11】:

              一个 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
              

              【讨论】:

              • 这种东西可能很有用,但如果有人对增量版本号感兴趣,他们会交换字段位置,以便(非增量)散列在最后。
              【解决方案12】:

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

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

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

              第三,在 git 中,在某种程度上由现已失效的 OpenCM 系统开创,提交的身份(提交是什么)等同于它的名称(SHA ID)。这个naming = identity 概念非常强大。当您拿着提交名称坐下来时,它还会以不可伪造的方式识别提交。这反过来让您可以使用git fsck 命令检查所有提交回第一个初始提交是否存在损坏。

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

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

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

              【讨论】:

                【解决方案13】:

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

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

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

                显示“HEAD”的“当前版本”是用这个模拟的:

                git rev-list HEAD | wc -l

                但是如果客户告诉我“修订版”1302 中存在错误怎么办?

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

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

                然后使用git show-rev-number 1302 将打印“修订”的散列 :)

                我不久前就该“技术”发了Blog Post (in german)

                【讨论】:

                • @Radek - “有时需要知道 'code change=commit' 修复了什么” - 然后git bisect (link) 是识别何时由谁更改的合适工具。
                • @Radek 是的,这是一个不断增加的数字。它只计算您在 HEAD 上签入的修订。所以每次提交都是一个新的修订。这不适用于不同的分支。
                • 我喜欢你的解决方案。请注意,您可以简化它: show-rev-number = !sh -c 'git rev-list --reverse HEAD | awk NR==$0'
                • @avner 谢谢!很明显,我一生中没有使用很多 awk :)
                • 我不得不使用git rev-list --reverse HEAD | awk "{ print NR }" | tail -n 1
                【解决方案14】:

                我只想指出另一种可能的方法——那就是使用 git git-notes(1),自 v 1.6.6 (Note to Self - Git) 以来就存在(我正在使用 git 版本 1.7.9.5 )。

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

                • 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
                

                需要注意的是,如果您在notes add 中使用--ref,则之后您还必须再次使用该引用 - 否则您可能会收到类似“No note found for object XXX...”。

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

                所以,假设您在一个目录中,有一个子文件夹 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 别名,称为setlinrevunsetlinrev;在您的 git 存储库文件夹中时,执行(注意讨厌的bash 转义,另请参阅#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
                

                ...所以您可以在尝试记录涉及线性修订注释的日志之前简单地调用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 完成这些别名所需的时间取决于存储库历史记录的大小。

                【讨论】:

                  【解决方案15】:

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

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

                  【讨论】:

                    【解决方案16】:

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

                    【讨论】:

                      【解决方案17】:

                      对您来说是好消息还是坏消息,哈希是修订号。当我从 SVN 切换到 git 时,我也遇到了这个问题。

                      您可以在 git 中使用“标记”将某个修订标记为特定版本的“发布”,以便于引用该修订。看看这个blog post

                      要理解的关键是 git 不能有修订号——想想去中心化的性质。如果用户 A 和 B 都提交到他们的本地存储库,git 如何合理地分配一个连续的修订号? A 在相互推/拉对方的更改之前不知道 B。

                      另一个值得关注的是错误修复分支的简化分支:

                      从一个版本开始:3.0.8。然后,在发布之后,执行以下操作:

                      git branch bugfixes308
                      

                      这将为错误修复创建一个分支。结帐分支:

                      git checkout bugfixes308
                      

                      现在进行您想要的任何错误修正更改。

                      git commit -a
                      

                      提交它们,然后切换回主分支:

                      git checkout master
                      

                      然后从另一个分支中提取这些更改:

                      git merge bugfixes308
                      

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

                      【讨论】:

                      • 我知道 hash 是修订号,但我希望它不是 :-))) 感谢您提供非常好的解释和建议来处理它。
                      • 不客气。当我第一次从 SVN 拿起 git 时,我对它感到非常沮丧,但现在我转向了另一种方式......
                      • ALSO,自从我发布这个已经有一段时间了,但请记住,您也可以使用“git checkout -b new_branch_name”来执行“git branch foo”和“git checkout foo”作为单行.
                      • 我是否正确地认为哈希是“真正的”哈希,甚至不是远程顺序的?所以,重要的是,如果错误数据库显示fixed in 547cc3e..c4b2eba,并且您有其他修订,您不知道您的代码是否应该包含修复?! git-central 的 gits 肯定有解决方案?!?!
                      • 在 SVN 中,一个 bug 在 r42 中已修复的事实并不能告诉您在您实际使用分支时它是否也已在 r43 中修复。
                      【解决方案18】:

                      SHA1 hash of the commit 等同于 Subversion 修订号。

                      【讨论】:

                      • 不幸的是,它具有与修订号完全不同的属性。比较长,不会单调增加。猜猜这是为分发付出的代价......
                      • @CodeInChaos:我知道你在说什么,但通常可以使用哈希码的前 6 或 8 个字符来引用 git 提交。
                      • @Radek:它们不能保证是唯一的(尽管如果你发现碰撞,你可以赢得一些名人)。
                      • @Radek 根据en.wikipedia.org/wiki/Collision_attack,散列的 4 个字符你有一个 16 位的 ID,这意味着在一个有 256(=2^(16/2)) 提交的回购中有两个提交具有相同的四字符前缀的可能性为 50%(并且对于 65536 次提交,这是肯定的,因为那时 4 字符 ID 的范围已用尽)。当你添加一个字符时,你有一个 20 位的 ID,这意味着 50% 的阈值是 1024 次提交。但由于这是一个统计参数,因此无法保证此类碰撞不会更早发生。
                      • 由于哈希是基于内容的,所以两次提交是否具有相同的哈希前缀仍然是概率,而不是确定性。在 65536 次提交时,很可能有两个具有相同的四字符前缀,但仍不确定。顺便说一句,完整的哈希还没有发生冲突,但 git 正在处理它:) stackoverflow.com/questions/3475648/…
                      【解决方案19】:

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

                      【讨论】:

                        猜你喜欢
                        • 2021-08-26
                        • 1970-01-01
                        • 2021-04-20
                        • 2017-05-30
                        • 1970-01-01
                        • 1970-01-01
                        • 2010-10-09
                        • 2013-10-01
                        • 2021-11-24
                        相关资源
                        最近更新 更多