51

以前は Subversion/SVN で作業していましたが、すぐにキーワード置換と呼ばれる優れた機能を使用していました。ソースファイルを次のように入れるだけです:

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

Subversion がキーワード (Author、Rev、LastChangedDate) を実際のキーワードに置き換えるたびに。

少し前に Git への移行を余儀なくされましたが、Git に Subversion のキーワード置換に似たものがあるのではないかと思っています。

4

3 に答える 3

17

解決

まあ、そのような機能を自分で簡単に実装できます。

基本的に、commit コマンドをシェル スクリプトに埋め込みました。このスクリプトは、最初に必要なマクロを置き換えてから、変更をコミットします。プロジェクトは次の 2 つのファイルで構成されます。

コンテンツ?

keysub、bash シェル スクリプト、およびkeysub.awk特定のファイル内のキーワードを置き換える awk スクリプト。3 番目のファイルは、置換する必要がある値を含む構成ファイルです (コミット カウントやタイムスタンプなどの変数に加えて)。

どうやって使うんですか?

keysub同じオプションでコミットする代わりに呼び出します。-morオプションは、-a他のコミット オプションよりも前に指定する必要があります。新しいオプション (常に最初に来る必要が-fあります) は、構成ファイルを値として受け取るものです。例:

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

また

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

キーサブ

#!/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 ディレクトリも参照してください。スクリプトを強化するのに役立つ情報がたくさんあるはずです。ただし、フォルダーを調査します。

于 2013-06-21T19:13:44.343 に答える