Git подстановка ключевых слов, как в Subversion?
Раньше я работал в Subversion/SVN и сразу использовал замечательную функцию под названием подстановка ключевых слов. Просто вставив исходные файлы, например:
/*
* $Author: ivanovpv $
* $Rev: 42 $
* $LastChangedDate: 2012-05-25 21:47:42 +0200 (Fri, 25 May 2012) $
*/
И каждый раз Subversion заменял ключевые слова (Author, Rev, LastChangedDate) реальными.
Некоторое время назад я был вынужден перейти на Git, и мне просто интересно, есть ли что-то похожее на подстановку ключевых слов Subversion в Git?
4 ответа
Решение
Ну, вы могли бы легко реализовать такую функцию самостоятельно.
По сути, я встроил команду commit в скрипт оболочки. Этот скрипт сначала заменит нужные макросы, а затем зафиксирует изменения. Проект состоит из двух файлов:
Содержание?
keysub
скрипт bash и keysub.awk
Скрипт awk для замены ключевых слов в определенном файле. Третий файл - это файл конфигурации, который содержит значения, которые должны быть заменены (помимо переменных, таких как число коммитов и метка времени).
Как вы используете его?
Ты звонишь keysub
вместо фиксации с теми же параметрами. -m
или же -a
опция должна стоять перед любой другой опцией коммита. Новый вариант (который всегда должен стоять первым) -f
который принимает файл конфигурации в качестве значения. Пример:
$ git add 'someJavaFile.java'
$ keysub -m 'fixed concurrent thread issue'
$ git push
или же
$ 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
}
Конфиг файл
author:ubunut-420
timestamp:Fri Jun 21 20:42:54 CEST 2013
commitmsg:default commit message
замечания
Я попытался документировать достаточно хорошо, чтобы вы могли легко реализовать его и изменить в соответствии со своими потребностями. Обратите внимание, что вы можете дать макросам любое имя по вашему желанию, если вы измените его в исходном коде. Я также стремился сделать сценарий относительно простым для расширения, чтобы вы могли довольно легко добавлять новые макросы. Если вы заинтересованы в расширении или изменении скрипта, возможно, вы захотите взглянуть и на каталог.git, там должно быть много информации, которая может помочь улучшить скрипт из-за нехватки времени, которое я не сделал изучить папку, хотя.
Git не поставляется с этой функциональностью из коробки. Однако в Git Book есть глава, посвященная настройке Git, и один из примеров - как использовать атрибуты git для реализации аналогичного результата.
Оказывается, вы можете написать свои собственные фильтры для выполнения подстановок в файлах при коммите / оформлении заказа. Они называются "чистыми" и "грязными" фильтрами. в
.gitattributes
файл, вы можете установить фильтр для определенных путей, а затем настроить сценарии, которые будут обрабатывать файлы непосредственно перед их извлечением ("пятно") и непосредственно перед их подготовкой ("очистка"). Эти фильтры могут быть настроены на все виды забавных вещей.
Есть даже пример для $LastChangedDate: $
:
Еще один интересный пример получает
$Date$
расширение ключевых слов, стиль RCS. Чтобы сделать это правильно, вам нужен небольшой скрипт, который принимает имя файла, вычисляет дату последней фиксации для этого проекта и вставляет дату в файл. Вот небольшой скрипт Ruby, который делает это:#! /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 для очистки этого при фиксации:$ git config filter.dater.smudge expand_date $ git config filter.dater.clean 'perl -pe "s/\\\$Date[^\\\$]*\\\$/\\\$Date\\\$/"'
Этот фрагмент Perl удаляет все, что он видит в
$Date$
строка, чтобы вернуться туда, где вы начали. Теперь, когда ваш фильтр готов, вы можете проверить его, настроив атрибут Git для этого файла, который включает новый фильтр, и создав файл с вашим$Date$
ключевое слово:date*.txt filter=dater $ echo '# $Date$' > date_test.txt If you commit
те изменения и проверьте файл снова, вы видите ключевое слово, правильно замененное:
$ 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
) нет, поэтому он не будет работать везде. Когда вы проектируете эти фильтры, они должны быть в состоянии изящно провалиться, и проект все еще будет работать должным образом.
К сожалению нет.
Прочитайте их документацию, ссылка прилагается: Расширение ключевых слов
Абсурдна идея о том, что расширение ключевых слов «не рекомендуется» и «бесполезно». Независимо от того, компилируете ли вы код в двоичные файлы, JAR-файлы или что-то еще, каждая система исходного кода, начиная с SCCS в 1970-х годах, поддерживает форму расширения ключевых слов. Цель состоит в том, чтобы позволить разработчику просматривать любой производный артефакт в любой среде и отслеживать точную версию каждого исходного файла, который был включен в артефакт. Без какой-либо формы расширения ключевых слов это невозможно, и вам остается только догадываться.