From: Andy Parkins <andyparkins@gmail.com>
To: git@vger.kernel.org
Cc: Bill Lear <rael@zopyra.com>, "Shawn O. Pearce" <spearce@spearce.org>
Subject: Re: Git push failure with update hook success
Date: Thu, 8 Mar 2007 09:22:53 +0000 [thread overview]
Message-ID: <200703080922.54978.andyparkins@gmail.com> (raw)
In-Reply-To: <17902.62836.920473.810183@lisa.zopyra.com>
On Wednesday 2007 March 07 17:25, Bill Lear wrote:
> Ok, thank you for fixing this. I guess the call run_update_hook()
> should not in fact come after the write_ref_sha1() block, and just
> before the 'return 0' line, because you don't want to run the
> write_ref_sha1() at all if the update hook complains.
Yep. The problem is definitely real, it's a bodge to have to do the email
generation in the update hook. When I started writing a new update hook, I
wanted to put it in post-update but found I couldn't.
Here's my assumption for an email generator: you want every change of revision
to generate an email; you want only the revisions added to make that change
to appear on an email; you want every new revision to appear on /only/ one
email.
A lot of the magic for making emails with useful information comes from the
fact that the update hook is given three pieces of information:
- ref being changed
- current revision of ref
- potential new revision of ref
The first job of the update hook is to see if this update is allowed. The
sample update hook defaults to rejecting un-annotated tags - generally
un-annotated tags are ones that you wouldn't want to distribute to the whole
project. It also rejects updates to remote tracking branches - obviously a
remote shouldn't be allowed to update your local tracking branches - that's
done by your own git-fetch; not someone elses git-push (in fact a central
repository probably shouldn't have tracking branches at all). This is the
bit that in an ideal world stay in the pre-update hook.
The second job (which is the one that really should go into post-update but
can't) is to build a useful email. The ref parameter tells us what sort of
ref we're updating; branch updates (i.e. refs/heads/*) and annotated tags
(i.e. refs/tags/*) updates are the most interesting.
So; you want to send an email summarising the changes that are being added to
the repository. You don't want to send the entire log for every change to
the branch in question since the beginning of time, because that would just
make ever increasing emails. Therefore you need the old revision. e.g.
* -- * --- O (oldrev)
\
N -- N -- N (newrev)
In this case, the new revisions are found with "git-rev-list $oldrev..
$newrev". Easy.
More difficult is when you want to be able to cope when the ref update
was --forced. e.g.
* -- * -- B -- O -- O -- O (oldrev)
\
N -- N -- N (newrev)
In this example, the ref update was not a fast forward, newrev points at the
tip of a branch which does not contain oldrev. Oh dear, "git-rev-list
$oldrev..$newrev" wouldn't return just the "N" revisions. To get around
this, the hook makes the assumption that emails for oldrev will already have
been issued (otherwise how did oldrev get into the repository :-)) and finds
the base revision of the old and new, B. Then the new commits are given
by "git-rev-list $baserev..$newrev".
The final tricky thing to get around is the killer for why this email
generation has to be done in the pre-update hook. Merges.
* -- O (master) -- A -- A -- A -- M
\ /
B --- B ---- B --- B --- B (maint)
Let's imagine that the master branch is what is being pushed, so it is about
to be updated from O to M. Sometime earlier, the "B" branch referenced by
maint has received updates as normal.
The new revisions that need an email are all of the "A" nodes and the "M"
node. We can't simply use "git rev-list O..M" as we have before because that
would include all of the "B" branch. We've already had emails for those
revisions so we'd simply be making noise. The solution then is to cheat a
little and say "all the revisions from O to M, but not any that reachable by
refs already in the repository". In git-speak:
git-rev-list $oldrev..$newrev --not --all
Or, close to how it's written in the update-hook
git-rev-list $newrev --not $oldrev --all
The "--all" means all of "refs/", and the revisions reachable by them. Now
here's the killer. If we did that in the post-update hook (even if all the
other information were available), this wouldn't work because the master ref
would have been updated and would already point at "M". In that
case "--not --all" would include the new revisions.
Without adding some nasty switches to git-rev-list
(like --all-except-this-branch), I can't see how the post-update hook could
ever send emails with the necessary amount of detail.
Andy
--
Dr Andy Parkins, M Eng (hons), MIET
andyparkins@gmail.com
next prev parent reply other threads:[~2007-03-08 9:23 UTC|newest]
Thread overview: 12+ messages / expand[flat|nested] mbox.gz Atom feed top
2007-03-07 16:29 Git push failure with update hook success Bill Lear
2007-03-07 16:46 ` Bill Lear
2007-03-07 17:09 ` Shawn O. Pearce
2007-03-07 17:25 ` Bill Lear
2007-03-07 17:38 ` Shawn O. Pearce
2007-03-07 23:09 ` Shawn O. Pearce
2007-03-07 23:15 ` Bill Lear
2007-03-08 9:22 ` Andy Parkins [this message]
2007-03-08 9:28 ` Shawn O. Pearce
2007-03-08 9:54 ` Junio C Hamano
2007-03-08 10:04 ` Andy Parkins
2007-03-08 10:06 ` Shawn O. Pearce
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=200703080922.54978.andyparkins@gmail.com \
--to=andyparkins@gmail.com \
--cc=git@vger.kernel.org \
--cc=rael@zopyra.com \
--cc=spearce@spearce.org \
/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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).