Here's my current hook in a bare repo that lives in the company's server:
git push origin master
This hooks pushes to Assembla.
What i need is to push only one branch (master, ideally) when someone pushes changes to that branch on our server, and ignore pushes to other branches. Is it possible to select the branch from a bare repo and push only that branch to Assembla?

- 86,532
- 28
- 194
- 218

- 10,464
- 8
- 37
- 56
-
What do you mean? `git push origin master` will only push the `master` branch to the `origin` remote, which I assume is defined to be Assembla. Are you saying that you need to *trigger* the hook only when someone pushes to `master`, as opposed to `feature1`, or something like that? – Stefan Kendall Sep 08 '11 at 16:42
-
@Stefan Exactly that. I couldn't find the word, hehe. – Jorge Guberte Sep 08 '11 at 16:44
-
Duplicate http://stackoverflow.com/questions/6372334/git-commit-hooks-per-branch – insign Nov 13 '15 at 18:43
7 Answers
A post-receive hook gets its arguments from stdin, in the form:
<oldrev> <newrev> <refname>
Since these arguments are coming from stdin, not from a command line argument, you need to use read
instead of $1 $2 $3
.
The post-receive hook can receive multiple branches at once (for example if someone does a git push --all
), so we also need to wrap the read
in a while
loop.
A working snippet looks something like this:
#!/bin/bash
while read oldrev newrev refname
do
branch=$(git rev-parse --symbolic --abbrev-ref $refname)
if [ "master" = "$branch" ]; then
# Do something
fi
done

- 24,647
- 4
- 70
- 96

- 10,803
- 4
- 28
- 33
-
2
-
That's odd. Double equals and single equals should both work fine here (see http://stackoverflow.com/questions/2600281/what-is-the-difference-between-operator-and-in-bash). Are you possibly using something other than bash? Regardless, glad you found a fix for it. – pauljz Oct 17 '13 at 18:39
-
1Sorry to bring up an old thread, but I'm getting an error at the if statement. fatal: the remote end hung up unexpectedly. error: error in the sideband demultiplexer. It will echo the $branch outside the if statement. – gin93r Apr 07 '14 at 14:22
-
@Veo check out http://stackoverflow.com/questions/4582849/git-responds-with-error-in-sideband-demultiplexer Repo might be in a bad state? – pauljz Apr 08 '14 at 16:44
-
Thanks @pauljz I ended up getting it working. It had something to do with the if statement. Changing it to a switch statement seemed to fix the issue. – gin93r Apr 09 '14 at 12:18
-
5
-
Whats the advantage of using rev-parse here instead of simply using the last part of refname (`refs/heads/(.*)`) directly ? – Zitrax Mar 29 '16 at 11:57
-
2One risk I can think of would be tags, since their names can overlap with branch names. If you look for `refs/heads/master` instead of `refs/tags/master` you should be okay. There may be other edge-cases like this I can't think of though. It could be a good StackOverflow question in its own right. – pauljz Mar 29 '16 at 15:22
-
I've been trying this and I get this error when deleting a branch using git push origin --delete: remote: fatal: ambiguous argument 'refs/heads/test': unknown revision or path not in the working tree – Jérôme Mar 15 '18 at 14:55
-
1@pauljz I use `if branch=$(git rev-parse --symbolic --abbrev-ref $refname 2>/dev/null); then` so that git doesn't complain when I remove a branch. – Jérôme Mar 15 '18 at 15:15
The last parameter that a post-receive hook gets on stdin is what ref was changed, so we can use that to check if that value was "refs/heads/master." A bit of ruby similar to what I use in a post-receive hook:
STDIN.each do |line|
(old_rev, new_rev, ref_name) = line.split
if ref_name =~ /master/
# do your push
end
end
Note that it gets a line for each ref that was pushed, so if you pushed more than just master, it will still work.

- 7,298
- 5
- 43
- 57

