我只想指出另一种可能的方法——那就是使用 git git-notes(1),自 v 1.6.6 (Note to Self - Git) 以来就存在(我正在使用 git 版本 1.7.9.5 )。
基本上,我使用git svn 克隆具有线性历史记录(无标准布局、无分支、无标签)的 SVN 存储库,并且我想比较克隆的git 存储库中的修订号。这个 git clone 默认没有标签,所以我不能使用git describe。这里的策略可能仅适用于线性历史 - 不确定合并等结果如何;但这里是基本策略:
- 向
git rev-list询问所有提交历史的列表
- 由于
rev-list 默认情况下按“时间倒序”排列,我们将使用其--reverse 开关来获取按最早排序的提交列表
- 使用
bash shell
- 在每次提交时增加一个计数器变量作为修订计数器,
- 为每个提交生成并添加一个“临时”git 注释
- 然后,使用
git log 和--notes 浏览日志,这也将转储提交的注释,在本例中为“修订号”
- 完成后,擦除临时注释(注意:我不确定这些注释是否已提交;它们不会真正显示在
git status)
首先,让我们注意git 有一个默认的笔记位置——但你也可以为笔记指定一个ref(erence)——这会将它们存储在.git 下的不同目录中;例如,在git repo 文件夹中,您可以调用git notes get-ref 来查看将是哪个目录:
$ git notes get-ref
refs/notes/commits
$ git notes --ref=whatever get-ref
refs/notes/whatever
需要注意的是,如果您在notes add 中使用--ref,则之后您还必须再次使用该引用 - 否则您可能会收到类似“No note found for object XXX...”。
对于这个例子,我选择将注释的ref 称为“linrev”(用于线性修订)——这也意味着该过程不太可能会干扰已经存在的注释。我也在使用--git-dir 开关,因为作为git 新手,我在理解它时遇到了一些问题——所以我想“以后记住”:);我还使用--no-pager 来抑制less 在使用git log 时产生。
所以,假设您在一个目录中,有一个子文件夹 myrepo_git,这是一个 git 存储库;可以这样做:
### check for already existing notes:
$ git --git-dir=./myrepo_git/.git notes show
# error: No note found for object 04051f98ece25cff67e62d13c548dacbee6c1e33.
$ git --git-dir=./myrepo_git/.git notes --ref=linrev show
# error: No note found for object 04051f98ece25cff67e62d13c548dacbee6c1e33.
### iterate through rev-list three, oldest first,
### create a cmdline adding a revision count as note to each revision
$ ix=0; for ih in $(git --git-dir=./myrepo_git/.git rev-list --reverse HEAD); do \
TCMD="git --git-dir=./myrepo_git/.git notes --ref linrev"; \
TCMD="$TCMD add $ih -m \"(r$((++ix)))\""; \
echo "$TCMD"; \
eval "$TCMD"; \
done
# git --git-dir=./myrepo_git/.git notes --ref linrev add 6886bbb7be18e63fc4be68ba41917b48f02e09d7 -m "(r1)"
# git --git-dir=./myrepo_git/.git notes --ref linrev add f34910dbeeee33a40806d29dd956062d6ab3ad97 -m "(r2)"
# ...
# git --git-dir=./myrepo_git/.git notes --ref linrev add 04051f98ece25cff67e62d13c548dacbee6c1e33 -m "(r15)"
### check status - adding notes seem to not affect it:
$ cd myrepo_git/
$ git status
# # On branch master
# nothing to commit (working directory clean)
$ cd ../
### check notes again:
$ git --git-dir=./myrepo_git/.git notes show
# error: No note found for object 04051f98ece25cff67e62d13c548dacbee6c1e33.
$ git --git-dir=./myrepo_git/.git notes --ref=linrev show
# (r15)
### note is saved - now let's issue a `git log` command, using a format string and notes:
$ git --git-dir=./myrepo_git/.git --no-pager log --notes=linrev --format=format:"%h: %an: %ad: >>%s<< %N" HEAD
# 04051f9: _user_: Sun Apr 21 18:29:02 2013 +0000: >>test message 15 << (r15)
# 77f3902: _user_: Sun Apr 21 18:29:00 2013 +0000: >>test message 14<< (r14)
# ...
# 6886bbb: _user_: Sun Apr 21 17:11:52 2013 +0000: >>initial test message 1<< (r1)
### test git log with range:
$ git --git-dir=./myrepo_git/.git --no-pager log --notes=linrev --format=format:"%h: %an: %ad: >>%s<< %N" HEAD^..HEAD
# 04051f9: _user_: Sun Apr 21 18:29:02 2013 +0000: >>test message 15 << (r15)
### erase notes - again must iterate through rev-list
$ ix=0; for ih in $(git --git-dir=./myrepo_git/.git rev-list --reverse HEAD); do \
TCMD="git --git-dir=./myrepo_git/.git notes --ref linrev"; \
TCMD="$TCMD remove $ih"; \
echo "$TCMD"; \
eval "$TCMD"; \
done
# git --git-dir=./myrepo_git/.git notes --ref linrev remove 6886bbb7be18e63fc4be68ba41917b48f02e09d7
# Removing note for object 6886bbb7be18e63fc4be68ba41917b48f02e09d7
# git --git-dir=./myrepo_git/.git notes --ref linrev remove f34910dbeeee33a40806d29dd956062d6ab3ad97
# Removing note for object f34910dbeeee33a40806d29dd956062d6ab3ad97
# ...
# git --git-dir=./myrepo_git/.git notes --ref linrev remove 04051f98ece25cff67e62d13c548dacbee6c1e33
# Removing note for object 04051f98ece25cff67e62d13c548dacbee6c1e33
### check notes again:
$ git --git-dir=./myrepo_git/.git notes show
# error: No note found for object 04051f98ece25cff67e62d13c548dacbee6c1e33.
$ git --git-dir=./myrepo_git/.git notes --ref=linrev show
# error: No note found for object 04051f98ece25cff67e62d13c548dacbee6c1e33.
因此,至少在我没有分支的完全线性历史的特定情况下,修订号似乎与这种方法相匹配 - 此外,这种方法似乎允许在修订范围内使用 git log,同时仍然获得正确的修订号 - 具有不同上下文的 YMMV...
希望这对某人有所帮助,
干杯!
编辑:好的,这里有点简单,上面的循环使用git 别名,称为setlinrev 和unsetlinrev;在您的 git 存储库文件夹中时,执行(注意讨厌的bash 转义,另请参阅#16136745 - Add a Git alias containing a semicolon):
cat >> .git/config <<"EOF"
[alias]
setlinrev = "!bash -c 'ix=0; for ih in $(git rev-list --reverse HEAD); do \n\
TCMD=\"git notes --ref linrev\"; \n\
TCMD=\"$TCMD add $ih -m \\\"(r\\$((++ix)))\\\"\"; \n\
#echo \"$TCMD\"; \n\
eval \"$TCMD\"; \n\
done; \n\
echo \"Linear revision notes are set.\" '"
unsetlinrev = "!bash -c 'ix=0; for ih in $(git rev-list --reverse HEAD); do \n\
TCMD=\"git notes --ref linrev\"; \n\
TCMD=\"$TCMD remove $ih\"; \n\
#echo \"$TCMD\"; \n\
eval \"$TCMD 2>/dev/null\"; \n\
done; \n\
echo \"Linear revision notes are unset.\" '"
EOF
...所以您可以在尝试记录涉及线性修订注释的日志之前简单地调用git setlinrev;和git unsetlinrev 完成后删除这些笔记;来自 git repo 目录的示例:
$ git log --notes=linrev --format=format:"%h: %an: %ad: >>%s<< %N" HEAD^..HEAD
04051f9: _user_: Sun Apr 21 18:29:02 2013 +0000: >>test message 15 <<
$ git setlinrev
Linear revision notes are set.
$ git log --notes=linrev --format=format:"%h: %an: %ad: >>%s<< %N" HEAD^..HEAD
04051f9: _user_: Sun Apr 21 18:29:02 2013 +0000: >>test message 15 << (r15)
$ git unsetlinrev
Linear revision notes are unset.
$ git log --notes=linrev --format=format:"%h: %an: %ad: >>%s<< %N" HEAD^..HEAD
04051f9: _user_: Sun Apr 21 18:29:02 2013 +0000: >>test message 15 <<
shell 完成这些别名所需的时间取决于存储库历史记录的大小。