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).
The SHA is just one representation of a version (albeit canonical). The
git describe
command offers others and does so quite well.For example, when I run
git describe
in my master branch of my Java memcached client source, I get this:That says two important things:
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 was2.2-12-g6c4ae7a
(not a release, but a valid version).You can now see exactly how far behind you are (4 commits), and you can see exactly which 4 commits:
This isn't an unreasonable request from the OP.
My use-case is:
/usr/local/bin
when they are ready.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 <repo version> <version in /usr/local/bin>".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.
Anyway, the way I did it was to create an attributes file in the repository like this:
Then put $Id$ somewhere in the file (I like to put it after the shebang).
The commit. Note that this doesn't automatically do the expansion like I expected. You have to re-co the file, for example,
And then you will see the expansion, for example:
Some good information is in How do I enable the ident string for a Git repository?.
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 thegit tag
command, which returns all the tags.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: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.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 you want the git commit information accessible into your code, then you have to do a pre-build step to get it there. In bash for C/C++ it might look something like this:
prebuild.sh
with
version.h
looking like:Then, wherever you need it in your code
#include "version.h"
and referencegit_tag
orgit_commit
as needed.And your
Makefile
might have something like this:This has the benefit of:
This implementation of
prepublish.sh
has the drawbacks of:git_tag
/git_commit
didn't change.git describe --tags --always --dirty
to catch that use-case.A fancier
prebuild.sh
that could avoid these issues is left as an exercise for the reader.