Комментарий ElpieKay имеет ключ к ответу, но стоит немного подробнее.Поскольку сервер на самом деле не выполнял git commit
, вы должны использовать ловушку после получения, чтобы следить за обновлениями ссылок.К сожалению, зацепки после получения не просты.Вот простой полезный каркас, выраженный в оболочке POSIX:
#! /bin/sh
# sample post-receive hook
# return true if the argument ($1) is the null hash (all-0s)
is_nullhash() {
expr "$1" : '0*$' >/dev/null
}
while read oldhash newhash ref; do
# If the old hash is all 0s, the reference was just created.
# If the new hash is all 0s, the reference was just deleted.
# Otherwise, the reference was updated, from $oldhash to $newhash.
if is_nullhash $oldhash; then
op=create
elif is_nullhash $newhash; then
op=delete
else
op=update
fi
# If the reference begins with refs/heads/, the rest of it is
# a branch name. If it starts with refs/tags, the rest is a tag.
# Otherwise it's some other type of reference (not decoded here).
case $ref in
refs/heads/*) reftype=branch; shortref=${ref#refs/heads/};;
refs/tags/*) reftype=tag; shortref=${ref#refs/tags/};;
*) reftype=other; shortref=$ref;; # NB: not shortened!
esac
... insert code here ...
done
Код, указанный в разделе «вставить код здесь», должен:
- определить, является ли этоэто операция, о которой вы заботитесь
- , если это так, решите, что делать, основываясь на типе операции
Например, если вы хотите специально наблюдать толчок к master
только:
if [ $reftype = branch -a $shortref = master ]; then
if [ $op = update ]; then
handle_master_update $oldhash $newhash
else
... do something different if the op is create or delete ...
fi
fi
, где handle_master_update
- ваша функция для обновления до master
.Если вы не хотите обрабатывать создание и удаление ветки master
, вы можете еще больше упростить это до:
case $ref,$op in
refs/heads/master,update) handle_master_update $oldhash $newhash;;
esac
, в этом случае вы можете удалить шаблонный раздел, который декодирует ссылочный тип.
Теперь мы переходим к сути обработки обновлений:
# Do something with update to master branch.
# The old hash is $1 and the new hash is $2,
# so commits in $1..$2 now appear on `master` but
# were not part of `master` before (they may have
# been on some other branch, and may still be).
# Meanwhile, commits in $2..$1 used to be on `master`
# but have just been removed via force-push. If this
# list is empty, the push did not have to be forced,
# and maybe was not.
handle_master_update() {
local rev parents
git rev-list $2..$1 | while read rev; do ...; done # deal with removed commits
git rev-list --parents $1..$2 | while read rev parents; do
...
done
}
Первый раздел (посвященный удаленным коммитам), конечно, не является обязательным.Во втором разделе вы хотели обнаружить слияния, поэтому мы используем git rev-list
(не git log
- здесь более полезна рабочая лошадка), чтобы перечислить все добавленные коммиты вместе с их родительскими хэш-идентификаторами..read
помещает все родительские хеши в переменную parents
, поэтому мы можем легко сосчитать их в разделе ...
.Например:
set -- $parents
case $# in
0) ...;; # $rev is a root commit
1) ...;; # $rev is an ordinary commit
*) ...;; # $rev is a merge, its parents are $1, $2, ... through $#
esac
Нулевой случай весьма необычен - для того, чтобы это произошло как обновление, мы должны добавить корневой ветвь к ветви, например, из:
A--B--C <-- master
до:
A--B--C--D--H <-- master
/
F---------G
В git rev-list
, заданном C..H
(ну, их хэш-идентификаторы), будут перечислены H
, D
, G
и F
в некоторыхпорядок.Хеш для H
будет первым, но все после этого зависит от любых параметров сортировки, которые вы предоставляете для git rev-list
.Используйте --topo-order
, чтобы гарантировать получение топологической сортировки, если это важно для работы вашего кода (например, вам может потребоваться --reverse --topo-sort
, чтобы всегда работать вперед , получая одно из D, F, G, H
или F, G, D, H
в качестве входных данных).
Обратите внимание, что если вы используете POSIX-совместимый sh
для реализации своей ловушки, то раздражает git rev-list ... | while read ...
: цикл while
выполняется в подоболочкеЭто означает, что любые переменные, установленные здесь, теряются при выходе из цикла.Вы можете обойти это несколькими способами;см. Дилемма подобъекта цикла цикла в Bash .