Я просто хотел бы отметить другой возможный подход - это использование git
git-notes (1) , существующее начиная с версии 1.6.6 ( Примечание к Self-Git ) (я используюgit
версию 1.7.9.5).
Обычно я git svn
клонировал SVN-репозиторий с линейной историей (без стандартного макета, без ветвей, без тегов) и хотел сравнить номера ревизий в клонированном git
репозитории. Этот git-клон не имеет тегов по умолчанию, поэтому я не могу его использовать git describe
. Стратегия здесь, вероятно, будет работать только для линейной истории - не уверен, как это получится с объединениями и т. Д .; но вот основная стратегия:
- Спросите
git rev-list
список всей истории коммитов
- Так
rev-list
как по умолчанию в «обратном хронологическом порядке», мы использовали бы его --reverse
переключатель, чтобы получить список коммитов, отсортированных по самым старым первым
- Используйте
bash
оболочку для
- увеличить переменную счетчика для каждого коммита как счетчик ревизий,
- генерировать и добавлять «временные» git note для каждого коммита
- Затем просмотрите журнал, используя
git log
с --notes
, который также выведет заметку коммита, которая в этом случае будет "номером ревизии"
- Когда закончите, удалите временные заметки ( примечание: я не уверен, зафиксированы ли эти заметки или нет; на самом деле они не отображаются
git status
)
Во-первых, давайте отметим, что у git
него есть расположение заметок по умолчанию - но вы также можете указать ref
(erence) для заметок - которые будут хранить их в другом каталоге .git
; например, находясь в git
папке репо, вы можете позвонить, git notes get-ref
чтобы узнать, какой каталог это будет:
$ git notes get-ref
refs/notes/commits
$ git notes --ref=whatever get-ref
refs/notes/whatever
Следует отметить, что если вы используете notes add
a --ref
, вы должны впоследствии снова использовать эту ссылку - в противном случае вы можете получить ошибки типа « Нет заметки для объекта 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 - Добавьте псевдоним Git, содержащий точку с запятой ):
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 <<
Время, которое потребуется оболочке для завершения этих псевдонимов, будет зависеть от размера истории хранилища.