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.
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.
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.
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.
So what alternatives do I have? If I can't get an $Id:$ equivalent, how else can I provide what I'm looking for?
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).
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.
As I’ve written before:
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).
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).
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:
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).While working for the next release a script extracts that
.version
number, some Git version descriptor (likegit 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.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).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: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:
And you should see
$Id$
replaced with something like:From
man gitattributes
:This ID will change every time a new version of the file is committed.
Not sure this will ever be in Git. To quote Linus:
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.
Edit: you should write or use someone else's scripts for this, of course, not do this manually.
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.
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:
And then I have a command-line option (-updateVersion) that calls updateVersion for the tool.
Finally, I go to the Git head and create an executable script in
.git/hooks/pre-commit
.The script simply changes to the head of the Git directory and calls my script with
-updateVersion
.Every time I check in, the MYVERSION variable is updated based on what the number of commits will be.