46

Is there a way to trigger a hook after a new branch has been checked out in Git?

jub0bs
  • 46,795
  • 22
  • 148
  • 157
netflux
  • 3,469
  • 6
  • 33
  • 39

4 Answers4

48

A git hook is a script placed in a special location of your repository, that location is:

.git/hooks

The script can be any kind that you can execute in your environment i.e. bash, python, ruby etc.

The hook that is executed after a checkout is post-checkout. From the docs:

...The hook is given three parameters...

Example:

  1. Create the hook (script):

    touch .git/hooks/post-checkout
    chmod u+x .git/hooks/post-checkout
    
  2. Hook sample content:

#!/bin/bash                                                                      

set -e                                                                           

printf '\npost-checkout hook\n\n'                                                

prevHEAD=$1                                                                      
newHEAD=$2                                                                       
checkoutType=$3                                                                  

[[ $checkoutType == 1 ]] && checkoutType='branch' ||                             
                            checkoutType='file' ;                                

echo 'Checkout type: '$checkoutType                                              
echo '    prev HEAD: '`git name-rev --name-only $prevHEAD`                       
echo '     new HEAD: '`git name-rev --name-only $newHEAD`

Note: The shebang in the first line indicates the type of script.

This script (git hook) will only capture the three parameters passed and print them in a human-friendly format.

givanse
  • 13,070
  • 8
  • 47
  • 71
  • 2
    Do you know of any way to tell if this is the branch creation checkout (besides looking at the new HEAD's reflog)? – pkoch Jan 17 '14 at 22:55
  • Seems like it would be a good idea for you to ask a whole new question. If you do, send me the link and I'll see if I can help. What is the problem that you are trying to solve? – givanse Jan 18 '14 at 14:16
  • If a commit is the top of several branches, `name-rev` only gives the name that comes alphabetically first. Thus after checking out a branch with a a name that alphabetically precedes the name of the original branch, the `prev HEAD` line will give the name of the NEW branch. A workaround: `thisBranchName=$(git rev-parse --abbrev-ref HEAD); for branch in $(git branch --color=never --contains $1 | sed -e 's/^..//'); do if [ "$(git show-ref -s $branch )" == $1 ] && [ "$branch" != "$thisBranchName" ]; then parentBranchName=$branch; break; fi; done` – Ansa211 Feb 13 '17 at 21:06
  • 1
    Thanks, the `chmod u+x .git/hooks/post-checkout` part is what got me. – romellem Apr 06 '17 at 16:58
37

If one of these hooks won’t do it I’d be amazed:

https://schacon.github.io/git/githooks.html

Maybe this one:

post-checkout

This hook is invoked when a git-checkout is run after having updated the worktree. The hook is given three parameters: the ref of the previous HEAD, the ref of the new HEAD (which may or may not have changed), and a flag indicating whether the checkout was a branch checkout (changing branches, flag=1) or a file checkout (retrieving a file from the index, flag=0). This hook cannot affect the outcome of git-checkout.

Florian Wendelborn
  • 1,389
  • 16
  • 27
SpliFF
  • 35,724
  • 15
  • 80
  • 113
  • Note that the `post-checkout` hook also works for `git switch` whereas there’s not `post-switch` hook (as of git 2.25). – Niavlys Jan 28 '21 at 14:31
11

Similar to others but verifies that the branch has been checked out once.

#!/bin/bash

# this is a file checkout – do nothing
if [ "$3" == "0" ]; then exit; fi

BRANCH_NAME=$(git symbolic-ref --short -q HEAD)
NUM_CHECKOUTS=`git reflog --date=local | grep -o ${BRANCH_NAME} | wc -l`

#if the refs of the previous and new heads are the same 
#AND the number of checkouts equals one, a new branch has been created
if [ "$1" == "$2"  ] && [ ${NUM_CHECKOUTS} -eq 1 ]; then
    git push origin ${BRANCH_NAME}
fi
Justin Tilson
  • 693
  • 9
  • 12
  • 3
    This got me on the right path, thanks so much! Since it's grepping reflog to count checkouts I believe one gotcha would be if a branch had previously existed and a new branch with the same name was created, that branch wouldn't be recognized as new. That could be the desired behavior or an issue depending on use case but I just figured I'd mention it. – Pwnrar Sep 18 '16 at 06:20
6

The post-checkout hook receives three parameters:

  1. Ref of previous HEAD
  2. Ref of new HEAD
  3. Whether this is a file checkout (0) or branch checkout (1)

You can use the fact that a branch created from the current HEAD will have the same value for parameters 1 and 2.

cat > .git/hooks/post-checkout <<"EOF"
if [ "$3" == "0" ]; then exit; fi
if [ "$1" == "$2" ]; then 
  echo "New branch created. (Probably)."
fi
EOF

chmod u+x .git/hooks/post-checkout

Limitations:

  • Checking out an existing branch which happens to be at the same HEAD as the current HEAD will fool it.
  • Creating a new branch not from the current HEAD will not be detected.
Steve Bennett
  • 84,226
  • 27
  • 133
  • 175