git/list[1] front-page[2] threads[3] people[4] search[5] about
 

Re: [RFC] Using sticky directories to control access to branches.

From
Junio C Hamano <junkio@cox.net>
Date
Nov 18, 2005, 07:55 UTC
Message-ID
<7vfypumlu3.fsf@assigned-by-dhcp.cox.net>
In-Reply-To
<20051117170129.GA14013@hpsvcnb.fc.hp.com>
Carl Baldwin <cnb@fc.hp.com> writes:
> Now, git was probably designed to do this on purpose because it is the
> safest way to update a branch in an automic way.

Yes. How about using hooks/update? The documentation for receive-pack suggests the use of it for generating commit notification e-mails, but this is more general mechanism.

When your developer runs git-push into the repository, git-receive-pack is run (either locally or over ssh) as that developer, so is hooks/update script. Quoting from the relevant section of the documentation:

    Before each ref is updated, if $GIT_DIR/hooks/update file exists
    and executable, it is called with three parameters:
           $GIT_DIR/hooks/update refname sha1-old sha1-new
    The refname parameter is relative to $GIT_DIR; e.g. for the
    master head this is "refs/heads/master".  Two sha1 are the
    object names for the refname before and after the update.  Note
    that the hook is called before the refname is updated, so either
    sha1-old is 0{40} (meaning there is no such ref yet), or it
    should match what is recorded in refname.

So if your policy is (1) always require fast-forward push (i.e. never allow "git-push repo +branch:branch"), (2) you have a list of users allowed to update each branch, and (3) you do not let tags to be overwritten, then:

	#!/bin/sh
	# This is a sample hooks/update script, written by JC
        # in his e-mail buffer, so naturally it is not tested
        # but hopefully would convey the idea.
	umask 002
        case "$1" in
        refs/tags/*)
		# No overwriting an existing tag
        	if test -f "$GIT_DIR/$1"
                then
                	exit 1
		fi
	refs/heads/*)
        	# No rebasing or rewinding
                if expr "$2" : '0*$' >/dev/null
                then
                	# creating a new branch
			;
		else
                	# updating -- make sure it is a fast forward
        		mb=`git-merge-base "$2" "$3"`
			case "$mb,$2" in
                        "$2,$mb")
                        	;; # fast forward -- happy
			*)
                        	exit 1 ;; # unhappy
			esac
		fi
	esac
	# Is he allowed to update it?
	me=`id -u -n` ;# e.g. "junio"
	while read head_pattern users
        do
		if expr "$1" : "$head_pattern" >/dev/null
		then
			case " $users " in
			*" $me "*)
                        	exit 0 ;; # happy
			'*')
                        	exit 0 ;; # anybody
			esac
		fi
	done
	exit 1

For the sake of simplicity, I assumed that you keep something like this in $GIT_DIR/info/allowed-pushers file:

	refs/heads/master	junio
        refs/heads/cogito$	pasky
	refs/heads/bw/		linus
        refs/heads/tmp/		*
        refs/tags/v[0-9]*	junio

With , Linus can push or create "bw/penguin" or "bw/zebra" or "bw/panda" branches, Pasky can do only "cogito", and I can do master branch and make versioned tags. And anybody can do tmp/blah branches. This assumes all the users are in a single group that can write into $GIT_DIR/ and underneath.

Previous: Carl BaldwinNext: Carl Baldwin
Message 2 of 8 in “[RFC] Using sticky directories to control access to branches.”
  1. Carl BaldwinNov 17, 2005
  2. Junio C HamanoNov 18, 2005
  3. Carl BaldwinNov 21, 2005
  4. Junio C HamanoNov 21, 2005
  5. Carl BaldwinDec 1, 2005
  6. Junio C HamanoDec 2, 2005
  7. Andreas EricssonDec 2, 2005
  8. Junio C HamanoDec 2, 2005

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.