On Wed, 4 Sep 2013 04:31:26 -0700 (PDT)
Ling <oylf1...@gmail.com> wrote:

> Thanks Thomas, And yes I had read this and also I tried with git log
> but this won't works since git log is only created after the push,
> which means it won't compare the new push comment, it only compare
> the previous pushed comment to trigger the hooks. since what I need
> is trigger the hooks when new push comment not meet my prerequisites.

Are you calling `git log` on a ref name (a branch name, if this sounds
simpler) or on the SHA-1 name of the prospective new tip commit of the
ref of interest?  You have to do the latter if you're writing a
pre-receive hook because while it works the refs are not yet updated,
and exiting the hook script with a non-zero exit state will leave the
refs in a pre-push state.

For each ref updated during the push session, Git tells your
pre-receive hook the SHA-1 names of both the old commit at which that
ref pointed, and the new commit at which that ref will point if your
hook will exit successfully.  You're able to use these names to inspect
the line of history sent to update each ref.

Note that a push operation might be a bit more complex you think it is:
* Several refs might be updated by a single push.
* More than one commit might be sent to update each ref, that is, it's
  quite common to push a line or even a graph of commits (if there were
  true merges during the development) to update a ref.

This means that if you're going to inspect the log messages of the
received commits, this should be done over *a range of commits* for each
ref to be updated -- starting with the prospective new tip commit of
that ref and ending at the topographically nearest commit which is
shared between the old history of that ref and its prospective new tip

This hints us that it's better to go lower level and use plumbing tools
to manually traverse the relevant bits of history.  I'd go with
`git merge-base`, `git rev-list` and `git cat-file` -- a sketch of how
to do this follows.

For each ref to be updated:

1) Call `git merge-base $oldname $newname` -- this will give you the
   name of a commit which is common between the old and the new state of
   the ref.  In the simplest case -- a fast-forward of the ref this will
   be the old tip commit of that ref ($oldname here), in a more complex
   case, where a user did a forced push which replaced some (or all) of
   the ref's history, this will be the nearest (to the prospective new
   tip) commit which won't be replaced, and this means its log message
   has already been checked at some point back in time.

2) Having obtained this base commit, call

   git rev-list $newname ^$basename

   to get the list of the SHA-1 names of all commits reachable from the
   new prospective ref's tip but excluding those also reachable from the
   base commit.

3) Iterate over the generated list, calling

   git cat-file -p $sha1name

   This will print a pretty-printed version of the commit object to its
   standard output.  Commit objects have standard format: the block of
   headers (each of the format <name> SP <value>), a blank line, and
   then the commit message, which is what's of interest for you.

   Note that a commit object might include the "encoding" header naming
   the encoding used to encode the actual message.  You might hence want
   to filter the commit message through

   iconv -f $encoding -t utf-8

   if the "encoding" header is detected.

You received this message because you are subscribed to the Google Groups "Git 
for human beings" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to git-users+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.

Reply via email to