热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

Git版本控制工具中自动增加版本号的替代方案

本文讨论了在使用Git进行版本控制时,如何提供类似CVS中自动增加版本号的功能。作者介绍了Git中的其他版本表示方式,如gitdescribe命令,并提供了使用这些表示方式来确定文件更新情况的示例。此外,文章还介绍了启用$Id:$功能的方法,并讨论了一些开发者在使用Git时的需求和使用场景。

I read through a bunch of questions asking about simple source code control tools and Git seemed like a reasonable choice. I have it up and running, and it works well so far. One aspect that I like about CVS is the automatic incrementation of a version number.

我阅读了一些问题,询问简单的源代码控制工具,Git似乎是一个合理的选择。我已经启动并运行,到目前为止它运行良好。我喜欢CVS的一个方面是自动增加版本号。

I understand that this makes less sense in a distributed repository, but as a developer I want/need something like this. Let me explain why:

我理解这在分布式存储库中没有多大意义,但作为开发人员,我想/需要这样的东西。让我解释一下原因:

I use Emacs. Periodically I go through and look for new versions of the Lisp source files for third-party packages. Say I've got a file, foo.el, which, according to the header, is version 1.3; if I look up the latest version and see it's 1.143 or 2.6 or whatever, I know I'm pretty far behind.

我用Emacs。我会定期查找第三方软件包的新版Lisp源文件。假设我有一个文件foo.el,根据标题,它是版本1.3;如果我查看最新版本并看到它是1.143或2.6或其他什么,我知道我已经远远落后了。

If instead I see a couple of 40-character hashes, I won't know which is later or get any idea of how much later it is. I would absolutely hate it if I had to manually check ChangeLogs just to get an idea of how out of date I am.

相反,如果我看到几个40个字符的哈希值,我将不知道哪个是稍后的,或者不知道它后来有多少。如果我不得不手动检查ChangeLogs以了解我是如何过时的,我绝对讨厌它。

As a developer, I want to extend this courtesy, as I see it, to the people that use my output (and maybe I'm kidding myself that anyone is, but let's leave that aside for a moment). I don't want to have to remember to increment the damn number myself every time, or a timestamp or something like that. That's a real PITA, and I know that from experience.

作为一名开发人员,我希望将这种礼貌扩展到使用我的输出的人(也许我在开玩笑说,任何人都是,但让我们暂时搁置一下)。我不想记得每次都自己增加该死的号码,或时间戳或类似的东西。这是一个真正的PITA,我从经验中知道。

So what alternatives do I have? If I can't get an $Id:$ equivalent, how else can I provide what I'm looking for?

那么我有什么替代品呢?如果我不能得到$ Id:$等价物,我还能提供我想要的东西吗?

I should mention that my expectation is that the end user will NOT have Git installed and even if they do, will not have a local repository (indeed, I expect not to make it available that way).

我应该提一下,我的期望是最终用户不会安装Git,即使他们这样做,也不会有本地存储库(事实上,我希望不会以这种方式提供它)。

15 个解决方案

#1


The SHA is just one representation of a version (albeit canonical). The git describe command offers others and does so quite well.

SHA只是版本的一种表示(尽管是规范的)。 git describe命令提供了其他功能,并且做得非常好。

For example, when I run git describe in my master branch of my Java memcached client source, I get this:

例如,当我在我的Java memcached客户端源的主分支中运行git describe时,我得到了:

2.2-16-gc0cd61a

That says two important things:

这说两件重要的事情:

  1. There have been exactly 16 commits in this tree since 2.2
  2. 自2.2以来,这棵树中确实有16次提交

  3. The exact source tree can be displayed on anyone else's clone.
  4. 确切的源树可以显示在任何其他人的克隆上。

Let's say, for example, you packaged a version file with the source (or even rewrote all the content for distribution) to show that number. Let's say that packaged version was 2.2-12-g6c4ae7a (not a release, but a valid version).

例如,假设您使用源打包了一个版本文件(甚至重写了所有要分发的内容)以显示该数字。假设打包版本是2.2-12-g6c4ae7a(不是发行版,而是有效版本)。

