Reputation: 490
When a Git pre-push
hooks script is working, how to get the full git push
command content?
Example, when I run: git push origin master
, pre-push hooks executed.
I want to get origin
& master
in this hook.
How can I get the list of arguments?
Upvotes: 9
Views: 4067
Reputation: 488103
Your hook script (assuming sh/bash) should include a loop of the form:
while read localname localhash remotename remotehash; do
... code here using $localname etc ...
done
All of the Git hooks are described in the githooks page. The pre-push
hook description begins with:
This hook is called by git push and can be used to prevent a push from taking place. The hook is called with two parameters which provide the name and location of the destination remote, if a named remote is not being used both values will be the same.
Information about what is to be pushed is provided on the hook’s standard input with lines of the form:
<local ref> SP <local sha1> SP <remote ref> SP <remote sha1> 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
although the full, 40-character SHA-1s would be supplied. ...
The first paragraph means that in a shell script, $1
and $2
are the name of the remote—e.g., origin
—and its URL, or the URL repeated twice if the user ran:
git push https://some.host.name/some/path ...
The second paragraph is important. A git push
command can push more than one branch. For instance, I can run:
git push origin feature-A feature-B
to push both feature-A
and feature-B
. You must read all input lines, one line at a time, to discover what is to be pushed. The current branch in the repository is not important: reading HEAD
will give you the wrong answer unless the user happens to be pushing the current branch. On the other hand, most users mostly just push the current branch. This will give you the illusion that your hook is 100% reliable, when it's actually only 92.37% reliable.1
As the documentation notes, the hook gets the full name of each reference. If you are pushing a branch, that full name starts with refs/heads/
, but you can push a tag, in which case the full name starts with refs/tags/
. To write a reliable hook, you must inspect the full name, rather than simply stripping off the first two components.2
1Like 38.61% of statistics, this one was made up on the spot. :-)
2There are a lot of bad sample hooks (not all of them pre-push hooks) out there that use:
branch=$(echo $ref | cut -d/ -f3)
If you are pushing tag v2.3
, this hook will think you are pushing a branch named v2.3
. If you are pushing a branch named bugfix/1234
, it will think you are pushing a branch named bugfix
! The cut
technique is just wrong, but a quick fix for the latter is to use -f3-
, which at least produces bugfix/1234
. It's better to verify the first components of the ref—i.e., do something like:
case $ref in
refs/heads/*) ... it's a branch ...;;
refs/tags/*) ... it's a tag ...;;
*) ... it's something else entirely, such as refs/notes/* ...;;
esac
Once you know the prefix, you can use ${ref#refs/heads/}
or ${ref#refs/tags/}
to strip off the known prefix and get the full but unqualified branch or tag name. If many cases, though, you can just work directly with the full reference name.
Upvotes: 7
Reputation: 142064
Those params are passed to the hook
In the hook you can get the branch name like this:
branch=$(git symbolic-ref HEAD | sed -e 's,.*/\(.*\),\1,')
If you wish to view those settings in your terminal as well and not as part of your script use those commands:
# get the name of the tracking branches
git branch -a -vv
# or:
git status -b --porcelain
# to get the name of the current branch:
git symbolic-ref -q HEAD
pre-push
hook?git push --no-verify
Upvotes: -1