<p>I recently asked about <a href="https://stackoverflow.com/questions/39742/does-git-have-anything-like-svn-propset-svnkeywords-or-pre-post-commit-hooks">keyword expansion in Git</a> and I'm willing to accept the design not to really support this idea in Git. </p>

<p>For better or worse, the project I'm working on at the moment requires SVN keyword expansion like this:</p>

<pre><code>svn propset svn:keywords "Id" expl3.dtx
</code></pre>

<p>to keep this string up-to-date:</p>

<pre><code>$Id: expl3.dtx 803 2008-09-11 14:01:58Z will $
</code></pre>

<p>But I would quite like to use Git to do my version control. Unfortunately, git-svn doesn't support this, according to the docs:</p>

<blockquote>
  <p>"We ignore all SVN properties except svn:executable"</p>
</blockquote>

<p>But it doesn't seem too tricky to have this keyword stuff emulated by a couple of pre/post commit hooks. Am I the first person to want this? Does anyone have some code to do this?</p>

[{'answer_id': 62288, 'author': 'Lily Ballard', 'author_id': 582, 'author_profile': 'https://Stackoverflow.com/users/582', 'pm_score': 1, 'selected': False, 'text': "<p>You could set the ident attribute on your files, but that would produce strings like</p>\n\n<pre><code>$Id: deadbeefdeadbeefdeadbeefdeadbeefdeadbeef$\n</code></pre>\n\n<p>where <code>deadbeef...</code> is the sha1 of the blob corresponding to that file. If you really need that keyword expansion, and you need it in the git repo (as opposed to an exported archive), I think you're going to have to go with the <code>ident</code> gitattribute with a custom script that does the expansion for you. The problem with just using a hook is then the file in the working tree wouldn't match the index, and git would think it's been modified.</p>\n"}, {'answer_id': 72874, 'author': 'emk', 'author_id': 12089, 'author_profile': 'https://Stackoverflow.com/users/12089', 'pm_score': 6, 'selected': True, 'text': '<p>What\'s going on here: Git is optimized to switch between branches as quickly as possible. In particular, <code>git checkout</code> is designed to not touch any files that are identical in both branches.</p>\n\n<p>Unfortunately, RCS keyword substitution breaks this. For example, using <code>$Date$</code> would  require <code>git checkout</code> to touch every file in the tree when switching branches. For a repository the size of the Linux kernel, this would bring everything to a screeching halt.</p>\n\n<p>In general, your best bet is to tag at least one version:</p>\n\n<pre><code>$ git tag v0.5.whatever\n</code></pre>\n\n<p>...and then call the following command from your Makefile:</p>\n\n<pre><code>$ git describe --tags\nv0.5.15.1-6-g61cde1d\n</code></pre>\n\n<p>Here, git is telling me that I\'m working on an anonymous version 6 commits past v0.5.15.1, with an SHA1 hash beginning with <code>g61cde1d</code>. If you stick the output of this command into a <code>*.h</code> file somewhere, you\'re in business, and will have no problem linking the released software back to the source code. This is the preferred way of doing things.</p>\n\n<p>If you can\'t possibly avoid using RCS keywords, you may want to start with this <a href="http://kerneltrap.org/mailarchive/git/2007/10/12/335953" rel="noreferrer">explanation by Lars Hjemli</a>. Basically, <code>$Id$</code> is pretty easy, and you if you\'re using <code>git archive</code>, you can also use <code>$Format$</code>.</p>\n\n<p>But, if you absolutely cannot avoid RCS keywords, the following should get you started:</p>\n\n<pre><code>git config filter.rcs-keyword.clean \'perl -pe "s/\\\\\\$Date[^\\\\\\$]*\\\\\\$/\\\\\\$Date\\\\\\$/"\'\ngit config filter.rcs-keyword.smudge \'perl -pe "s/\\\\\\$Date[^\\\\\\$]*\\\\\\$/\\\\\\$Date: `date`\\\\\\$/"\'\n\necho \'$Date$\' &gt; test.html\necho \'test.html filter=rcs-keyword\' &gt;&gt; .gitattributes\ngit add test.html .gitattributes\ngit commit -m "Experimental RCS keyword support for git"\n\nrm test.html\ngit checkout test.html\ncat test.html\n</code></pre>\n\n<p>On my system, I get:</p>\n\n<pre><code>$Date: Tue Sep 16 10:15:02 EDT 2008$\n</code></pre>\n\n<p>If you have trouble getting the shell escapes in the <code>smudge</code> and <code>clean</code> commands to work, just write your own Perl scripts for expanding and removing RCS keywords, respectively, and use those scripts as your filter.</p>\n\n<p>Note that you <em>really</em> don\'t want to do this for more files than absolutely necessary, or git will lose most of its speed.</p>\n'}, {'answer_id': 1194313, 'author': 'Rhialto', 'author_id': 146440, 'author_profile': 'https://Stackoverflow.com/users/146440', 'pm_score': 5, 'selected': False, 'text': "<blockquote>\n  <p>Unfortunately, RCS keyword\n  substitution breaks this. For example,\n  using $Date$ would require git\n  checkout to touch every file in the\n  tree when switching branches.</p>\n</blockquote>\n\n<p>That is not true. $Date$ etc. expand to the value which holds at checkin time. That is much more useful anyway. So it doesn't change on other revisions or branches, unless the file is actually re-checked-in.\nFrom the RCS manual:</p>\n\n<pre><code>   $Date$ The  date  and  time the revision was checked in.  With -zzone a\n          numeric time zone offset is appended;  otherwise,  the  date  is\n          UTC.\n</code></pre>\n\n<p>This also means that the suggested answer above, with the rcs-keyword.smudge filter, is incorrect. It inserts the time/date of the checkout, or whatever it is that causes it to run.</p>\n"}, {'answer_id': 5633162, 'author': 'turon', 'author_id': 322797, 'author_profile': 'https://Stackoverflow.com/users/322797', 'pm_score': 3, 'selected': False, 'text': '<p>Here is a sample project containing the configuration and filter code needed for adding RCS keyword support to a git project:</p>\n\n<p><a href="https://github.com/turon/git-rcs-keywords" rel="noreferrer">https://github.com/turon/git-rcs-keywords</a></p>\n\n<p>It\'s not as simple to setup as one would like, but it seems to work.  It uses a smudge/clean filter pair written in perl (similar to what emk\'s answer described), and yes, it will touch all files with the extensions set in .gitattributes, generally slowing things down a bit. </p>\n'}]
['https://Stackoverflow.com/questions/62264', 'https://Stackoverflow.com', 'https://Stackoverflow.com/users/4161/']