threads / discuss / 60088

git pre-push hook not getting the lines from STDIN

Subject: git pre-push hook not getting the lines from STDIN

## tl;dr

3 messages between Aug 8, 2023 and Aug 9, 2023.

replies: 2people: 2as markdown or json

Wesley· Aug 8, 2023, 22:24 UTC · lore
Hello list,

I'm trying to figure out how I can check which branches are used in a git push action while using the pre-push hook. In the man page the following is mentioned:

----<

Information about what is to be pushed is provided on the hook’s standard input with lines of the form:

<local ref> SP <local object name> SP <remote ref> SP <remote object name> LF

For instance, if the command `git push origin master:foreign` were run the hook would receive a line like the following:

   refs/heads/master 67890 refs/heads/foreign 12345
----<

I cannot seem to reproduce this behavior with the push action. Only when pushing to delete a remote branch or pushing to a new branch gets created yields any success. I went as far back as git 2.9.0 (I can't build older versions of git), to no avail. The line in the man page seems to indicate git v1.8.2-rc0 was the first tag to have it (ec55559f).

Could someone verify that what I am seeing is correct behavior or that this is incorrect?

As stated, I experience issues on git v2.9.0, 2.40.1 (Debian) and also directly from source 2.42.0.rc0.26.g6ac35453d6.

Thanks, Wesley

----< a new branch

$ git push origin test:fofofo +.git/hooks/pre-push:5> remote=origin +.git/hooks/pre-push:6> url=git@gitlab.com:gitlabmeme/somerepo.git +.git/hooks/pre-push:8> success=128 +.git/hooks/pre-push:10> z40=0000000000000000000000000000000000000000 +.git/hooks/pre-push:11> IFS=' ' +.git/hooks/pre-push:13> read LOCAL_REF LOCAL_SHA REMOTE_REF REMOTE_SHA +.git/hooks/pre-push:15> echo refs/heads/test refs/heads/test +.git/hooks/pre-push:16> echo 24a3b84a02937df6040fecce2e0620e16c823b36 24a3b84a02937df6040fecce2e0620e16c823b36 +.git/hooks/pre-push:17> echo refs/heads/fofofo refs/heads/fofofo +.git/hooks/pre-push:18> echo 0000000000000000000000000000000000000000 0000000000000000000000000000000000000000 +.git/hooks/pre-push:21> [ refs/heads/test '=' 0000000000000000000000000000000000000000 ']' +.git/hooks/pre-push:23> [ refs/heads/test '=' '(delete)' ']' +.git/hooks/pre-push:30> exit 128

----< deletion of a branch on the remote

$ git push origin :development +.git/hooks/pre-push:5> remote=origin +.git/hooks/pre-push:6> url=git@gitlab.com:gitlabmeme/somerepo.git +.git/hooks/pre-push:8> success=128 +.git/hooks/pre-push:10> z40=0000000000000000000000000000000000000000 +.git/hooks/pre-push:11> IFS=' ' +.git/hooks/pre-push:13> read LOCAL_REF LOCAL_SHA REMOTE_REF REMOTE_SHA +.git/hooks/pre-push:15> echo '(delete)' (delete) +.git/hooks/pre-push:16> echo 0000000000000000000000000000000000000000 0000000000000000000000000000000000000000 +.git/hooks/pre-push:17> echo refs/heads/development refs/heads/development +.git/hooks/pre-push:18> echo 1762c08fd38c1137bbca27898df7c64ad846f877 1762c08fd38c1137bbca27898df7c64ad846f877 +.git/hooks/pre-push:21> [ '(delete)' '=' 0000000000000000000000000000000000000000 ']' +.git/hooks/pre-push:23> [ '(delete)' '=' '(delete)' ']' +.git/hooks/pre-push:23> exit 128

----<

If I push to an existing repo on my remote I see this: $ git push origin HEAD:development +.git/hooks/pre-push:5> remote=origin +.git/hooks/pre-push:6> url=git@gitlab.com:gitlabmeme/somerepo.git +.git/hooks/pre-push:8> success=128 +.git/hooks/pre-push:10> z40=0000000000000000000000000000000000000000 +.git/hooks/pre-push:11> IFS=' ' +.git/hooks/pre-push:13> read LOCAL_REF LOCAL_SHA REMOTE_REF REMOTE_SHA +.git/hooks/pre-push:15> echo

+.git/hooks/pre-push:16> echo
+.git/hooks/pre-push:17> echo
+.git/hooks/pre-push:18> echo

+.git/hooks/pre-push:21> [ '' '=' 0000000000000000000000000000000000000000 ']' +.git/hooks/pre-push:23> [ '' '=' '(delete)' ']' +.git/hooks/pre-push:28> exit 128

----< The pre-push script

#!/usr/bin/env zsh # set -x

remote="$1" url="$2"

success=128

z40=0000000000000000000000000000000000000000 IFS=' '

read LOCAL_REF LOCAL_SHA REMOTE_REF REMOTE_SHA

echo $LOCAL_REF echo $LOCAL_SHA echo $REMOTE_REF echo $REMOTE_SHA

# deletion of remote branch [ "$LOCAL_REF" = $z40 ] && exit $success # git 2.40 at least does not have $z40 as a delete [ "$LOCAL_REF" = '(delete)' ] && exit $success

exit $success
-- 
Wesley

Why not both?
Sean Allred· Aug 9, 2023, 11:00 UTC · re: Wesley · lore

Re: git pre-push hook not getting the lines from STDIN

Wesley <wesleys@opperschaap.net> writes:
> Hello list,
>
> I'm trying to figure out how I can check which branches are used in a
> git push action while using the pre-push hook.
Show 27 quoted lines
> ----< The pre-push script
>
> #!/usr/bin/env zsh
> #
> set -x
>
> remote="$1"
> url="$2"
>
> success=128
>
> z40=0000000000000000000000000000000000000000
> IFS=' '
>
> read LOCAL_REF LOCAL_SHA REMOTE_REF REMOTE_SHA
>
> echo $LOCAL_REF
> echo $LOCAL_SHA
> echo $REMOTE_REF
> echo $REMOTE_SHA
>
> # deletion of remote branch
> [ "$LOCAL_REF" = $z40 ] && exit $success
> # git 2.40 at least does not have $z40 as a delete
> [ "$LOCAL_REF" = '(delete)' ] && exit $success
>
> exit $success

Have you looked at simplifying this script to the bare minimum to identify the issue? I might suggest starting by just slurping stdin and writing that to a file:

    #!/bin/sh
    echo "$@" >pre-push.$$.args
    cat >>pre-push.$$.stdin
    exit 1

(The 'exit 1' here is to unconditionally prevent the push from actually going through during testing. Likely similar to your '128' value, since actual success of course should be exit code '0'.)

From here, you can test your pre-push hook by using that file as stdin:
    ./my-hook $(cat pre-push.$$.args) <pre-push.12345.stdin

I'm not familiar with the particulars of Zsh scripting, but I suspect there is a bug in your script. Zsh works with my script, too, so it doesn't appear to be a problem with Zsh itself.

-- Sean Allred

Wesley· Aug 9, 2023, 12:38 UTC · re: Sean Allred · lore

Re: git pre-push hook not getting the lines from STDIN

Hello Sean,
Show 8 quoted lines
> Have you looked at simplifying this script to the bare minimum to
> identify the issue? I might suggest starting by just slurping stdin and
> writing that to a file:
> 
>      #!/bin/sh
>      echo "$@" >pre-push.$$.args
>      cat >>pre-push.$$.stdin
>      exit 1
 >
> I'm not familiar with the particulars of Zsh scripting, but I suspect
> there is a bug in your script. Zsh works with my script, too, so it
> doesn't appear to be a problem with Zsh itself.

This is the bare miminum. You can also take the example script from the git sources which does it in bash[^1] and uses while read syntax. It produces the same output, with the exception that you don't see the empty echo statements because it cannot read the input from STDIN and exits immediately.

It seems it works intermittently.
In my zsh repo for example with the following remotes:

origin git@gitlab.com:waterkip/zsh (fetch) origin git@gitlab.com:waterkip/zsh (push) upstream git://git.code.sf.net/p/zsh/code (fetch) upstream git://git.code.sf.net/p/zsh/code (push)

Locally my patchlevel-in_version branch is at commit b7f280ab5. If I `git pull --rebase upstream master` and than push it (`git push origin HEAD) with hook configured it doesn't show any of the things I expect in LOCAL_REF etc. This happens with my version of the script and the version provided by git (in .git/hooks/pre-push.sample).

Cheers, Wesley

[^1]: https://github.com/git/git/blob/87c86dd14abe8db7d00b0df5661ef8cf147a72a3/templates/hooks--pre-push.sample

-- 
Wesley

Why not both?

← back to recent threads