6

When switching from one branch to another in Git, is there any way to retrieve the names of both branches from within the post-checkout hook?

So assuming I were to run the following two commands:

$ git branch
* branch_a
  branch_b
  master

$ git checkout branch_b
Switched to branch 'branch_b'

I'd be looking for the following two strings (in the post-checkout hook):

"branch_a"
"branch_b"
ojh
  • 422
  • 3
  • 9

2 Answers2

8

You can use git reflog inside your hook to get the previous and next branch. Here a simple working example:

#!/bin/bash

# $6 = previous branch, $8 is next branch
git reflog | awk 'NR==1{ print $6 " -> " $8; exit }'

EDIT: updated answer. Here the previous:

This hook is given with three arguments:

  • the ref of the previous HEAD
  • the ref of the new HEAD
  • 1 if it was a branch checkout, 0 for a file checkout.

With the two firsts you should have enough information for what you are trying to do.

GHugo
  • 2,584
  • 13
  • 14
  • Thanks for your answer - this works, but it feels a bit fragile - what if the message format changes at some point in the future? Surely there must be a less hacky approach than this? – ojh Aug 31 '14 at 09:21
  • I don't think there is another option. The reflog is used to track information that are only for the local repository (such as a checkout). As far as I understood how it is done, the entire message is stored inside the log, not a special structure keeping previous branch, new branch and the type of the action. Thus you can be pretty confident about parsing the string which is hardcoded inside git source code (https://github.com/git/git/blob/398dd4bd039680ba98497fbedffa415a43583c16/builtin/checkout.c#L615). – GHugo Aug 31 '14 at 09:40
  • 2
    About your edit: sadly arguments 1 and 2 of the post-checkout hook are SHAs, not symbolic refs (e.g. `refs/heads/master`); therefore, you can't really use them to unambiguously determine the old and new branches. – jub0bs Aug 31 '14 at 10:25
  • @GHugo I am marking this answer as correct (which it is, technically), for want of a cleaner approach. However, I am not convinced that the string's format being hard-coded into Git's source code is a *good* thing, as it means it could break unexpectedly (i.e. in a later version of Git). That said, with suitable tests and error handling, I can certainly work with this solution. – ojh Aug 31 '14 at 23:25
  • 1
    Never do `cmd | head -1 | awk '{ print $6 }'` as awk is perfectly capably of just operating on the first line of a file without the extra intermediate head and pipe: `cmd | awk 'NR==1{ print $6; exit }'`. – Ed Morton Sep 02 '14 at 14:09
  • `git describe --all ` applied to each of the SHA hashes given to the hook script would be another alternative... – twalberg Sep 02 '14 at 20:56
  • If you have multiple branches pointing to the same commit, you can't make the distinction. – GHugo Sep 02 '14 at 21:22
  • +1 for the `reflog` version. It works. We can only get one ref name from commit SHA if multiple branches refer it. – Landys Sep 22 '14 at 08:38
5

Here is full example, based on @GHugo answer

PREV_BRANCH=`git reflog | awk 'NR==1{ print $6; exit }'`
NEW_BRANCH=`git reflog | awk 'NR==1{ print $8; exit }'`
echo "PREV_BRANCH: $PREV_BRANCH"
echo "NEW_BRANCH: $NEW_BRANCH"
MegaJoe
  • 575
  • 6
  • 11