Documentation / howto / update-hook-example.txton commit Documentation: git-diff asciidoc table workaround. (dfa2f22)
   1From: Junio C Hamano <junkio@cox.net>
   2Subject: control access to branches.
   3Date: Thu, 17 Nov 2005 23:55:32 -0800
   4Message-ID: <7vfypumlu3.fsf@assigned-by-dhcp.cox.net>
   5Abstract: An example hooks/update script is presented to
   6 implement repository maintenance policies, such as who can push
   7 into which branch and who can make a tag.
   8
   9When your developer runs git-push into the repository,
  10git-receive-pack is run (either locally or over ssh) as that
  11developer, so is hooks/update script.  Quoting from the relevant
  12section of the documentation:
  13
  14    Before each ref is updated, if $GIT_DIR/hooks/update file exists
  15    and executable, it is called with three parameters:
  16
  17           $GIT_DIR/hooks/update refname sha1-old sha1-new
  18
  19    The refname parameter is relative to $GIT_DIR; e.g. for the
  20    master head this is "refs/heads/master".  Two sha1 are the
  21    object names for the refname before and after the update.  Note
  22    that the hook is called before the refname is updated, so either
  23    sha1-old is 0{40} (meaning there is no such ref yet), or it
  24    should match what is recorded in refname.
  25
  26So if your policy is (1) always require fast-forward push
  27(i.e. never allow "git-push repo +branch:branch"), (2) you
  28have a list of users allowed to update each branch, and (3) you
  29do not let tags to be overwritten, then:
  30
  31        #!/bin/sh
  32        # This is a sample hooks/update script, written by JC
  33        # in his e-mail buffer, so naturally it is not tested
  34        # but hopefully would convey the idea.
  35
  36        umask 002
  37        case "$1" in
  38        refs/tags/*)
  39                # No overwriting an existing tag
  40                if test -f "$GIT_DIR/$1"
  41                then
  42                        exit 1
  43                fi
  44                ;;
  45        refs/heads/*)
  46                # No rebasing or rewinding
  47                if expr "$2" : '0*$' >/dev/null
  48                then
  49                        # creating a new branch
  50                        ;
  51                else
  52                        # updating -- make sure it is a fast forward
  53                        mb=`git-merge-base "$2" "$3"`
  54                        case "$mb,$2" in
  55                        "$2,$mb")
  56                                ;; # fast forward -- happy
  57                        *)
  58                                exit 1 ;; # unhappy
  59                        esac
  60                fi
  61                ;;
  62        *)
  63                # No funny refs allowed
  64                exit 1
  65                ;;
  66        esac
  67
  68        # Is the user allowed to update it?
  69        me=`id -u -n` ;# e.g. "junio"
  70        while read head_pattern users
  71        do
  72                if expr "$1" : "$head_pattern" >/dev/null
  73                then
  74                        case " $users " in
  75                        *" $me "*)
  76                                exit 0 ;; # happy
  77                        ' * ')
  78                                exit 0 ;; # anybody
  79                        esac
  80                fi
  81        done
  82        exit 1
  83
  84For the sake of simplicity, I assumed that you keep something
  85like this in $GIT_DIR/info/allowed-pushers file:
  86
  87        refs/heads/master       junio
  88        refs/heads/cogito$      pasky
  89        refs/heads/bw/          linus
  90        refs/heads/tmp/         *
  91        refs/tags/v[0-9]*       junio
  92
  93With this, Linus can push or create "bw/penguin" or "bw/zebra"
  94or "bw/panda" branches, Pasky can do only "cogito", and I can do
  95master branch and make versioned tags.  And anybody can do
  96tmp/blah branches.  This assumes all the users are in a single
  97group that can write into $GIT_DIR/ and underneath.
  98
  99
 100
 101
 102
 103
 104
 105