Git keyword replacement e.g. in Subversion?

I worked in Subversion / SVN and instantly used a nice feature called keyword replacement. Just pasting the source files, for example:

/* * $Author: ivanovpv $ * $Rev: 42 $ * $LastChangedDate: 2012-05-25 21:47:42 +0200 (Fri, 25 May 2012) $ */ 

And every time Subversion replaces the keywords (Author, Rev, LastChangedDate) with the actual ones.

Some time ago I had to switch to Git and just wondering if there is something similar to Subversion keyword substitution in Git?

+32
git version-control svn version-control-keywords
Jul 18 '12 at 5:14
source share
3 answers

Decision

Well, you can easily implement such a function yourself.

I basically embedded the commit command in a shell script. This script will first replace the necessary macros, and then commit the changes. The project consists of two files:

Content

keysub , a bash shell script and keysub.awk awk script to replace keywords in a specific file. The third file is a configuration file that contains the values ​​that should be replaced (in addition to variables, such as the commit amount and timestamp).

How do you use it?

You call keysub instead of keysub with the same parameters. The -m or -a option should appear before any other commit option. The new option (which should always be the first) is -f , which takes the configuration file as a value. Example:

 $ git add 'someJavaFile.java' $ keysub -m 'fixed concurrent thread issue' $ git push 

or

 $ git -f .myfile.cnf -m 'enhanced javadoc entries' 

keysub

 #!/bin/bash # 0 -- functions/methods ######################### # <Function description> function get_timestamp () { date # change this to get a custom timestamp } # 1 -- Variable declarations ############################# # input file for mapping file=".keysub.cnf" timestamp=$(get_timestamp) # 2 -- Argument parsing and flag checks ######################################## # Parsing flag-list while getopts ":f:m:a" opt; do case $opt in f) file=${OPTARG} ;; a) echo 'Warning, keyword substitution will be incomplete when invoked' echo 'with the -a flag. The commit message will not be substituted into' echo 'source files. Use -m "message" for full substitutions.' echo -e 'Would you like to continue [y/n]? \c' read answer [[ ${answer} =~ [Yy] ]] || exit 3 unset answer type="commit_a" break ;; m) type="commit_m" commitmsg=${OPTARG} break ;; \?) break ;; esac done shift $(($OPTIND - 1)) # check file for typing if [[ ! -f ${file} ]] then echo 'No valid config file found.' exit 1 fi # check if commit type was supplied if [[ -z ${type} ]] then echo 'No commit parameters/flags supplied...' exit 2 fi # 3 -- write config file ######################### sed " /timestamp:/ { s/\(timestamp:\).*/\1${timestamp}/ } /commitmsg:/ { s/\(commitmsg:\).*/\1${commitmsg:-default commit message}/ } " ${file} > tmp mv tmp ${file} # 4 -- get remaining tags ########################## author=$(grep 'author' ${file} | cut -f1 -d':' --complement) # 5 -- get files ready to commit ################################# git status -s | grep '^[MARCU]' | cut -c1-3 --complement > tmplist # 6 -- invoke awk and perform substitution ########################################### # beware to change path to your location of the awk script for item in $(cat tmplist) do echo ${item} awk -v "commitmsg=${commitmsg}" -v "author=${author}" \ -v "timestamp=${timestamp}" -f "${HOME}/lib/awk/keysub.awk" ${item} \ > tmpfile mv tmpfile ${item} done rm tmplist # 5 -- invoke git commit ######################### case ${type} in "commit_m") git commit -m "${commitmsg}" "$@" ;; "commit_a") git commit -a "$@" ;; esac # exit using success code exit 0 

keysub.awk

 # 0 BEGIN ########## BEGIN { FS=":" OFS=": " } # 1 parse source files ######################## # update author $0 ~ /.*\$Author.*\$.*/ { $2=author " $" } # update timestamp $0 ~ /.*\$LastChangedDate.*\$.*/ { $0=$1 $2=timestamp " $" } # update commit message $0 ~ /.*\$LastChangeMessage.*\$.*/ { $2=commitmsg " $" } # update commit counts $0 ~ /.*\$Rev.*\$.*/ { ++$2 $2=$2 " $" } # print line { print } 

configuration file

 author:ubunut-420 timestamp:Fri Jun 21 20:42:54 CEST 2013 commitmsg:default commit message 

Notes

I tried to document well enough so that you could easily implement it and change it to your own, personal needs. Note that you can give macros whatever name you want, as long as you change it in the source code. I also sought to simplify the script extension, you should easily add new macros. If you are interested in expanding or modifying the script, you can also take a look at the .git directory, there should be a lot of information that can help improve the script due to lack of time. I have not examined the folder though.

+12
Jun 21 '13 at 7:13
source share

Git does not come with this functionality out of the box. However, there is a chapter in Git's book Configuring Git , and one example is the use of Git attributes to implement a similar result.

It turns out that you can write your own filters for replacing in files during commit / check. They are called "clean" and "smudge". In the .gitattributes file .gitattributes you can set a filter for certain paths, and then configure scripts that will process files shortly before they are checked (“smudge”) and right in front of them (“clean”). These filters can be configured for all kinds of entertainment things.

There is even an example for $LastChangedDate: $ :

Another interesting example: the extension of the keyword $Date$ , RCS style. To do this correctly, you will need a small script that takes the file name, determines the last commit date for this project, and inserts the date into the file. Here is a little Ruby script that does this:

 #! /usr/bin/env ruby data = STDIN.read last_date = `git log --pretty=format:"%ad" -1` puts data.gsub('$Date$', '$Date: ' + last_date.to_s + '$') 

The whole script is getting the last commit, enter the date from the git log command, paste it into any line of $Date$ . sees in stdin and prints the results - it should be easy to do in any language in which you are most comfortable. You can name this file expand_date and put it in your path. Now you need to configure the filter in Git (name it dater ) and tell it to use your expand_date filter to smudge files when placing an order. You use a Perl expression to clear what's on commit:

 $ git config filter.dater.smudge expand_date $ git config filter.dater.clean 'perl -pe "s/\\\$Date[^\\\$]*\\\$/\\\$Date\\\$/"' 

This Perl snippet removes everything it sees on the $Date$ line to return to where you started. Now that your filter is ready, you can check it by setting the Git attribute for this file, which uses the new filter and creating a file with your keyword $Date$ :

 date*.txt filter=dater $ echo '# $Date$' > date_test.txt If you commit 

these changes and check the file again, you will see the keyword is correctly replaced:

 $ git add date_test.txt .gitattributes $ git commit -m "Testing date expansion in Git" $ rm date_test.txt $ git checkout date_test.txt $ cat date_test.txt # $Date: Tue Apr 21 07:26:52 2009 -0700$ 

You can see how powerful this method can be for custom applications. You have to be careful though, since the .gitattributes file .gitattributes committed and transferred with the project, but the driver (in this case dater ) isnt, so it won’t work everywhere. When you create these filters, they must be able to gracefully fail, and the project is still working properly.

+23
Jul 18 '12 at 6:19 06:19
source share

Unfortunately not.

Read their documentation, add the link: Keyword Extension

+5
Jul 18 '12 at 5:20
source share



All Articles