虽然 Mercurial(1) 已经有一个定义明确的 API(尽管是内部的)可以去开发 Mercurial 功能的扩展,但是 git 的扩展模型遵循 Unix 的哲学,即开发小的程序去实现相同的效果。这意味着 git 的扩展可以使用任何语言编写,只需要遵循一些简单的规则,就可以 git 内置命令那样。
例子:git activity
我实现了一个 git activity 命令去看仓库中各个分支上的活动,这个命令会显示每个分支上最新的 commit,根据提交时间来排序。
下面这张图就是在 Radils 仓库执行这个命令的结果:
这个脚本是用 bash 来编写的,非常简单。我们设置了颜色并且解析了一些脚本支持的命令行参数(例如:关闭颜色,限制输出),然后运行 git for-each-ref 以输出每个引用的信息。
#!/bin/bash
set -e
GIT_OPTS=""
OUTPUT_FILTER="cat" # no-op
commit_id_format=$(tput setaf 1)
date_format=$(tput bold; tput setaf 4)
author_format=$(tput setaf 2)
ref_name_format=$(tput setaf 3)
bold=$(tput bold)
reset=$(tput sgr0)
function usage() {
echo ""
echo "git activity"
echo ""
echo " See 'man git-activity' for further information"
}
# actually parse the options and do stuff
while [[ $1 = -?* ]]; do
case $1 in
-h|--help)
usage
exit 0
;;
--fetch)
echo "Fetch updates"
git fetch -q
;;
-c|--count)
shift
limit=${1-"10"}
#OUTPUT_FILTER="tail -n ${limit}"
GIT_OPTS="--count=${limit}"
;;
--no-color|--no-color)
commit_id_format=""
date_format=""
author_format=""
ref_name_format=""
bold=""
reset=""
;;
*) ;;
esac
shift
done
# Use newline as a field separator
IFS=$(echo -en "\n\b")
# Use tac if available, otherwise tail with the possibly-not-always-available
# -r flag (for reverse output)
TAC=$(which tac || echo 'tail -r')
for line in $(git for-each-ref ${GIT_OPTS} refs/remotes --format="%(authordate:relative)|%(objectname:short)|%(authorname)|%(refname:short)|%(subject)" --sort="-authordate"); do
fields=(`echo $line | tr "|" "\n"`)
printf "${date_format}%15s${reset} ${commit_id_format}%s${reset} - ${author_format}[%s]${reset} (${ref_name_format}%s${reset}): %s\n" ${fields[*]}
done | eval $TAC # reverse sort the output to show the newest entry last
遵循这些重要的规则可以让这个脚本作为 git 子命令:
- 它应该被命名为 git-COMMANDNAME,在上面的例子中,它被命名为 git-activity
- 这个脚本必须是可执行文件,并且在 $PATH 是可用的。在上面的例子中,
git-activity脚本在/usr/local/bin目录中,当然也可以在PATH中的其他文件夹里。
[5002] λ > type git-activity
git-activity is /usr/local/bin/git-activity
[5002] λ > git activity
[...]
提供手册/帮助页面
如果自定义命令还附带了一个手册页(man page),那么 git help 也会显示这个帮助信息。例如,git activity 的帮助页面位于/usr/local/share/man/man1/git-activity.1,可以通过 man git-activity 或者 git help activity 来显示。
manpath 命令可以显示系统定位帮助页面(man page)的位置。
[5003] λ > manpath /Users/ssaasen/.opam/system/man:/usr/local/share/man:/usr/share/man:\ /Users/ssaasen/.cabal/share/man:/opt/scala/man
git help activity 的输出(使用了https://bitbucket.org/ssaasen/git-pastiche/src/master/man/git-activity.1 )
帮助页面可以使用Pandoc简单得通过Markdown 来生成:
[5010] λ > pandoc -s -w man doc/git-activity.1.md -o ./distribution/man/git-activity.1
# Display the man page for testing
[5011] λ > nroff -man ./distribution/man/git-activity.1
# Show the actual man page being used after copying it to a known manpath location:
[5012] λ > man -wa git-activity
/usr/local/share/man/man1/git-activity.1
结论
扩展git的功能并使自定义命令成为git命令套件的一部分非常容易。
更多扩展
git-activity以及其他一些命令的源代码可以在这里找到:bitbucket.org/ssaasen/git…
其他附加的git命令可以在这里找到:
备注
- Mercurial 是一个供开发者使用的跨平台的分布式版本控制工具,主要由 Python 实现,支持在 Windows 和类 Unix 系统(如 FreeBSD、Mac OS X 和 Linux)上使用。 mercurial.selenic.com
- 本文只是很简陋的翻译了一下,讲究的是信达雅三不沾,意思大体符合就 OK。