All of lore.kernel.org
 help / color / mirror / Atom feed
From: Junio C Hamano <junkio@cox.net>
To: "Sam Watkins" <swatkins@fastmail.fm>
Cc: git@vger.kernel.org
Subject: Re: git-push hook to update remote working copy safely
Date: Fri, 23 Feb 2007 03:00:09 -0800	[thread overview]
Message-ID: <7v649t5ebq.fsf@assigned-by-dhcp.cox.net> (raw)
In-Reply-To: <1172220709.10221.1176113191@webmail.messagingengine.com> (Sam Watkins's message of "Fri, 23 Feb 2007 19:51:49 +1100")

"Sam Watkins" <swatkins@fastmail.fm> writes:

> I'm looking for a command that will update the remote working copy after
> a "git push", without damaging any changes that may have been made to
> the working copy.

Define "without damaging".  If there are changes to paths that
are modified by the pushed commit since the current HEAD, what
should your "update the remote working copy" procedure would
do?

 * Abort the push and refuse to update branch head?

 * Run file-level merge and leave the conflicted results on the
   working tree, in the $GIT_DIR/index and leave the pushed
   commit object name in $GIT_DIR/MERGE_HEAD?

I think the latter is just crazy, as you would then have to
think about cases where you already have $GIT_DIR/MERGE_HEAD
when you attempt to push.

Why in the first place does checking out need to perform a
possibly conflicting update?  Unless it is _also_ modified by
something other than push (i.e. some human user modifies it in
the editor, iow active development happening in the repository),
you can assume that when a push tries to update the working
tree, the working tree is clean (i.e. the index matches HEAD and
the working tree files match the index).  And in such a case,
you can set receive.denyNonFastForwards, and push will not even
call the update hook unless it is fast-forward.  And checking
out a fast-forward in a clean working tree should always succeed
without conflicts.  So I am puzzled what you are really trying
to achieve here.

The only thing you need to protect against is simultaneous push,
and I think that can be solved by holding a lock file while your
update hook runs a checkout.

So it might be just the matter of something like this totally
untested script:

	#!/bin/sh
        # Assumes that the repository has its own working tree and
	# $GIT_DIR is "/path/to/repository/.git".  update hook
        # is always called with `pwd` the same as $GIT_DIR.

        GIT_DIR=`pwd`

	cd .. ;# to the top of working tree
        BRANCH="$1"
        OLDREV="$2"
        NEWREV="$3"

	# Do not bother with non branch push.
        case "$BRANCH" in refs/heads/*) ;; *) exit 0 ;; esac

	# Make sure it is a fast-forward, unless totally new.
	if test "0000000000000000000000000000000000000000" = "$OLDREV"
	then
		MB=$(git merge-base "$OLDREV" "$NEWREV") &&
	        test "$OLDREV" = "$NEWREV" || exit 1
	fi

	# Pushing into a non-checked-out branch -- no need to
        # do anything.
        HEAD_BRANCH=`git symbolic-ref HEAD`
        test "z$HEAD_BRANCH" = "z$BRANCH" || exit 0

	# Could we have a lock please?
	lock="$GIT_DIR/push-update.lock"
        lockfile "$lock"
        trap 'rm -f "$lock"' 0

        # Make sure the index, working tree and HEAD all match.
	HEAD=`git rev-parse --verify HEAD` &&
        test "z$HEAD" = "z$OLDREV" &&
        git update-index --refresh &&
        test -z "`git diff-files --name-only`" &&
        test -z "`git diff-index --cached --name-only $HEAD`" ||
	exit 1

	# Update the working tree -- we do not do git-checkout
        # because updating the ref in 'update' hook is a big
        # No-no.  It would screw up the lockless update in
        # receive-pack that happens after update hook returns.
        git read-tree -m -u "$OLDREV" "$NEWREV"

  reply	other threads:[~2007-02-23 11:00 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2007-02-23  8:51 git-push hook to update remote working copy safely Sam Watkins
2007-02-23 11:00 ` Junio C Hamano [this message]
2007-02-23 16:35   ` Sam Watkins
2007-02-23 16:40     ` Johannes Schindelin
2007-02-23 17:04       ` Sam Watkins
2007-02-23 18:13         ` Johannes Schindelin
2007-02-23 18:32       ` Junio C Hamano

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=7v649t5ebq.fsf@assigned-by-dhcp.cox.net \
    --to=junkio@cox.net \
    --cc=git@vger.kernel.org \
    --cc=swatkins@fastmail.fm \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.