Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

A different approach to ident-style strings in Git?

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:

  1. the date of last modification
  2. the name of the committer
  3. possibly the commit message

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 .

like image 987
Mykle Hansen Avatar asked Mar 14 '13 20:03

Mykle Hansen


People also ask

What is Gitattribute?

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.

Where can I find .gitattributes file?

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.

How git diff works internally?

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.

When might git diff head yield no results?

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.


2 Answers

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.

like image 24
Klas Mellbourn Avatar answered Sep 26 '22 23:09

Klas Mellbourn


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).

like image 115
vonbrand Avatar answered Sep 23 '22 23:09

vonbrand