{"thread":{"id":"1378","subject":"[PATCH] Added hook in git-receive-pack","startedAt":"2005-07-31T19:17:43Z","lastAt":"2005-08-13T20:39:41Z","messageCount":15,"participants":["Josef Weidendorfer","Linus Torvalds","Junio C Hamano","Johannes Schindelin"],"isPatch":true,"patchVersion":1,"patchTotal":null},"messages":[{"id":"6671","messageId":"200507312117.43957.Josef.Weidendorfer@gmx.de","threadId":"1378","inReplyTo":null,"subject":"[PATCH] Added hook in git-receive-pack","fromName":"Josef Weidendorfer","fromEmail":"josef.weidendorfer@gmx.de","sentAt":"2005-07-31T19:17:43Z","receivedAt":"2005-07-31T19:17:43Z","isPatch":true,"sender":{"key":"josef.weidendorfer@gmx.de","avatar":null},"body":"Added hook in git-receive-pack\n\nAfter successful update of a ref,\n\n $GIT_DIR/hooks/update refname old-sha1 new-sha2\n\nis called if present. This allows e.g sending of a mail\nwith pushed commits on the remote repository.\nDocumentation update with example hook included.\n\nSigned-off-by: Josef Weidendorfer <Josef.Weidendorfer@gmx.de>\n------------------------------------------------\n\ndiff --git a/Documentation/git-receive-pack.txt b/Documentation/git-receive-pack.txt\n--- a/Documentation/git-receive-pack.txt\n+++ b/Documentation/git-receive-pack.txt\n@@ -20,10 +20,25 @@ This command is usually not invoked dire\n The UI for the protocol is on the 'git-send-pack' side, and the\n program pair is meant to be used to push updates to remote\n repository.  For pull operations, see 'git-fetch-pack' and\n 'git-clone-pack'.\n\n+The command allows for creation and fast forwarding of sha1 refs\n+(heads/tags) on the local end. After each successful update, the\n+following external hook script is called if it is present:\n+\n+       $GIT_DIR/hooks/update refname sha1-old sha1-new\n+\n+It is assured that sha1-old is an ancestor of sha1-new (otherwise,\n+the update would have not been allowed). refname is relative to\n+$GIT_DIR; e.g. for the master head this is \"refs/heads/master\".\n+Using this hook, it is easy to generate mails on updates to\n+the local repository. This example script sends a mail with\n+the commits pushed to the repository:\n+\n+       #!/bin/sh\n+       git-rev-list --pretty \"$3\" \"^$2\" |\n+        mail -r $USER -s \"New commits on $1\" commit-list@mydomain\n\n OPTIONS\n -------\n <directory>::\n        The repository to sync into.\ndiff --git a/receive-pack.c b/receive-pack.c\n--- a/receive-pack.c\n+++ b/receive-pack.c\n@@ -53,10 +53,53 @@ static int verify_old_ref(const char *na\n        if (memcmp(buffer, hex_contents, 40))\n                return -1;\n        return 0;\n }\n\n+static const char *update_hook = \"hooks/update\";\n+\n+static void updatehook(const char *name, unsigned char *old_sha1, unsigned char *new_sha1)\n+{\n+        if (access(update_hook, X_OK) < 0) return;\n+       fprintf(stderr, \"executing update hook for %s\\n\", name);\n+\n+       pid_t pid = fork();\n+\n+       if (pid < 0)\n+               die(\"hook fork failed\");\n+       if (!pid) {\n+               execlp(update_hook, update_hook, name, old_sha1, new_sha1, NULL);\n+               die(\"hook execute failed\");\n+       }\n+\n+       for (;;) {\n+               int status, code;\n+               int retval = waitpid(pid, &status, 0);\n+\n+               if (retval < 0) {\n+                       if (errno == EINTR)\n+                               continue;\n+                       die(\"waitpid failed (%s)\", strerror(retval));\n+               }\n+               if (retval != pid)\n+                       die(\"waitpid is confused\");\n+               if (WIFSIGNALED(status)) {\n+                   fprintf(stderr, \"%s died of signal %d\",\n+                           update_hook, WTERMSIG(status));\n+                   return;\n+               }\n+               if (!WIFEXITED(status))\n+                       die(\"%s died out of really strange complications\",\n+                           update_hook);\n+               code = WEXITSTATUS(status);\n+               if (code)\n+                   fprintf(stderr, \"%s exited with error code %d\",\n+                           update_hook, code);\n+               return;\n+       }\n+}\n+\n static void update(const char *name, unsigned char *old_sha1, unsigned char *new_sha1)\n {\n        char new_hex[60], *old_hex, *lock_name;\n        int newfd, namelen, written;\n\n@@ -93,10 +136,12 @@ static void update(const char *name, uns\n        if (rename(lock_name, name) < 0) {\n                unlink(lock_name);\n                die(\"unable to replace %s\", name);\n        }\n        fprintf(stderr, \"%s: %s -> %s\\n\", name, old_hex, new_hex);\n+\n+       updatehook(name, old_hex, new_hex);\n }\n\n\n /*\n  * This gets called after(if) we've successfully\n"},{"id":"6676","messageId":"Pine.LNX.4.58.0507311305170.29650@g5.osdl.org","threadId":"1378","inReplyTo":"200507312117.43957.Josef.Weidendorfer@gmx.de","subject":"Re: [PATCH] Added hook in git-receive-pack","fromName":"Linus Torvalds","fromEmail":"torvalds@osdl.org","sentAt":"2005-07-31T20:11:58Z","receivedAt":"2005-07-31T20:11:58Z","isPatch":true,"sender":{"key":"torvalds@linux-foundation.org","avatar":"https://avatars.githubusercontent.com/u/1024025?v=4"},"body":"\n\nOn Sun, 31 Jul 2005, Josef Weidendorfer wrote:\n>\n> Added hook in git-receive-pack\n> \n> After successful update of a ref,\n> \n>  $GIT_DIR/hooks/update refname old-sha1 new-sha2\n> \n> is called if present. This allows e.g sending of a mail\n> with pushed commits on the remote repository.\n> Documentation update with example hook included.\n\nThis looks sane. However, I also get the strong feeling that\ngit-update-server-info should be run as part of a hook and not be built \ninto receive-pack..\n\nPersonally, I simply don't want to update any dumb server info stuff for \nmy own local repositories - it's not like I'm actually serving those out \nanyway.\n\n\t\tLinus\n"},{"id":"6677","messageId":"7v3bpuenpi.fsf@assigned-by-dhcp.cox.net","threadId":"1378","inReplyTo":"200507312117.43957.Josef.Weidendorfer@gmx.de","subject":"Re: [PATCH] Added hook in git-receive-pack","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2005-07-31T20:15:53Z","receivedAt":"2005-07-31T20:15:53Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Josef Weidendorfer <Josef.Weidendorfer@gmx.de> writes:\n\n> +It is assured that sha1-old is an ancestor of sha1-new (otherwise,\n> +the update would have not been allowed). refname is relative to\n> +$GIT_DIR; e.g. for the master head this is \"refs/heads/master\".\n\nI think this description is inaccurate; the send-pack can be run\nwith the --force flag and it is my understanding that receiver\nwould happily rewind the branch.  One possibility, if we wanted\nto enforce it on the receiver end, would be to add another hook\nthat is called before the rename happens and tell the\nreceive-pack to refuse that update, but that should be done with\na separate patch, I suppose.\n\n> +Using this hook, it is easy to generate mails on updates to\n> +the local repository. This example script sends a mail with\n> +the commits pushed to the repository:\n> +\n> +       #!/bin/sh\n> +       git-rev-list --pretty \"$3\" \"^$2\" |\n> +        mail -r $USER -s \"New commits on $1\" commit-list@mydomain\n\nWhat is the environment the hook runs in?  For example, who\ndefines $USER used here?\n\nWe might want to describe the environment a bit more tightly\nthan the current patch does.  This includes not just the\nenvironment variables, but $cwd and the set of open file\ndescriptors among other things.\n\nI am not saying this from the security standpoint (the fact that\nyou can invoke receive-pack and that you can write into the\nupdate hooks means you already have control over that\nrepository), but to help hook writers to avoid making mistakes.\nFor example, I offhand cannot tell what happens if the hook\ntries to read from its standard input.  Also what happens if the\nhook does not return but sleeps forever in a loop?  Do we want\nto somehow time it out?  I think \"It is hooks' responsibility to\ntime itself out\" is an acceptable answer here, but if that is\nthe case it had better be documented.\n\n> +static void updatehook(const char *name, unsigned char *old_sha1, unsigned char *new_sha1)\n> +{\n> +        if (access(update_hook, X_OK) < 0) return;\n> +       fprintf(stderr, \"executing update hook for %s\\n\", name);\n> +...\n> +}\n\nI think I've seen this \"fork -- exec -- for loop with waitpid\"\npattern repeated number of times in the code.  Would it be\nfeasible to make them into a single library-ish function and\ncall it from here and other existing places?\n\nAnother thing you may want to consider is to do this hook\nprocessing before and/or after processing all the refs.  A hook\nmight want to know what the entire set of refs are that are\nbeing updated, and may not have enough information if it is\ninvoked once per ref.\n\nThanks for the patch; I agree with what the patch tries to\nachieve in general.\n\n-jc\n"},{"id":"6678","messageId":"7vr7ded8ax.fsf@assigned-by-dhcp.cox.net","threadId":"1378","inReplyTo":"Pine.LNX.4.58.0507311305170.29650@g5.osdl.org","subject":"Re: [PATCH] Added hook in git-receive-pack","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2005-07-31T20:33:58Z","receivedAt":"2005-07-31T20:33:58Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Linus Torvalds <torvalds@osdl.org> writes:\n\n> This looks sane. However, I also get the strong feeling that\n> git-update-server-info should be run as part of a hook and not be built \n> into receive-pack..\n\n> Personally, I simply don't want to update any dumb server info stuff for \n> my own local repositories - it's not like I'm actually serving those out \n> anyway.\n\nBut you are.  I can run this just fine:\n\n $ git clone http://www.kernel.org/pub/scm/linux/kernel/git/torvalds/git.git/ linus\n\nI agree in principle that you should be able to disable the call\nto update_server_info() from there, but on the other hand once\nwe start doing it, we need to explain people which repo is http\ncapable and which repo is not and why.\n\nI was actually thinking about a call to git-update-server-info\nat the end of git-repack-script.  Again, great minds think the\nopposite way sometimes ;-).\n"},{"id":"6680","messageId":"Pine.LNX.4.58.0507311549300.14342@g5.osdl.org","threadId":"1378","inReplyTo":"7vr7ded8ax.fsf@assigned-by-dhcp.cox.net","subject":"Re: [PATCH] Added hook in git-receive-pack","fromName":"Linus Torvalds","fromEmail":"torvalds@osdl.org","sentAt":"2005-07-31T22:50:21Z","receivedAt":"2005-07-31T22:50:21Z","isPatch":true,"sender":{"key":"torvalds@linux-foundation.org","avatar":"https://avatars.githubusercontent.com/u/1024025?v=4"},"body":"\n\nOn Sun, 31 Jul 2005, Junio C Hamano wrote:\n> \n> But you are.  I can run this just fine:\n\nNo I'm not. Try all the machines behind my firewall.\n\nkernel.org is just the place I put things to when I publish them. It \ndoesn't have any of my working directories on it.\n\n\t\t\tLinus\n"},{"id":"6681","messageId":"200508010117.41848.Josef.Weidendorfer@gmx.de","threadId":"1378","inReplyTo":"7v3bpuenpi.fsf@assigned-by-dhcp.cox.net","subject":"Re: [PATCH] Added hook in git-receive-pack","fromName":"Josef Weidendorfer","fromEmail":"josef.weidendorfer@gmx.de","sentAt":"2005-07-31T23:17:41Z","receivedAt":"2005-07-31T23:17:41Z","isPatch":true,"sender":{"key":"josef.weidendorfer@gmx.de","avatar":null},"body":"On Sunday 31 July 2005 22:15, Junio C Hamano wrote:\n> Josef Weidendorfer <Josef.Weidendorfer@gmx.de> writes:\n> > +It is assured that sha1-old is an ancestor of sha1-new (otherwise,\n> > +the update would have not been allowed). refname is relative to\n> > +$GIT_DIR; e.g. for the master head this is \"refs/heads/master\".\n>\n> I think this description is inaccurate;\n\nThanks for the constructive comments; that patch was only a draft, and \ntailored for my needs. I thought it would be better to provide a patch than \nrequesting for a feature.\n\nI am trying to convert a CVS project with a few developers to GIT; the idea is \nthat each developer has his public branch in *the* central repository, and \n(s)he is allowed to merge to master him/herself; when pushing new features \ninto the branches or merging to master, there should be send out a mail to a \nmailing list.\n\n> the send-pack can be run \n> with the --force flag and it is my understanding that receiver\n> would happily rewind the branch.\n\nI didn't know this...\n\n> One possibility, if we wanted \n> to enforce it on the receiver end,\n\nI actually thought that the ancestor relationship always is given; perhaps we \ndon't need to enforce this; but before sending out a mail, the hook script \nprobably would like to check if there is any ancestor relationship; this \nwould be a potential long lasting task, wouldn't it?\n\n> would be to add another hook \n> that is called before the rename happens and tell the\n> receive-pack to refuse that update, but that should be done with\n> a separate patch, I suppose.\n\nSorry, I do not understand this.\n\n> > +Using this hook, it is easy to generate mails on updates to\n> > +the local repository. This example script sends a mail with\n> > +the commits pushed to the repository:\n> > +\n> > +       #!/bin/sh\n> > +       git-rev-list --pretty \"$3\" \"^$2\" |\n> > +        mail -r $USER -s \"New commits on $1\" commit-list@mydomain\n>\n> What is the environment the hook runs in?  For example, who\n> defines $USER used here?\n\nGood question. I thought it is UNIX/POSIX behavior to set this environemt in \nshells (same as \"id -u -n\"). At least, ssh sets it to \"the user logging \nin\" (see man ssh).\nAnd I supposed \"git-receive-pack\" to be called in a users SSH environment.\nHmmm... could this be called via CGI script by a web server?\n\nYou are right: we should be careful here. Is there any other hook mechanism in \nGIT at the moment? Originally, I thought this should be a task for a \nporcelain, but this thing is buried too deep in GIT itself...\n\nAll the issues about documenting the environment of the hooks, time out \nbehavior and so on, are general issues for every kind of hook.\n\n> I am not saying this from the security standpoint (the fact that\n> you can invoke receive-pack and that you can write into the\n> update hooks means you already have control over that\n> repository), but to help hook writers to avoid making mistakes.\n> For example, I offhand cannot tell what happens if the hook\n> tries to read from its standard input.  Also what happens if the\n> hook does not return but sleeps forever in a loop?  Do we want\n> to somehow time it out?  I think \"It is hooks' responsibility to\n> time itself out\" is an acceptable answer here, but if that is \n> the case it had better be documented.\n\nI think that a time out is not needed here: as the hook is called synchronous, \ngit-receive-pack won't return without until the hook terminated. And that is \nvisible to the user, i.e. he would see that there is something wrong.\n\n> I think I've seen this \"fork -- exec -- for loop with waitpid\"\n> pattern repeated number of times in the code.\n\nThis is no coincidence ;-) I copied it from inside the same file.\nBut the behavior is another: If the hook goes wrong, I do not want for \ngit-receive-pack to die.\n\n> Would it be \n> feasible to make them into a single library-ish function and\n> call it from here and other existing places?\n\nProbably.\n\n> Another thing you may want to consider is to do this hook\n> processing before and/or after processing all the refs.  A hook\n> might want to know what the entire set of refs are that are\n> being updated, and may not have enough information if it is\n> invoked once per ref.\n\nDo you have a use case? At least, it would make things more complex.\n\nJosef\n"},{"id":"6682","messageId":"7viryqd0eo.fsf@assigned-by-dhcp.cox.net","threadId":"1378","inReplyTo":"Pine.LNX.4.58.0507311549300.14342@g5.osdl.org","subject":"Re: [PATCH] Added hook in git-receive-pack","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2005-07-31T23:24:31Z","receivedAt":"2005-07-31T23:24:31Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Linus Torvalds <torvalds@osdl.org> writes:\n\n> No I'm not. Try all the machines behind my firewall.\n\nAh, that's true.  Do you push into them?\n\nLet's yank out the update_server_info() call when Josef's patch\ncan handle a single hook call at the end of the run, in addition\nto one call per each ref getting updated.\n"},{"id":"6684","messageId":"Pine.LNX.4.58.0508010130490.8410@wgmdd8.biozentrum.uni-wuerzburg.de","threadId":"1378","inReplyTo":"7viryqd0eo.fsf@assigned-by-dhcp.cox.net","subject":"Re: [PATCH] Added hook in git-receive-pack","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2005-07-31T23:31:43Z","receivedAt":"2005-07-31T23:31:43Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi,\n\nOn Sun, 31 Jul 2005, Junio C Hamano wrote:\n\n> Let's yank out the update_server_info() call when Josef's patch\n> can handle a single hook call at the end of the run, in addition\n> to one call per each ref getting updated.\n\nHow about executing update_server_info() if no hook was found? That way,\nit can be turned off by an empty hook, but is enabled in standard\nsettings.\n\nCiao,\nDscho\n"},{"id":"6683","messageId":"Pine.LNX.4.58.0507311627280.14342@g5.osdl.org","threadId":"1378","inReplyTo":"7viryqd0eo.fsf@assigned-by-dhcp.cox.net","subject":"Re: [PATCH] Added hook in git-receive-pack","fromName":"Linus Torvalds","fromEmail":"torvalds@osdl.org","sentAt":"2005-07-31T23:33:53Z","receivedAt":"2005-07-31T23:33:53Z","isPatch":true,"sender":{"key":"torvalds@linux-foundation.org","avatar":"https://avatars.githubusercontent.com/u/1024025?v=4"},"body":"\n\nOn Sun, 31 Jul 2005, Junio C Hamano wrote:\n> Linus Torvalds <torvalds@osdl.org> writes:\n> \n> > No I'm not. Try all the machines behind my firewall.\n> \n> Ah, that's true.  Do you push into them?\n\nYup, I do. I have this thing that I don't do backups, but I end up having \nredundancy instead, so I keep archives on my own machines and inside the \nprivate osdl network, for example.\n\nAlso, I suspect that anybody who uses the \"CVS model\" with git - ie a\ncentral repository - is not likely to export that central repository any\nway: it's the crown jewels, after all. Open source may not have that\nmindset, but I'm thinking of how I was forced to use CVS at Transmeta, for\nexample:  the machine that had the CVS repo was certainly supposed to be\nvery private indeed.\n\nIn the \"central repo model\" you have another issue - you have potentially\nparallell pushes to different branches with no locking what-so-ever (and\nthat's definitely _supposed_ to work), and I have this suspicion that the \n\"update for dumb servers\" code isn't really safe in that setting anyway. I \nhaven't checked.\n\n\t\t\tLinus\n"},{"id":"6688","messageId":"7vhdeabjo7.fsf@assigned-by-dhcp.cox.net","threadId":"1378","inReplyTo":"Pine.LNX.4.58.0507311627280.14342@g5.osdl.org","subject":"Re: [PATCH] Added hook in git-receive-pack","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2005-08-01T00:11:20Z","receivedAt":"2005-08-01T00:11:20Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Linus Torvalds <torvalds@osdl.org> writes:\n\n> In the \"central repo model\" you have another issue - you have potentially\n> parallell pushes to different branches with no locking what-so-ever (and\n> that's definitely _supposed_ to work), and I have this suspicion that the \n> \"update for dumb servers\" code isn't really safe in that setting anyway. I \n> haven't checked.\n\nYou are absolutely right.  It should grab some sort of lock\nwhile it does its thing (would fcntl(F_GETLK) be acceptable to\nnetworked filesystem folks?).\n\nI have one question regarding the hooks.  We seem to prefer\navoiding system and roll our own.  Is there a particular reason,\nother than bypassing the need to quote parameters for shell?\n"},{"id":"6689","messageId":"Pine.LNX.4.58.0507311720220.14342@g5.osdl.org","threadId":"1378","inReplyTo":"7vhdeabjo7.fsf@assigned-by-dhcp.cox.net","subject":"Re: [PATCH] Added hook in git-receive-pack","fromName":"Linus Torvalds","fromEmail":"torvalds@osdl.org","sentAt":"2005-08-01T00:25:47Z","receivedAt":"2005-08-01T00:25:47Z","isPatch":true,"sender":{"key":"torvalds@linux-foundation.org","avatar":"https://avatars.githubusercontent.com/u/1024025?v=4"},"body":"\n\nOn Sun, 31 Jul 2005, Junio C Hamano wrote:\n> \n> You are absolutely right.  It should grab some sort of lock\n> while it does its thing (would fcntl(F_GETLK) be acceptable to\n> networked filesystem folks?).\n\nThere is no lock that works reliably except for the \"create a directory \nand rename it onto another directory\"\n\nPlease do it in the hook layer.\n\n> I have one question regarding the hooks.  We seem to prefer\n> avoiding system and roll our own.  Is there a particular reason,\n> other than bypassing the need to quote parameters for shell?\n\nHmm.. I suspect it's partly just because there is existing code that does\nthe fork()/exec() thing because it needs to do IO, and system() doesn't\nclose the right pipes after fork etc.\n\n\"system()\" really is very inflexible. It basically never works if you have \nany shared file descriptors.\n\n\t\tLinus\n"},{"id":"6700","messageId":"7vzms2xeei.fsf@assigned-by-dhcp.cox.net","threadId":"1378","inReplyTo":"200508010117.41848.Josef.Weidendorfer@gmx.de","subject":"Re: [PATCH] Added hook in git-receive-pack","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2005-08-01T08:14:13Z","receivedAt":"2005-08-01T08:14:13Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Josef, I've committed a version that has slightly different\nsemantics from what you originally posted.\n\nThe differences are:\n\n - Instead of being post-change hook, the script is run just\n   before each ref is updated.  The script can exit with\n   non-zero status to tell receive-pack not to update that ref\n   if it wants to.  This means that you should explicitly exit\n   with zero status if all you want to do in the hook is to send\n   a mail out.\n\n - The script is called once at the very end with a single\n   parameter \"\" (i.e. $refname == \"\"), to signal that\n   receive-pack is about to finish.  This is a good place to add\n   any \"final cleanup\" hook.\n\nThe latter change allowed me to remove the mandatory\nupdate_server_info call Linus did not like and make it\noptional.\n\n-jc\n"},{"id":"7209","messageId":"200508132031.27668.Josef.Weidendorfer@gmx.de","threadId":"1378","inReplyTo":"200507312117.43957.Josef.Weidendorfer@gmx.de","subject":"Re: [PATCH] Added hook in git-receive-pack","fromName":"Josef Weidendorfer","fromEmail":"josef.weidendorfer@gmx.de","sentAt":"2005-08-13T18:31:27Z","receivedAt":"2005-08-13T18:31:27Z","isPatch":true,"sender":{"key":"josef.weidendorfer@gmx.de","avatar":null},"body":"On Sunday 31 July 2005 21:17, Josef Weidendorfer wrote:\n> Added hook in git-receive-pack\n\nRegarding the update hook:\nIn this script, it would be nice to be able to distinguish rebasing/forced \nsetting of a head from a regular fast forwarding. In the first case, I do not \nwant to potentially send a list of all commits starting from project root, \nwhich currently can happen.\n\nA solution would be to call the hook simply with\n\tupdate refname new_sha1\nif this is not a fast forward.\n\nThe question is if there is a use case for the script to get the old_sha1 even \nin a rebase situation. So another option would be to call the script with\n\tupdate action refname old_sha1 new_sha1\nwith action being \"fastforward\" or \"forcedrebase\" or similar.\n\nOr is there already an easy way to detect the fast-forward situation in the \nscript?\n\nJosef\n"},{"id":"7210","messageId":"7voe81myc4.fsf@assigned-by-dhcp.cox.net","threadId":"1378","inReplyTo":"200508132031.27668.Josef.Weidendorfer@gmx.de","subject":"Re: [PATCH] Added hook in git-receive-pack","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2005-08-13T19:27:39Z","receivedAt":"2005-08-13T19:27:39Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Josef Weidendorfer <Josef.Weidendorfer@gmx.de> writes:\n\n> Or is there already an easy way to detect the fast-forward situation in the \n> script?\n\nSince you are given old and new, presumably you can do\nmerge-base in the hook to see what it yields?\n"},{"id":"7217","messageId":"200508132239.41445.Josef.Weidendorfer@gmx.de","threadId":"1378","inReplyTo":"7voe81myc4.fsf@assigned-by-dhcp.cox.net","subject":"Re: [PATCH] Added hook in git-receive-pack","fromName":"Josef Weidendorfer","fromEmail":"josef.weidendorfer@gmx.de","sentAt":"2005-08-13T20:39:41Z","receivedAt":"2005-08-13T20:39:41Z","isPatch":true,"sender":{"key":"josef.weidendorfer@gmx.de","avatar":null},"body":"On Saturday 13 August 2005 21:27, Junio C Hamano wrote:\n> Josef Weidendorfer <Josef.Weidendorfer@gmx.de> writes:\n> > Or is there already an easy way to detect the fast-forward situation in\n> > the script?\n>\n> Since you are given old and new, presumably you can do\n> merge-base in the hook to see what it yields?\n\nAh, yes, thanks.\nA proposed update for the example hook (one change actually is a fix):\n\nFixed/Extended example for update hook\n---\n\ndiff --git a/templates/hooks--update b/templates/hooks--update\n--- a/templates/hooks--update\n+++ b/templates/hooks--update\n@@ -1,6 +1,7 @@\n #!/bin/sh\n #\n # An example hook script to mail out commit update information.\n+# Called by git-receive-pack with arguments: refname sha1-old sha1-new\n #\n # To enable this hook:\n # (1) change the recipient e-mail address\n@@ -12,10 +13,15 @@ recipient=\"commit-list@mydomain.xz\"\n if expr \"$2\" : '0*$' >/dev/null\n then\n        echo \"Created a new ref, with the following commits:\"\n-       git-rev-list --pretty \"$2\"\n+       git-rev-list --pretty \"$3\"\n else\n-       echo \"New commits:\"\n-       git-rev-list --pretty \"$3\" \"^$2\"\n+       $base=$(git-merge-base \"$2\" \"$3\")\n+       if [ $base == \"$2\" ]; then\n+               echo \"New commits:\"\n+       else\n+               echo \"Rebased ref, commits from common ancestor:\"\n+       fi\n+       git-rev-list --pretty \"$3\" \"^$base\"\n fi |\n mail -s \"Changes to ref $1\" \"$recipient\"\n exit 0\n"}]}