我有一个本地git存储库,使用:
创建git clone --mirror git://github.com/<user>/<project>.git
偶尔会有更改被推送到github,这台机器会将它们拉到:
git remote update --prune
这一切都运行正常,但在更新后,我想运行一个钩子,我不确定要运行哪个。我尝试过“post-receive”和“post-merge”,但似乎在更新后都没有执行。在这两种情况下,钩子文件的内容都是:
#!/bin/sh
echo foo > foo.log
当我从命令行通过bash.exe运行它们(是的,在Windows上)时,会创建一个foo.log文件,这样就行了。但是由于“git远程更新”没有任何结果。在每个“git远程更新”之间,我正在推动一项无用的更改,以确保有一些东西可以拉动。
答案 0 :(得分:3)
我最后通过制作一个小的bash脚本来包装&#34; git远程更新&#34;命令。该脚本查看更新之前和之后的所有refspecs,然后以与git具有缺失功能相同的方式调用更新后挂钩。感谢他们对原始问题的评论中的@torek和@larsks。
注意:此脚本使用bash关联数组,这些数组仅在bash版本&gt; = 4.0中可用。
#!/bin/bash
git_dir=$(git rev-parse --git-dir) || exit
cd "$git_dir"
declare -A before after all
# create the 'before' list
while read commit_hash refspec; do
before[$refspec]="$commit_hash"
all[$refspec]=''
done < <(git show-ref --heads)
# do the remote update
git remote update --prune
# create the 'after' list
while read commit_hash refspec; do
after[$refspec]="$commit_hash"
all[$refspec]=''
done < <(git show-ref --heads)
# see if there were any changes, and if so, run the post-receive hook
changes=0
for refspec in "${!all[@]}"; do
[ "${before[$refspec]}" != "${after[$refspec]}" ] && { changes=1; break; }
done
if [ "$changes" == "1" ]; then
none="$(printf "%0.s0" {1..40})" # forty zeroes, or git's "don't care" ref
for refspec in "${!all[@]}"; do
# if the refspec changed, pass it to the post-receive hook
[ "${before[$refspec]}" != "${after[$refspec]}" ] && \
echo "${before[$refspec]:-$none} ${after[$refspec]:-$none} $refspec"
done | hooks/post-receive
fi
答案 1 :(得分:1)
对于那些没有bash 4的Windows用户来说,这是一个awk:
#!/bin/sh
GIT_DIR=`git rev-parse --git-dir` || exit
cd "$GIT_DIR"
before=`git show-ref`
git remote update --prune
after=`git show-ref`
{ echo "$before"
echo
echo "$after"
} | awk '
/^$/ {++after; next}
1 { ++seen[$2]
if (!after) old[$2]=$1; else new[$2]=$1
}
END { z8="00000000"; none = z8 z8 z8 z8 z8
for ( k in seen ) if (old[k] != new[k])
print (old[k]?old[k]:none), (new[k]?new[k]:none), k
}
' | hooks/post-receive