You can now see exactly how far behind you are (4 commits), and you can see exactly which 4 commits:

你现在可以确切地看到你有多远(4次提交),你可以看到确切的4次提交:

# The RHS of the .. can be origin/master or empty, or whatever you want.
% git log --pretty=format:"%h %an %s" 2.2-12-g6c4ae7a..2.2-16-gc0cd61a
c0cd61a Dustin Sallings More tries to get a timeout.
8c489ff Dustin Sallings Made the timeout test run on every protocol on every bui
fb326d5 Dustin Sallings Added a test for bug 35.
fba04e9 Valeri Felberg Support passing an expiration date into CAS operations.

#2


By now there is support for $Id:$ in Git. To enable it for file README you would put "README ident" into .gitattributes. Wildcards on file names are supported. See man gitattributes for details.

到目前为止,Git支持$ Id:$。要为文件README启用它,您可以将“README ident”放入.gitattributes。支持文件名上的通配符。有关详细信息,请参阅man gitattributes。

#3


This isn't an unreasonable request from the OP.

这不是OP的无理要求。

My use-case is:

我的用例是:

  1. I use Git for my own personal code, therefore no collaboration with others.
  2. 我使用Git作为我自己的个人代码,因此没有与他人合作。

  3. I keep system Bash scripts in there which might go into /usr/local/bin when they are ready.
  4. 我将系统Bash脚本保留在那里,当它们准备就绪时可能会进入/ usr / local / bin。

I use three separate machines with the same Git repository on it. It would be nice to know what "version" of the file I have currently in /usr/local/bin without having to do a manual "diff -u ".

我使用三台具有相同Git存储库的独立机器。很高兴知道我目前在/ usr / local / bin中的文件的“版本”,而无需在/ usr / local / bin>中执行手册“diff -u

To those of you being negative, remember there are other use cases out there. Not everyone uses Git for collaborative work with the files in the Git repository being their "final" location.

对于那些你消极的人,请记住还有其他用例。不是每个人都使用Git进行协作,将Git存储库中的文件作为其“最终”位置。

Anyway, the way I did it was to create an attributes file in the repository like this:

无论如何,我这样做的方式是在存储库中创建一个属性文件,如下所示:

cat .git/info/attributes
# see man gitattributes
*.sh ident
*.pl ident
*.cgi ident

Then put $Id$ somewhere in the file (I like to put it after the shebang).

然后把$ Id $放在文件的某个地方(我喜欢把它放在shebang之后)。

The commit. Note that this doesn't automatically do the expansion like I expected. You have to re-co the file, for example,

提交。请注意,这不会像我预期的那样自动进行扩展。例如,您必须重新处理该文件

git commit foo.sh
rm foo.sh
git co foo.sh

And then you will see the expansion, for example:

然后你会看到扩展,例如:

$ head foo.sh
#!/bin/sh

# $Id: e184834e6757aac77fd0f71344934b1cd774e6d4 $

Some good information is in How do I enable the ident string for a Git repository?.

一些好的信息在如何为Git存储库启用ident字符串?

#4


Not sure this will ever be in Git. To quote Linus:

不确定这将永远在Git中。引用Linus:

"The whole notion of keyword substitution is just totally idiotic. It's trivial to do "outside" of the actual content tracking, if you want to have it when doing release trees as tar-balls etc."

“关键字替换的整个概念完全是愚蠢的。如果你想在释放树作为tar-ball等时想要它,那么在实际内容跟踪之外”做“是微不足道的。”

It's pretty easy to check the log, though - if you're tracking foo.el's stable branch, you can see what new commits are in the stable branch's log that aren't in your local copy. If you want to simulate CVS's internal version number, you can compare the timestamp of the last commit.

但是,检查日志非常容易 - 如果您正在跟踪foo.el的稳定分支,您可以看到稳定分支日志中的新提交不在本地副本中。如果要模拟CVS的内部版本号,可以比较上次提交的时间戳。

Edit: you should write or use someone else's scripts for this, of course, not do this manually.

