I'm planning my company's transition from CVS to Git, and certain engineers are wishing we still had use of CVS keyword strings such as $Id: $
. I have read all about implementing this with the ident setting .gitattributes
, and I understand why it's undesirable, though maybe possible for smaller source trees. (Our source is huge, so I think it would be impossible.)
Our engineers don't particularly care about having the SHA1 hash in the file. They just want to know:
They find it extremely handy to see this info in file headers when browsing code, and I can't argue with that.
What I want to know is:
Is there any way to info-stamp all the staged files at the moment before git commit? In other words, to run a perl command -- that replaces $Id: $
with a block of desired info -- on the working copies of files being committed?
This wouldn't require any .gitattributes
actions at all. Git would just need to know how to merge two such blocks of info, ideally by choosing the later one. The stamped info would be just one more file change in the newly created version.
I looked at doing this in the pre-commit hook, but it seems to be intended differently -- not for editing files, just for checking them. Am I right about that?
And has nobody tried this approach? It seems simpler to me than trying to filter all source files every time git changes versions, which it what it sounds like .gitattributes
does.
Much thanks for any advice/warnings/pointers .
A gitattributes file is a simple text file that gives attributes to pathnames. Each line in gitattributes file is of form: pattern attr1 attr2 ... That is, a pattern followed by an attributes list, separated by whitespaces.
These path-specific settings are called Git attributes and are set either in a . gitattributes file in one of your directories (normally the root of your project) or in the . git/info/attributes file if you don't want the attributes file committed with your project.
Diffing is a function that takes two input data sets and outputs the changes between them. git diff is a multi-use Git command that when executed runs a diff function on Git data sources. These data sources can be commits, branches, files and more.
There is no output to git diff because Git doesn't see any changes inside your repository, only files outside the repository, which it considers 'untracked' and so ignores when generating a diff.
The Keyword Expansion section of the git documentation explains how to make clean keyword expansion.
A ruby script for expanding what you want would be something like this (not tested)
#! /usr/bin/env ruby
data = STDIN.read
last_info = `git log --pretty=format:"%ad %cn %s" -1`
puts data.gsub('$Last$', '$Last: ' + last_info.to_s + '$')
setup filter
$ git config filter.last_expander.smudge expand_last_info
$ git config filter.last_expander.clean 'perl -pe "s/\\\$Last[^\\\$]*\\\$/\\\$Last\\\$/"'
setup .gitattributes
echo '*.txt filter=last_expander' >> .gitattributes
Note: (just as vonbrand says) what this gives you, and what you in all likelyhood want, is field expansion on checkout and removal of the fields on commit. But the effect is that your engineers will be able to read the field in the checked out files in their working directory. Isn't that what they want? And this will not mess up the actually versioned content with any redundant metadata.
RCS (and thus CVS) does the expanding of $Id:$
and such on checkout, those aren't in the saved files. And they can't really be, somebody might come around and rename version 1.8.2-rc10
to plain 1.8.2
. If somebody wants to know where file
comes from, git log file
answers that nicely, with more details than RCS could ever give. And it is a local command, no trip to the CVS server (and thus available everywhere where git
is, and instantaneous).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With