- 20,795
- 9
- 30
- 30
-
Thanks for the Ruby example. I'm going to do something similar to this. – leifericf May 19 '14 at 09:17
Stefan's answer didn't work for me, but this did:
#!/bin/bash
echo "determining branch"
if ! [ -t 0 ]; then
read -a ref
fi
IFS='/' read -ra REF <<< "${ref[2]}"
branch="${REF[2]}"
if [ "master" == "$branch" ]; then
echo 'master was pushed'
fi
if [ "staging" == "$branch" ]; then
echo 'staging was pushed'
fi
echo "done"

- 31,756
- 15
- 66
- 72
-
Worked for me for branchs with a simple name (master,test,etc.), But when I have branch name such : prod12/proj250/ropesPatch12 . it doesn't work to well. Do you have a solution that can work with those special characters? – Shahar Hamuzim Rajuan Nov 19 '15 at 16:41
Neither of the solutions above worked for me. After much, much debugging, it turns out that using the 'read' command doesn't work -- instead, parsing command line arguments the usual way works fine.
Here is the exact post-update hook that I just successfully tested now on CentOS 6.3.
#!/bin/bash
echo "determining branch"
branch=`echo $1 | cut -d/ -f3`
if [ "master" == "$branch" ]; then
echo "master branch selected"
fi
if [ "staging" == "$branch" ]; then
echo "staging branch selected"
fi
exec git update-server-info
UPDATE: on an even stranger note, the pre-receive hook takes its input via stdin, therefore read with 'read' (wow, never thought I'd say that). The post-update hook still works with $1 for me.

- 61
- 3
-
2For what it's worth, the above solutions may not have worked because they are specifically for `post-receive` hooks, not `post-update` hooks. They take their input in different ways. – pauljz Feb 15 '14 at 04:03
-
`post-receive` takes stdin as noted here: https://git-scm.com/book/en/v2/Customizing-Git-Git-Hooks – h4xnoodle Feb 19 '16 at 01:01
The answer from @pauljz works fine for certain git hooks like pre-push
, but pre-commit
does not have access to those variables oldrev newrev refname
So I created this alternate version which works for pre-commit, or really and hook. This is a pre-commit
hook that will run a husky
script if we're NOT on the master
branch.
#!/bin/bash
# git 'commit' does not have access to these variables: oldrev newrev refname
# So get the branch name off the head
branchPath=$(git symbolic-ref -q HEAD) # Something like refs/heads/myBranchName
branch=${branchPath##*/} # Get text behind the last / of the branch path
echo "Head: $branchPath";
echo "Current Branch: $branch";
if [ "master" != "$branch" ]; then
# If we're NOT on the Master branch, then Do something
# Original Pre-push script from husky 0.14.3
command_exists () {
command -v "$1" >/dev/null 2>&1
}
has_hook_script () {
[ -f package.json ] && cat package.json | grep -q "\"$1\"[[:space:]]*:"
}
cd "frontend" # change to your project directory, if .git is a level higher
# Check if precommit script is defined, skip if not
has_hook_script precommit || exit 0
# Node standard installation
export PATH="$PATH:/c/Program Files/nodejs"
# Check that npm exists
command_exists npm || {
echo >&2 "husky > can't find npm in PATH, skipping precommit script in package.json"
exit 0
}
# Export Git hook params
export GIT_PARAMS="$*"
# Run npm script
echo "husky > npm run -s precommit (node `node -v`)"
echo
npm run -s precommit || {
echo
echo "husky > pre-commit hook failed (add --no-verify to bypass)"
exit 1
}
fi
I hope that helps someone. You can easily modify for your needs, anything in between the if
and fi
statements.

- 16,074
- 6
- 60
- 61
I had written a PHP script for myself to do this functionality.
https://github.com/fotuzlab/githubdump-php
Host this file on your server, preferably repo root and define the url in github webhooks. Change 'allcommits' on line 8 with your branch name and add your code/function at line 18.
e.g.
function githubdump($payload_object) {
// Write your code here.
exec('git push origin master');
}

- 1,436
- 1
- 15
- 19
Simple approach, in git hook
write
read refname
echo $refname
Simple - more info on this great link hooking system

- 14,824
- 12
- 64
- 81