local git hook for “git remote update”?

折月煮酒 提交于 2019-12-13 16:19:56

问题


I have a local git repository, created with:

git clone --mirror git://github.com/<user>/<project>.git

Occasionally changes will get pushed to github, and this machine will pull them with:

git remote update --prune

This all works fine, but after the update, I want to run a hook, and I'm not sure which to run. I have tried "post-receive" and "post-merge", but neither seems to execute after the update. In both cases, the contents of the hook file are:

#!/bin/sh 
echo foo > foo.log

When I run them from the command-line via bash.exe (yes, on Windows), a foo.log file is created, so that works. But nothing happens as a result of the "git remote update". Between each "git remote update" I am pushing a useless change to make sure there's something to pull.


回答1:


I ended up solving this by making a little bash script to wrap the "git remote update" command. The script looks at all refspecs before and after the update, then calls the post-update hook in the same way that git would if it had the missing feature. Credit to @torek and @larsks for the idea in their comments to the original question.

Note: this script uses bash associative arrays which are only available in bash versions >= 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



回答2:


Here's an awk for Windows people who don't have bash 4:

#!/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


来源:https://stackoverflow.com/questions/21567518/local-git-hook-for-git-remote-update

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!