编辑:您应该为此编写或使用其他人的脚本,当然,不要手动执行此操作。

#5


As I’ve written before:

正如我之前写的:

Having automatically generated Id tags that show a sensible version number is impossible to do with DSCM tools like Bazaar because everybody’s line of development can be different from all others. So somebody could refer to version “1.41” of a file but your version “1.41” of that file is different.

使用像Bazaar这样的DSCM工具自动生成显示合理版本号的Id标签是不可能的,因为每个人的开发线都可能与其他所有开发线不同。所以有人可以参考文件的“1.41”版本,但是该文件的版本“1.41”是不同的。

Basically, $Id$ does not make any sense with Bazaar, Git, and other distributed source code management tools.

基本上,$ Id $对Bazaar,Git和其他分布式源代码管理工具没有任何意义。

#6


I had the same problem. I needed to have a version that was simpler than a hash string and available for people using the tool without needing to connect to the repository.

我有同样的问题。我需要一个比哈希字符串更简单的版本,并且可供使用该工具的人使用而无需连接到存储库。

I did it with a Git pre-commit hook and changed my script to be able to automatically update itself.

我使用Git预提交钩子并更改了我的脚本以便能够自动更新自己。

I base the version off of the number of commits done. This is a slight race condition because two people could commit at the same time and both think they are committing the same version number, but we don't have many developers on this project.

我的版本基于完成的提交数量。这是一个轻微的竞争条件,因为两个人可以同时提交,并且都认为他们提交相同的版本号,但我们在这个项目上没有很多开发人员。

Mine is in Ruby, but it's not terribly complex code. The Ruby script has:

我的是Ruby,但它不是非常复杂的代码。 Ruby脚本具有:

MYVERSION = '1.090'
## Call script to do updateVersion from .git/hooks/pre-commit
def updateVersion
  # We add 1 because the next commit is probably one more - though this is a race
  commits = %x[git log #{$0} | grep '^commit ' | wc -l].to_i + 1
  vers = "1.%0.3d" % commits

  t = File.read($0)
  t.gsub!(/^MYVERSION = '(.*)'$/, "MYVERSION = '#{vers}'")
  bak = $0+'.bak'
  File.open(bak,'w') { |f| f.puts t }
  perm = File.stat($0).mode & 0xfff
  File.rename(bak,$0)
  File.chmod(perm,$0)
  exit
end

And then I have a command-line option (-updateVersion) that calls updateVersion for the tool.

然后我有一个命令行选项(-updateVersion)调用该工具的updateVersion。

Finally, I go to the Git head and create an executable script in .git/hooks/pre-commit.

最后,我转到Git头并在.git / hooks / pre-commit中创建一个可执行脚本。

The script simply changes to the head of the Git directory and calls my script with -updateVersion.

该脚本只需更改为Git目录的头部,并使用-updateVersion调用我的脚本。

Every time I check in, the MYVERSION variable is updated based on what the number of commits will be.

每次我签入时,MYVERSION变量都会根据提交的数量进行更新。

#7


If having $Keywords$ is essential for you, then maybe you could try to look at Mercurial instead? It has a hgkeyword extension that implement what you want. Mercurial is interesting as a DVCS anyway.

如果拥有$ Keywords $对你来说至关重要,那么也许你可以试着看看Mercurial呢?它有一个hgkeyword扩展,可以实现你想要的。无论如何,Mercurial作为DVCS很有意思。

#8


Something that is done with Git repositories is to use the tag object. This can be used to tag a commit with any kind of string and can be used to mark versions. You can see that tags in a repository with the git tag command, which returns all the tags.

使用Git存储库完成的任务是使用标记对象。这可以用于使用任何类型的字符串标记提交,并可用于标记版本。您可以使用git tag命令在存储库中查看该标记,该命令将返回所有标记。

It's easy to check out a tag. For example, if there is a tag v1.1 you can check that tag out to a branch like this:

检查标签很容易。例如,如果有标记v1.1,您可以将标记检出到分支,如下所示:

git checkout -b v1.1

As it's a top level object, you'll see the whole history to that commit, as well as be able to run diffs, make changes, and merges.

由于它是顶级对象,您将看到该提交的整个历史记录,以及能够运行差异,进行更改和合并。

Not only that, but a tag persists, even if the branch that it was on has been deleted without being merged back into the main line.

不仅如此,标签仍然存在,即使它所在的分支已被删除而未合并回主线。

#9


If you're just wanting people to be able to get an idea how far out of date they are, Git can inform them of that in several fairly easy ways. They compare the dates of the last commit on their trunk and your trunk, for example. They can use git cherry to see how many commits have occurred in your trunk that are not present in theirs.

如果您只是希望人们能够了解它们的过时程度,Git可以通过几种相当简单的方式告知它们。例如,他们比较最后一次提交他们的行李箱和行李箱的日期。他们可以使用git cherry来查看你的主干中有多少次没有出现的提交。

If that's all you want this for, I'd look for a way to provide it without a version number.

如果这就是你想要的全部内容,我会寻找一种方法来提供它而没有版本号。

Also, I wouldn't bother extending the courtesy to anyone unless you're sure they want it. :)

