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,即使他们这样做,也不会有本地存储库(事实上,我希望不会以这种方式提供它)。
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:
这说两件重要的事情:
自2.2以来,这棵树中确实有16次提交
确切的源树可以显示在任何其他人的克隆上。
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.
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。
This isn't an unreasonable request from the OP.
这不是OP的无理要求。
My use-case is:
我的用例是:
我使用Git作为我自己的个人代码,因此没有与他人合作。
/usr/local/bin
when they are ready.我将系统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字符串?
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.
编辑:您应该为此编写或使用其他人的脚本,当然,不要手动执行此操作。
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和其他分布式源代码管理工具没有任何意义。
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变量都会根据提交的数量进行更新。
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很有意思。
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.
不仅如此,标签仍然存在,即使它所在的分支已被删除而未合并回主线。
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. :)
此外,除非你确定他们想要,否则我不会费心向任何人伸出礼貌。 :)
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
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更新为下一个数字(主要或次要更新,具体取决于合并的功能)。
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。
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。我没有试过说实话,但在读这篇文章时我想到了。
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
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都会更改。