1

I've previously developed Tcl/Python scripts using SVN for version control; now I'm using git. With SVN I used keywords to print date modified and other info to file headers, but git doesn't offer this sort of functionality. I've read the reasons for this and I agree that this functionality isn't really necessary for most cases. Why print this information to the file if you can get the information from git itself?

But what if I am developing a script using git version control, but I want to make it available to read-only users who aren't using git? In this case the file needs some information in it to tell the user what version it is, and perhaps who modified it and when. SVN keywords provided this functionality, but git doesn't have an easy way to do this without writing some complex pre-commit hook that would leave the working copy dirty anyway.

Does anyone have a similar use case, and a way to do this using git?

DrBuck
  • 822
  • 7
  • 22
  • 2
    possible duplicate of [Git keyword substitution like those in Subversion?](http://stackoverflow.com/questions/11534655/git-keyword-substitution-like-those-in-subversion) – joran Sep 08 '15 at 09:02
  • I've had a look at these answers, but I can't see how you can do this without affecting the working copy. I was more interested in whether people have another way of writing version info to files that I may have overlooked. – DrBuck Sep 08 '15 at 12:52

3 Answers3

2

So if anyone is interested I came up with a solution after looking at the comments below. I've written a bash script that publishes files contained within the $gitFiles folder for me using git archive to the $publishFolder location. The script then gets info for each file using git log and prints to each file header using sed s/findstr/repstr/ $file.

#!/bin/bash

publishFolder="./Release"
gitFiles="./PythonFiles"

updateFindStr="\\\$Last Update[^\\$]*\\$"
commentFindStr="\\\$Comment[^\\$]*\\$"
hashFindStr="\\\$Hash[^\\$]*\\$"

# Archive the whole folder
folderHash=$(git log -1 --pretty=format:"%H" $gitFiles)
git archive $folderHash --format tar $gitFiles > $publishFolder/archive.tar

# Unpack the tar file and delete it
tar xf $publishFolder/archive.tar -C $publishFolder
rm $publishFolder/archive.tar

# Loop through all files in the gitfiles folder and write git info to the published files
for file in $(ls $gitFiles/*.*)

do
    echo "Publishing $(basename $file)..."

    # Grab the git info and save as string in format date;author;comment;hash
    gitInfo=$(git log -1 --pretty=format:"%cd;%an;%s;%H" --date=short $file)

    # Split the string and save to separate variables
    IFS=";" read date author comment hash <<< "$gitInfo"

    # build update, comment and hash strings
    updateRepStr="\\\$Last Update: ${date} by ${author} \\$"
    commentRepStr="\\\$Comment: ${comment} \\$"
    hashRepStr="\\\$Hash: ${hash} \\$"

    # Write git hash and info into the new file
    sed -i "s/${updateFindStr}/${updateRepStr}/; s/${commentFindStr}/${commentRepStr}/; s/${hashFindStr}/${hashRepStr}/" $publishFolder${file:1}

done

So I start with a file header like this:

# ------------------------------------------------------------------------------
# PYTHONSCRIPT:     myfile.py
# ------------------------------------------------------------------------------
# Project:      n/a
# Created by:   user on 22/7/2015
# $Last Update: $
# $Comment:     $
# $Hash:        $
# ------------------------------------------------------------------------------

And I end up with a published file with a header looking like this, which is what I wanted :)

# ------------------------------------------------------------------------------
# PYTHONSCRIPT:     myfile.py
# ------------------------------------------------------------------------------
# Project:      n/a
# Created by:   user on 22/7/2015
# $Last Update: 2015-09-09 by user $
# $Comment: Added comment keyword $
# $Hash: ec56f527333c0c0af98c2ed3ab3395c6c8a50624 $
# ------------------------------------------------------------------------------
DrBuck
  • 822
  • 7
  • 22
1

Since you're wanting to emulate something akin to SVN $Header$ in git, here is a solution that implements that exact feature:

  1. Add the following pre-commit hook:

    #!/bin/sh
    git diff --cached --name-only -z --diff-filter=ACM |
            xargs -r0 .filters/keywords --
    git diff --cached --name-only -z --diff-filter=ACM |
            xargs -r0 git add -u -v --
    
  2. Add the following commit-msg hook:

    #!/bin/sh
    awk '!/^[[:space:]]*(#|$)/{exit f++}END{exit !f}' "$1" && exit
    # NOTREACHED unless commit was aborted
    git diff --cached --name-only -z --diff-filter=ACM |
            xargs -r0 .filters/keywords -d --
    git diff --cached --name-only -z --diff-filter=ACM |
            xargs -r0 git add -u -v --
    
  3. Download ".filters/fraubsd-keywords" but rename file to "keywords":

    https://raw.githubusercontent.com/freebsdfrau/FrauBSD/master/.filters/fraubsd-keywords

  4. Edit "keywords", changing in the CONFIGURATION section at top:

    • FrauBSD to Header
    • _FrauBSD to _Header

After which, each time you do a git commit the text $Header$ and/or $Header: ... $ will be translated into $Header: file YYYY-MM-DD HH:MM:SS GMTOFFSET committer $

NOTE: You may have to modify a small section of the "keywords" script to operate on more-or-less types of files. At the time of this writing it only operates on files that are "ASCII text" or "shell scripts".

0

It depends on how you intend to publish your files (users download them from your repository, like from Github or Bitbucket) or if you prepare a package that can be downloaded from your site. You can either add the information before the commit is "written" to the repository (i.e. using a pre-commit hook) or when you checkout the files from the repository (i.e. using a smudge/cleanup filter, see http://git-scm.com/book/en/v2/Customizing-Git-Git-Attributes).

Another alternative would be to have a custom script that checksout your files, fetch the information from git and inserts relevant parts in the files before it publish your files.

joran
  • 2,815
  • 16
  • 18
  • OK thanks. I guess the best thing to use to publish my files would be to use `git archive`? It's a shame git doesn't provide keywords built in like SVN, because to me this was a really useful feature... – DrBuck Sep 08 '15 at 14:12