此外,除非你确定他们想要,否则我不会费心向任何人伸出礼貌。 :)

#10


If I understand correctly, essentially, you want to know how many commits have happened on a given file since you last updated.

如果我理解正确,基本上,您想知道自上次更新以来在给定文件上发生了多少次提交。

First get the changes in the remote origin, but don't merge them into your master branch:

首先获取远程源的更改,但不要将它们合并到主分支中:

% git fetch

Then get a log of the changes that have happened on a given file between your master branch and the remote origin/master.

然后获取主分支和远程源/主服务器之间给定文件上发生的更改的日志。

% git log master..origin/master foo.el

This gives you the log messages of all the commits that have happened in the remote repository since you last merged origin/master into your master.

这为您提供了自上次将origin / master合并到主服务器以来远程存储库中发生的所有提交的日志消息。

If you just want a count of the changes, pipe it to wc. Say, like this:

如果您只想计算更改,请将其传递给wc。说,像这样:

% git rev-list master..origin/master foo.el | wc -l

#11


RCS IDs are nice for single-file projects, but for any other the $Id$ says nothing about the project (unless you do forced dummy check-ins to a dummy version file).

RCS ID适用于单个文件项目,但对于任何其他项目,$ Id $对项目没有任何说明(除非您强制虚拟签入虚拟版本文件)。

Still one might be interested how to get the equivalents of $Author$, $Date$, $Revision$, $RCSfile$, etc. on a per file level or at the commit level (how to put them where some keywords are is another question). I don't have an answer on these, but see the requirement to update those, especially when the files (now in Git) originated from RCS-compatible systems (CVS).

还有一个人可能有兴趣如何在每个文件级别或提交级别获得$ Author $,$ Date $,$ Revision $,$ RCSfile $等的等价物(如何将它们放在某些关键字所在的位置是另一个题)。我对这些没有答案,但看到更新这些的要求,特别是当文件(现在在Git中)来自RCS兼容系统(CVS)时。

