Bar*_*ica 42 svn git version-control version-control-keywords
我曾经在Subversion/SVN下工作,并立即使用称为关键字替换的好功能.只需输入源文件即可:
/*
* $Author: ivanovpv $
* $Rev: 42 $
* $LastChangedDate: 2012-05-25 21:47:42 +0200 (Fri, 25 May 2012) $
*/
Run Code Online (Sandbox Code Playgroud)
每次Subversion都用实际的关键字替换关键字(Author,Rev,LastChangedDate).
前段时间我被迫转移到Git,只是想知道是否有类似Subversion在Git中的关键字替换?
Mar*_*ski 31
Git没有提供开箱即用的此功能.但是,Git Book中有一章关于自定义Git,其中一个例子是如何使用git属性来实现类似的结果.
事实证明,您可以编写自己的过滤器,以便在提交/结帐时在文件中进行替换.这些被称为"干净"和"涂抹"过滤器.在该
.gitattributes
文件中,您可以为特定路径设置过滤器,然后设置脚本,这些脚本将在文件签出之前处理("涂抹")并且在它们上演之前("清理").这些过滤器可以设置为做各种有趣的事情.
甚至有一个例子$LastChangedDate: $
:
另一个有趣的例子是
$Date$
关键字扩展,RCS风格.要正确执行此操作,您需要一个带有文件名的小脚本,计算出该项目的上次提交日期,并将日期插入到文件中.这是一个小的Ruby脚本,它可以做到:Run Code Online (Sandbox Code Playgroud)#! /usr/bin/env ruby data = STDIN.read last_date = `git log --pretty=format:"%ad" -1` puts data.gsub('$Date$', '$Date: ' + last_date.to_s + '$')
所有脚本都是从
git log
命令获取最新的提交日期,将其粘贴到$Date$
它在stdin中看到的任何字符串中,然后打印结果 - 使用您最熟悉的语言应该很简单.您可以命名此文件expand_date
并把它放在你的道路上.现在,您需要在Git中设置一个过滤器(调用它dater
)并告诉它使用您的expand_date
过滤器在结帐时涂抹文件.您将使用Perl表达式在提交时清除它:Run Code Online (Sandbox Code Playgroud)$ git config filter.dater.smudge expand_date $ git config filter.dater.clean 'perl -pe "s/\\\$Date[^\\\$]*\\\$/\\\$Date\\\$/"'
这个Perl片段会删除它在
$Date$
字符串中看到的任何内容,以便返回到您开始的位置.现在您的过滤器已准备就绪,您可以通过为该文件设置Git属性来测试它,该属性使用新过滤器并使用您的$Date$
关键字创建文件:Run Code Online (Sandbox Code Playgroud)date*.txt filter=dater $ echo '# $Date$' > date_test.txt If you commit
这些更改并再次检出文件,您会看到正确替换的关键字:
Run Code Online (Sandbox Code Playgroud)$ 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$
您可以看到此技术对于自定义应用程序有多强大.但是,您必须要小心,因为
.gitattributes
文件已提交并传递给项目,但驱动程序(在本例中dater
)不是,因此它无法在任何地方工作.设计这些过滤器时,它们应该能够正常失败并使项目仍能正常工作.
She*_*ish 15
好吧,你可以自己轻松实现这样的功能.
基本上我将commit命令嵌入到shell脚本中.此脚本将首先替换所需的宏,然后提交更改.该项目包含两个文件:
keysub
,一个bash shell脚本和keysub.awk
一个awk脚本来替换特定文件中的关键字.第三个文件是一个配置文件,其中包含应该替换的值(除了提交计数和时间戳之类的可变内容).
您keysub
使用相同的选项调用而不是提交.该-m
或-a
选项应该出现在任何其他提交选项.一个新选项(应该总是第一个)是-f
将配置文件作为值.例:
$ git add 'someJavaFile.java'
$ keysub -m 'fixed concurrent thread issue'
$ git push
Run Code Online (Sandbox Code Playgroud)
要么
$ git -f .myfile.cnf -m 'enhanced javadoc entries'
Run Code Online (Sandbox Code Playgroud)
#!/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
Run Code Online (Sandbox Code Playgroud)
# 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
}
Run Code Online (Sandbox Code Playgroud)
author:ubunut-420
timestamp:Fri Jun 21 20:42:54 CEST 2013
commitmsg:default commit message
Run Code Online (Sandbox Code Playgroud)
我已经尝试了足够好的文档,因此您可以轻松地实现它并根据您自己的个人需求进行修改.请注意,只要您在源代码中修改它,就可以为宏提供您想要的任何名称.我还希望保持扩展脚本相对容易,你应该能够相当容易地添加新的宏.如果你对扩展或修改脚本感兴趣,你可能也想查看.git目录,那里应该有很多信息可以帮助增强脚本,因为我没有时间然后调查该文件夹.
归档时间: |
|
查看次数: |
22995 次 |
最近记录: |