热门标签 | 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都会更改。


推荐阅读
  • Iamtryingtomakeaclassthatwillreadatextfileofnamesintoanarray,thenreturnthatarra ... [详细]
  • 欢乐的票圈重构之旅——RecyclerView的头尾布局增加
    项目重构的Git地址:https:github.comrazerdpFriendCircletreemain-dev项目同步更新的文集:http:www.jianshu.comno ... [详细]
  • Hibernate延迟加载深入分析-集合属性的延迟加载策略
    本文深入分析了Hibernate延迟加载的机制,特别是集合属性的延迟加载策略。通过延迟加载,可以降低系统的内存开销,提高Hibernate的运行性能。对于集合属性,推荐使用延迟加载策略,即在系统需要使用集合属性时才从数据库装载关联的数据,避免一次加载所有集合属性导致性能下降。 ... [详细]
  • 本文介绍了Redis的基础数据结构string的应用场景,并以面试的形式进行问答讲解,帮助读者更好地理解和应用Redis。同时,描述了一位面试者的心理状态和面试官的行为。 ... [详细]
  • Spring特性实现接口多类的动态调用详解
    本文详细介绍了如何使用Spring特性实现接口多类的动态调用。通过对Spring IoC容器的基础类BeanFactory和ApplicationContext的介绍,以及getBeansOfType方法的应用,解决了在实际工作中遇到的接口及多个实现类的问题。同时,文章还提到了SPI使用的不便之处,并介绍了借助ApplicationContext实现需求的方法。阅读本文,你将了解到Spring特性的实现原理和实际应用方式。 ... [详细]
  • ZSI.generate.Wsdl2PythonError: unsupported local simpleType restriction ... [详细]
  • Python正则表达式学习记录及常用方法
    本文记录了学习Python正则表达式的过程,介绍了re模块的常用方法re.search,并解释了rawstring的作用。正则表达式是一种方便检查字符串匹配模式的工具,通过本文的学习可以掌握Python中使用正则表达式的基本方法。 ... [详细]
  • [大整数乘法] java代码实现
    本文介绍了使用java代码实现大整数乘法的过程,同时也涉及到大整数加法和大整数减法的计算方法。通过分治算法来提高计算效率,并对算法的时间复杂度进行了研究。详细代码实现请参考文章链接。 ... [详细]
  • 本文介绍了Android 7的学习笔记总结,包括最新的移动架构视频、大厂安卓面试真题和项目实战源码讲义。同时还分享了开源的完整内容,并提醒读者在使用FileProvider适配时要注意不同模块的AndroidManfiest.xml中配置的xml文件名必须不同,否则会出现问题。 ... [详细]
  • Android开发实现的计时器功能示例
    本文分享了Android开发实现的计时器功能示例,包括效果图、布局和按钮的使用。通过使用Chronometer控件,可以实现计时器功能。该示例适用于Android平台,供开发者参考。 ... [详细]
  • Java自带的观察者模式及实现方法详解
    本文介绍了Java自带的观察者模式,包括Observer和Observable对象的定义和使用方法。通过添加观察者和设置内部标志位,当被观察者中的事件发生变化时,通知观察者对象并执行相应的操作。实现观察者模式非常简单,只需继承Observable类和实现Observer接口即可。详情请参考Java官方api文档。 ... [详细]
  • 本文介绍了在使用Laravel和sqlsrv连接到SQL Server 2016时,如何在插入查询中使用输出子句,并返回所需的值。同时讨论了使用CreatedOn字段返回最近创建的行的解决方法以及使用Eloquent模型创建后,值正确插入数据库但没有返回uniqueidentifier字段的问题。最后给出了一个示例代码。 ... [详细]
  • SpringBoot整合SpringSecurity+JWT实现单点登录
    SpringBoot整合SpringSecurity+JWT实现单点登录,Go语言社区,Golang程序员人脉社 ... [详细]
  • 本文介绍了pack布局管理器在Perl/Tk中的使用方法及注意事项。通过调用pack()方法,可以控制部件在显示窗口中的位置和大小。同时,本文还提到了在使用pack布局管理器时,应注意将部件分组以便在水平和垂直方向上进行堆放。此外,还介绍了使用Frame部件或Toplevel部件来组织部件在窗口内的方法。最后,本文强调了在使用pack布局管理器时,应避免在中间切换到grid布局管理器,以免造成混乱。 ... [详细]
  • 本文介绍了在C#中SByte类型的GetHashCode方法,该方法用于获取当前SByte实例的HashCode。给出了该方法的语法和返回值,并提供了一个示例程序演示了该方法的使用。 ... [详细]
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社区 版权所有