Such keywords may be interesting if the sources are distributed separately from any Git repository (that's what I also do). My solution is like this:

如果源与任何Git存储库分开分发,这样的关键字可能会很有趣(这也是我也做的)。我的解决方案是这样的:

Every project has a directory of its own, and in the project root I have a text file named .version which content describes the current version (the name that will be used when exporting the sources).

每个项目都有自己的目录,在项目根目录中我有一个名为.version的文本文件,其中的内容描述了当前版本(导出源时将使用的名称)。

While working for the next release a script extracts that .version number, some Git version descriptor (like git describe) and a monotonic build number in .build (plus host and date) to an auto-generated source file that is linked to the final program, so you can find out from what source and when it was built.

在为下一个版本工作时,脚本会将.version编号,一些Git版本描述符(如git describe)和.build中的单调内部版本号(加上主机和日期)提取到链接到最终版本的自动生成的源文件中。程序,所以你可以找出它的来源和时间。

I develop new features in separate branches, and the first thing I do is add n (for "next") to the .version string (multiple branches originating from the same root would use the same temporary .version number). Before release I decide which branches to merge (hopefully all having the same .version). Before committing the merge, I update .version to the next number (major or minor update, depending on the merged features).

我在单独的分支中开发新功能,我做的第一件事是将。(对于“next”)添加到.version字符串(源自同一根的多个分支将使用相同的临时.version编号)。在发布之前,我决定合并哪些分支(希望所有分支都具有相同的.version)。在提交合并之前,我将.version更新为下一个数字(主要或次要更新,具体取决于合并的功能)。

#12


I agree with those who think that token replacement belongs to build tools rather than to version control tools.

我同意那些认为令牌替换属于构建工具而不是版本控制工具的人。

You should have some automated release tool to set the version IDs in your sources at the time the release is being tagged.

您应该拥有一些自动发布工具,以便在标记发布时在您的源中设置版本ID。

#13


Since you use Emacs, you might be lucky :)

既然你使用Emacs,你可能会很幸运:)

I've came across this question by coincidence, and also by coincidence I've came by Lively few days ago, an Emacs package which allows having lively pieces of Emacs Lisp in your document. I've not tried it to be honest, but it came to my mind when reading this.

我巧合地遇到了这个问题,而且巧合的是我几天前来到Lively,这是一个Emacs软件包,允许在你的文档中使用Emacs Lisp。我没有试过说实话,但在读这篇文章时我想到了。

#14


I also came from SCCS, RCS, and CVS (%W% %G% %U%).

我也来自SCCS,RCS和CVS(%W %% G %% U%)。

I had a similar challenge. I wanted to know what version a piece of code was on any system running it. The system may or may not be connected to any network. The system may or may not have Git installed. The system may or may not have the GitHub repository installed on it.

我遇到了类似的挑战。我想知道运行它的任何系统上的代码是什么版本。系统可能连接也可能不连接到任何网络。系统可能安装也可能没有安装Git。系统可能有也可能没有安装GitHub存储库。

I wanted the same solution for several types of code (.sh, .go, .yml, .xml, etc). I wanted any person without knowledge of Git or GitHub to be able to answer the question "What version are you running?"

我想要几种类型的代码(.sh,.go,.yml,.xml等)相同的解决方案。我希望任何不了解Git或GitHub的人都能回答“你在运行什么版本?”的问题。

So, I wrote what I call a wrapper around a few Git commands. I use it to mark a file with a version number and some information. It solves my challenge. It may help you.

所以,我写了一些我称之为几个Git命令的包装器。我用它来标记带有版本号和一些信息的文件。它解决了我的挑战。它可能会帮助你。

https://github.com/BradleyA/markit

git clone https://github.com/BradleyA/markit
cd markit

#15


