{"thread":{"id":"45640","subject":"Unexpected working directory in post-receive hook in non-bare repository","startedAt":"2017-04-09T13:01:36Z","lastAt":"2017-04-29T15:50:08Z","messageCount":4,"participants":["Simon Ruderich","Ævar Arnfjörð Bjarmason"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"316436","messageId":"20170409130126.uqmjop25jidhblhd@ruderich.org","threadId":"45640","inReplyTo":null,"subject":"Unexpected working directory in post-receive hook in non-bare repository","fromName":"Simon Ruderich","fromEmail":"simon@ruderich.org","sentAt":"2017-04-09T13:01:26Z","receivedAt":"2017-04-09T13:01:36Z","isPatch":false,"sender":{"key":"simon@ruderich.org","avatar":"https://avatars.githubusercontent.com/u/390994?v=4"},"body":"Hello,\n\nThe following snippet reproduces the issue for me (note the\nremote: line in its output):\n\n    git --version\n\n    rm -rf a b\n\n    git init a\n    cd a\n    echo first >data\n    git add data\n    git commit -m initial\n    cat >>.git/hooks/post-receive <<EOF\n    #!/bin/sh\n    pwd\n    EOF\n    chmod +x .git/hooks/post-receive\n    cd ..\n\n    git clone a b\n    cd b\n    echo second >>data\n    git add data\n    git commit -m test\n    git push origin master:not-master\n\nAccording to man githooks \"Before Git invokes a hook, it changes\nits working directory to either the root of the working tree in a\nnon-bare repository, [...]\". In this case \"a\" is non-bare and I\nexpected the command to be run in the working tree; but instead\nit's run inside .git. (This caused some confusion in my case\nbecause I ran \"git merge\" in the hook which put files in the .git\ndirectory and I didn't notice it at first. I know running merge\nin receive-hooks is \"bad practice\" but it works fine in my\nsetup.)\n\nThe same happens for all hooks executed by git-receive-pack:\npre-receive, update, post-receive, post-update.\n\nIs this a documentation issue or unexpected behavior?\n\nRegards\nSimon\n-- \n+ privacy is necessary\n+ using gnupg http://gnupg.org\n+ public key id: 0x92FEFDB7E44C32F9\n"},{"id":"316476","messageId":"CACBZZX4uBL99y=ZaKZ7dqyP9Ne-cx=kYkh8p51p3VYOr3PQGSw@mail.gmail.com","threadId":"45640","inReplyTo":"20170409130126.uqmjop25jidhblhd@ruderich.org","subject":"Re: Unexpected working directory in post-receive hook in non-bare repository","fromName":"Ævar Arnfjörð Bjarmason","fromEmail":"avarab@gmail.com","sentAt":"2017-04-10T11:13:15Z","receivedAt":"2017-04-10T11:13:41Z","isPatch":false,"sender":{"key":"avarab@gmail.com","avatar":"https://avatars.githubusercontent.com/u/45301?v=4"},"body":"On Sun, Apr 9, 2017 at 3:01 PM, Simon Ruderich <simon@ruderich.org> wrote:\n> The following snippet reproduces the issue for me (note the\n> remote: line in its output):\n>\n>     git --version\n>\n>     rm -rf a b\n>\n>     git init a\n>     cd a\n>     echo first >data\n>     git add data\n>     git commit -m initial\n>     cat >>.git/hooks/post-receive <<EOF\n>     #!/bin/sh\n>     pwd\n>     EOF\n>     chmod +x .git/hooks/post-receive\n>     cd ..\n>\n>     git clone a b\n>     cd b\n>     echo second >>data\n>     git add data\n>     git commit -m test\n>     git push origin master:not-master\n>\n> According to man githooks \"Before Git invokes a hook, it changes\n> its working directory to either the root of the working tree in a\n> non-bare repository, [...]\". In this case \"a\" is non-bare and I\n> expected the command to be run in the working tree; but instead\n> it's run inside .git. (This caused some confusion in my case\n> because I ran \"git merge\" in the hook which put files in the .git\n> directory and I didn't notice it at first. I know running merge\n> in receive-hooks is \"bad practice\" but it works fine in my\n> setup.)\n>\n> The same happens for all hooks executed by git-receive-pack:\n> pre-receive, update, post-receive, post-update.\n>\n> Is this a documentation issue or unexpected behavior?\n\nIt's a documentation issue I think. I added this change to the\ngithooks manpage last year in 49fa52fd00, but didn't think about the\ncase of pushing into non-bare repositories. The behavior itself hasn't\nchanged in a long time.\n\nI wonder how to phrase this so that it's unambiguous & simply states a\ngeneral rule. I.e. instead of:\n\n\"\"\"\"\nBefore Git invokes a hook, it changes its working directory to either\nthe root of the working tree in a non-bare repository, or to the\n$GIT_DIR in a bare repository.\n\"\"\"\n\nCan we say as we do now that:\n\n* All hooks regardless of type in bare repos execute in the bare repo\n* If you have a working tree hooks use that\n\nBut add:\n\n* Working trees are ignored by any hooks invoked on your behalf during a push.\n\nSome ad-hoc testing reveals that this rule also goes for the\npush-to-checkout hook. Should it? Wouldn't it be more useful if it\nbroke the pattern, since it's dealing with the working tree on the\nother side? Junio?\n"},{"id":"318235","messageId":"20170429122829.lz56r7exh3ecynxb@ruderich.org","threadId":"45640","inReplyTo":"CACBZZX4uBL99y=ZaKZ7dqyP9Ne-cx=kYkh8p51p3VYOr3PQGSw@mail.gmail.com","subject":"[PATCH] githooks.txt: clarify push hooks are always executed in $GIT_DIR","fromName":"Simon Ruderich","fromEmail":"simon@ruderich.org","sentAt":"2017-04-29T12:28:29Z","receivedAt":"2017-04-29T12:28:40Z","isPatch":true,"sender":{"key":"simon@ruderich.org","avatar":"https://avatars.githubusercontent.com/u/390994?v=4"},"body":"Listing the specific hooks might feel verbose but without it the\nreader is left to wonder which hooks are triggered during the\npush. Something which is not immediately obvious when only trying\nto find out where the hook is executed.\n\nSigned-off-by: Simon Ruderich <simon@ruderich.org>\n---\n Documentation/githooks.txt | 6 ++++--\n 1 file changed, 4 insertions(+), 2 deletions(-)\n\nOn Mon, Apr 10, 2017 at 01:13:15PM +0200, Ævar Arnfjörð Bjarmason wrote:\n> [snip]\n>\n> Can we say as we do now that:\n>\n> * All hooks regardless of type in bare repos execute in the bare repo\n> * If you have a working tree hooks use that\n>\n> But add:\n>\n> * Working trees are ignored by any hooks invoked on your behalf during a push.\n\nHello,\n\nMaybe like this? I reordered the cases as it felt more natural\nthat the general case is first and followed by the one with the\nexception.\n\n> Some ad-hoc testing reveals that this rule also goes for the\n> push-to-checkout hook. Should it? Wouldn't it be more useful if it\n> broke the pattern, since it's dealing with the working tree on the\n> other side? Junio?\n\nI added push-to-checkout to the patch. Changing the behavior will\nbreak backwards compatibility so I think that's a no-go.\n\nRegards\nSimon\n\ndiff --git a/Documentation/githooks.txt b/Documentation/githooks.txt\nindex 32343ae29..706091a56 100644\n--- a/Documentation/githooks.txt\n+++ b/Documentation/githooks.txt\n@@ -22,8 +22,10 @@ changed via the `core.hooksPath` configuration variable (see\n linkgit:git-config[1]).\n \n Before Git invokes a hook, it changes its working directory to either\n-the root of the working tree in a non-bare repository, or to the\n-$GIT_DIR in a bare repository.\n+$GIT_DIR in a bare repository or the root of the working tree in a non-bare\n+repository. An exception are hooks triggered during a push ('pre-receive',\n+'update', 'post-receive', 'post-update', 'push-to-checkout') which are always\n+executed in $GIT_DIR.\n \n Hooks can get their arguments via the environment, command-line\n arguments, and stdin. See the documentation for each hook below for\n-- \n2.11.0\n\n-- \n+ privacy is necessary\n+ using gnupg http://gnupg.org\n+ public key id: 0x92FEFDB7E44C32F9\n"},{"id":"318241","messageId":"CACBZZX5EdWHWjnYG2YFj7P4Ec+qm80DurUmP4JAR+sSaBjWWtA@mail.gmail.com","threadId":"45640","inReplyTo":"20170429122829.lz56r7exh3ecynxb@ruderich.org","subject":"Re: [PATCH] githooks.txt: clarify push hooks are always executed in $GIT_DIR","fromName":"Ævar Arnfjörð Bjarmason","fromEmail":"avarab@gmail.com","sentAt":"2017-04-29T15:45:27Z","receivedAt":"2017-04-29T15:50:08Z","isPatch":true,"sender":{"key":"avarab@gmail.com","avatar":"https://avatars.githubusercontent.com/u/45301?v=4"},"body":"On Sat, Apr 29, 2017 at 2:28 PM, Simon Ruderich <simon@ruderich.org> wrote:\n> Listing the specific hooks might feel verbose but without it the\n> reader is left to wonder which hooks are triggered during the\n> push. Something which is not immediately obvious when only trying\n> to find out where the hook is executed.\n>\n> Signed-off-by: Simon Ruderich <simon@ruderich.org>\n> ---\n>  Documentation/githooks.txt | 6 ++++--\n>  1 file changed, 4 insertions(+), 2 deletions(-)\n>\n> On Mon, Apr 10, 2017 at 01:13:15PM +0200, Ęvar Arnfjörš Bjarmason wrote:\n>> [snip]\n>>\n>> Can we say as we do now that:\n>>\n>> * All hooks regardless of type in bare repos execute in the bare repo\n>> * If you have a working tree hooks use that\n>>\n>> But add:\n>>\n>> * Working trees are ignored by any hooks invoked on your behalf during a push.\n>\n> Hello,\n>\n> Maybe like this? I reordered the cases as it felt more natural\n> that the general case is first and followed by the one with the\n> exception.\n>\n>> Some ad-hoc testing reveals that this rule also goes for the\n>> push-to-checkout hook. Should it? Wouldn't it be more useful if it\n>> broke the pattern, since it's dealing with the working tree on the\n>> other side? Junio?\n>\n> I added push-to-checkout to the patch. Changing the behavior will\n> break backwards compatibility so I think that's a no-go.\n>\n> Regards\n> Simon\n>\n> diff --git a/Documentation/githooks.txt b/Documentation/githooks.txt\n> index 32343ae29..706091a56 100644\n> --- a/Documentation/githooks.txt\n> +++ b/Documentation/githooks.txt\n> @@ -22,8 +22,10 @@ changed via the `core.hooksPath` configuration variable (see\n>  linkgit:git-config[1]).\n>\n>  Before Git invokes a hook, it changes its working directory to either\n> -the root of the working tree in a non-bare repository, or to the\n> -$GIT_DIR in a bare repository.\n> +$GIT_DIR in a bare repository or the root of the working tree in a non-bare\n> +repository. An exception are hooks triggered during a push ('pre-receive',\n> +'update', 'post-receive', 'post-update', 'push-to-checkout') which are always\n> +executed in $GIT_DIR.\n>\n>  Hooks can get their arguments via the environment, command-line\n>  arguments, and stdin. See the documentation for each hook below for\n\nThis looks good to me. Thanks for working on this.\n"}]}