我有一个git post-receive hook,它提取在“git push”期间添加的所有修订,并对每个修订进行一些处理(例如发送通知电子邮件)。这种方法很有效,除非合并时; e.g:
我该如何避免这种情况?下面是我的post-receive钩子的开头,我提取了应该处理的提交(最后$ COMMITS保存了要处理的提交列表)。
#!/bin/sh
REPO_PATH=`pwd`
COMMITS=''
SHELL=/bin/sh
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
# for each ref that was updated during the push
while read OLD_REV NEW_REV REF_NAME; do
OLD_REV="`git rev-parse $OLD_REV`"
NEW_REV="`git rev-parse $NEW_REV`"
if expr "$OLD_REV" : '0*$' >/dev/null; then
# if the branch was created, add all revisions in the new branch; skip tags
if ! expr "$REF_NAME" : 'refs/tags/' >/dev/null; then
REF_REV="`git rev-parse $REF_NAME`"
REF_NAME="`git name-rev --name-only $REF_REV`"
COMMITS="$COMMITS `git rev-list $REF_NAME | git name-rev --stdin | grep -G \($REF_NAME.*\) | awk '{ print $1 }' | tr '\n' ' '`"
fi
elif expr "$NEW_REV" : '0*$' >/dev/null; then
# don't think branch deletes ever hit a post-receive hook, so we should never get here
printf ''
else
# add any commits in this push
COMMITS="$COMMITS `git rev-parse --not --all | grep -v $(git rev-parse $REF_NAME) | git rev-list --reverse --stdin $(git merge-base $OLD_REV $NEW_REV)..$NEW_REV | tr '\n' ' '`"
fi
done
答案 0 :(得分:6)
看看$(prefix)/share/git-core/contrib/hooks/post-receive-email
,这就是我想要的(我认为)。基本上它使用git for-each-ref
来查找所有分支的名称,然后排除除了正在更新的分支之外的某个分支可以访问的每个提交:
if [ "$change_type" = create ]
then
# Show all revisions exclusive to this (new) branch.
revspec=$newrev
else
# Branch update; show revisions not part of $oldrev.
revspec=$oldrev..$newrev
fi
other_branches=$(git for-each-ref --format='%(refname)' refs/heads/ |
grep -F -v $refname)
git rev-parse --not $other_branches | git rev-list --pretty --stdin $revspec
(我在这里对其进行了简化,希望在我的剪切和粘贴作业中没有任何损坏。这里的输入是:$change_type
create
$oldrev
如果update
全部 - 零,否则它是$oldrev
; $newrev
是最近从stdin读取的行中的旧rev SHA1; $refname
是新的rev SHA1; refs/heads/topic
是全名例如,{{1}}。)
答案 1 :(得分:1)
我们所做的是将先前处理的提交的哈希值保存在文本文件中。每次钩子运行时,它都会查找该文件以检查是否已经处理了给定的提交。如果它还没有处理该提交,请处理它,然后将该提交记录到该文件中。
这不是很可扩展,因为文本文件只会随着更多提交添加到存储库而增长,并且检查给定提交的时间也会增加。
答案 2 :(得分:0)
我们通过在遇到合并提交(具有两个或更多父项的提交)时使用post-receive挂钩停止处理来完成此操作。这在推送合并时需要一些纪律,以确保不会抛弃其他“真正的”提交。该规则是在合并之前始终推送,然后分别推送合并。
答案 3 :(得分:0)
我在post-receive hook中完全实现了这个。无论新提交是同时推送到单个分支还是多个分支,它都会在上次提取 之后仅通知trac,而不会复制 。此方法在git目录中保留一个名为TRAC_HEAD
的文件,用于跟踪已处理的提交。
建议您在启用挂钩之前在cat refs/heads/* > TRAC HEAD
目录中运行.git
。
#!/bin/sh
#
# Reads and notifies trac of only new commits that have not yet been dealt with.
#
# The "post-receive" script is run after receive-pack has accepted a pack
# and the repository has been updated. It is passed arguments in through
# stdin in the form
# <oldrev> <newrev> <refname>
# For example:
# aa453216d1b3e49e7f6f98441fa56946ddcd6a20 68f7abf4e6f922807889f52bc043ecd31b79f814 refs/heads/master
#
TRAC_PATH="/path/to/trac/env"
# Read the standard input
while read oldrev newrev refname ; do
echo "Processing branch: $refname"
# Read the last revisions for each branch from TRAC_HEAD
exclusions=$(cat TRAC_HEAD | uniq | sed -e 's/^/^/' -e 's/ / ^/g' | xargs echo)
echo "Exclusion list: $exclusions"
git rev-list --reverse $newrev $exclusions | while read rev ; do
trac-admin $TRAC_PATH changeset added '(default)' $rev
echo "Processed: $rev"
done
# Add to the exclusions file the latest revision from this branch
echo $newrev >> TRAC_HEAD
done
# Update the TRAC_HEAD file
cat refs/heads/* > TRAC_HEAD