To apply the expansion to all files in all sub-directories in the repository, add a .gitattributes file to the top level directory in the repository (i.e. where you'd normally put the .gitignore file) containing:

要将扩展应用于存储库中所有子目录中的所有文件,请将.gitattributes文件添加到存储库中的顶级目录(即通常放置.gitignore文件的位置),其中包含:

* ident

To see this in effect, you'll need to do an effective checkout of the file(s) first, such as deleting or editing them in any way. Then restore them with:

要查看这有效,您需要先对文件进行有效检查,例如以任何方式删除或编辑它们。然后恢复它们:

git checkout .

And you should see $Id$ replaced with something like:

你应该看到$ Id $被替换为:

$Id: ea701b0bb744c90c620f315e2438bc6b764cdb87 $

From man gitattributes:

来自man gitattributes:

ident

When the attribute ident is set for a path, Git replaces $Id$ in the blob object with $Id:, followed by the 40-character hexadecimal blob object name, followed by a dollar sign $ upon checkout. Any byte sequence that begins with $Id: and ends with $ in the worktree file is replaced with $Id$ upon check-in.

当为路径设置属性ident时,Git用$ Id:替换blob对象中的$ Id $,后跟40个字符的十六进制blob对象名称,然后在结帐时使用美元符号$。任何以$ Id开头且以worktree文件中的$结尾的字节序列在签入时将替换为$ Id $。

This ID will change every time a new version of the file is committed.

每次提交新版本的文件时,此ID都会更改。


推荐阅读
  • 深入体验Python的高级交互式Shell - IPython
    IPython 是一个增强型的 Python 交互式 Shell,提供了比标准 Python 控制台更为强大的功能,适用于开发和调试过程。它不仅支持直接执行 Linux 命令,还提供了丰富的特性来提高编程效率。 ... [详细]
  • Jupyter Notebook多语言环境搭建指南
    本文详细介绍了如何在Linux环境下为Jupyter Notebook配置Python、Python3、R及Go四种编程语言的环境,包括必要的软件安装和配置步骤。 ... [详细]
  • 如何在PHP中安装Xdebug扩展
    本文介绍了如何从PECL下载并编译安装Xdebug扩展,以及如何配置PHP和PHPStorm以启用调试功能。 ... [详细]
  • Android与JUnit集成测试实践
    本文探讨了如何在Android项目中集成JUnit进行单元测试,并详细介绍了修改AndroidManifest.xml文件以支持测试的方法。 ... [详细]
  • 深入理解Java SE 8新特性:Lambda表达式与函数式编程
    本文作为‘Java SE 8新特性概览’系列的一部分,将详细探讨Lambda表达式。通过多种示例,我们将展示Lambda表达式的不同应用场景,并解释编译器如何处理这些表达式。 ... [详细]
  • flea,frame,db,使用,之 ... [详细]
  • 本文详细介绍了`android.os.Binder.getCallingPid()`方法的功能和应用场景,并提供了多个实际的代码示例。通过这些示例,开发者可以更好地理解如何在不同的开发场景中使用该方法。 ... [详细]
  • 本文详细介绍了 Java 中 org.w3c.dom.Node 类的 isEqualNode() 方法的功能、参数及返回值,并通过多个实际代码示例来展示其具体应用。此方法用于检测两个节点是否相等,而不仅仅是判断它们是否为同一个对象。 ... [详细]
  • 尝试使用Composer安装自定义提交的包时遇到问题,Composer报告找不到指定的包。 ... [详细]
  • Windows操作系统提供了Encrypting File System (EFS)作为内置的数据加密工具,特别适用于对NTFS分区上的文件和文件夹进行加密处理。本文将详细介绍如何使用EFS加密文件夹,以及加密过程中的注意事项。 ... [详细]
  • 本文详细介绍了如何搭建一个高可用的MongoDB集群,包括环境准备、用户配置、目录创建、MongoDB安装、配置文件设置、集群组件部署等步骤。特别关注分片、读写分离及负载均衡的实现。 ... [详细]
  • 深入解析WebP图片格式及其应用
    随着互联网技术的发展,无论是PC端还是移动端,图片数据流量占据了很大比重。尤其在高分辨率屏幕普及的背景下,如何在保证图片质量的同时减少文件大小,成为了亟待解决的问题。本文将详细介绍Google推出的WebP图片格式,探讨其在实际项目中的应用及优化策略。 ... [详细]
  • Logging all MySQL queries into the Slow Log
    MySQLoptionallylogsslowqueriesintotheSlowQueryLog–orjustSlowLog,asfriendscallit.However,Thereareseveralreasonstologallqueries.Thislistisnotexhaustive:Belowyoucanfindthevariablestochange,astheyshouldbewritteninth ... [详细]
  • 本文详细探讨了在Web开发中常见的UTF-8编码问题及其解决方案,包括HTML页面、PHP脚本、MySQL数据库以及JavaScript和Flash应用中的乱码问题。 ... [详细]
  • 微信小程序开发指南:创建动态电影选座界面
    本文详细介绍如何在微信小程序中实现一个动态且可视化的电影选座组件,提高用户体验。通过合理的布局和交互设计,使用户能够轻松选择心仪的座位。 ... [详细]
author-avatar
zhangsheng7_215
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有