Skip to content

Instantly share code, notes, and snippets.

@intel352
Forked from joechrysler/who_is_my_mummy.sh
Last active June 26, 2021 17:06
Show Gist options
  • Save intel352/9761288 to your computer and use it in GitHub Desktop.
Save intel352/9761288 to your computer and use it in GitHub Desktop.
#!/usr/bin/env zsh
branch=`git rev-parse --abbrev-ref HEAD`
git show-branch | ack '\*' | ack -v "$branch" | head -n1 | sed 's/.*\[\(.*\)\].*/\1/' | sed 's/[\^~].*//'
# How it works:
# 1| Display a textual history of all commits.
# 2| Ancestors of the current commit are indicated
# by a star. Filter out everything else.
# 3| Ignore all the commits in the current branch.
# 4| The first result will be the nearest ancestor branch.
# Ignore the other results.
# 5| Branch names are displayed [in brackets]. Ignore
# everything outside the brackets, and the brackets.
# 6| Sometimes the branch name will include a ~2 or ^1 to
# indicate how many commits are between the referenced
# commit and the branch tip. We don't care. Ignore them.
@intel352
Copy link
Author

Removed the trailing backtick that caused error to occur.

@jpbochi
Copy link

jpbochi commented Aug 25, 2014

As git aliases ("pb" for parent branch, and "cb" for current branch), add the following to your .gitconfig file. One could use git config --global, but the escaping hell would be just too much.

[alias]
    cb = rev-parse --abbrev-ref HEAD
    pb = !"git show-branch -a | ack '\\*' | ack -v \"`git cb`\" | head -n1 | sed 's/.*\\[\\(.*\\)\\].*/\\1/' | sed 's/[\\^~].*//'"

@matt-d-rat
Copy link

@jpbochi The alias works a treat, however I seem to get a lot of warnings spat out before the result:

warning: ignoring origin/some/branch/name cannot handle more than 25 refs

Is there a way to suppress these warnings for just this alias?

@psema4
Copy link

psema4 commented Apr 23, 2015

@matt-d-rat Haven't tried the aliases yet but you might redirect git's stderr to stdout and then filter the warnings out at the end. Just forked for Ubuntu environments that does this.

@JacobEvelyn
Copy link

I just redirected git's stderr to /dev/null. Works like a charm!

@ezequielv
Copy link

@jpbochi: It's a nice idea to make commands like the cb and pb aliases. I've gone a bit further, and:

  • created a self-documenting pair of commands (the "long versions") and their convenient "short versions" equivalents;
  • reduced the number of runtime dependencies to just git and awk (the command(s) should work with mawk, as well as gawk):
  • made the git show-closest-parent-branch command return a non-zero exit code when the branch name could not be computed;
  • silently discarded invoked (sub)command(s) error output;
  • increased error checking;
  • FIXED: do not "trip" on output that contains an asterisk (such as one in the commit description): only the line section containing the one-character "tokens" is considered for the match;
[alias]
        # based on: https://gist.github.com/intel352/9761288
        show-closest-branch = rev-parse --abbrev-ref HEAD
        # based on: http://stackoverflow.com/questions/3161204/find-the-parent-branch-of-a-git-branch
        show-closest-parent-branch = !"git show-branch -a --no-color 2> /dev/null | awk -F '[]^~[]' -v current_branch=`git show-closest-branch 2> /dev/null || true` 'BEGIN { rc=1 ; if ( length( current_branch ) == 0 ) { exit } } ( ( index( $1, \"*\" ) > 0 ) && ( length( $2 ) > 0 ) && ( $2 != current_branch ) ) { print $2 ; rc=0 ; exit } END { exit rc }'"
        # short versions
        cb = !git show-closest-branch
        pb = !git show-closest-parent-branch

Sample runs:

# run from a directory with a valid git repository, with a topic branch branched off from an existing branch
$ ( cd my_repository_directory && git pb ) ; echo "rc: $?"
some_branch_name
rc: 0

# run from a non-git directory
$ ( cd /tmp && git pb ) ; echo "rc: $?"
rc: 1

@haoyangnz
Copy link

haoyangnz commented May 11, 2016

vbc=$(git rev-parse --abbrev-ref HEAD)
vbc_col=$(( $(git show-branch | grep '^[^\[]*\*' | head -1 | cut -d* -f1 | wc -c) - 1 )) 
swimming_lane_start_row=$(( $(git show-branch | grep -n "^[\-]*$" | cut -d: -f1) + 1 )) 
git show-branch | tail -n +$swimming_lane_start_row | grep -v "^[^\[]*\[$vbc" | grep "^.\{$vbc_col\}[^ ]" | head -n1 | sed 's/.*\[\(.*\)\].*/\1/' | sed 's/[\^~].*//'

Achieves the same ends, but uses a much safer approach that doesn't misbehave in a number of scenarios:

  1. Parent branch's last commit is a merge, making the column show -
    not *
  2. Commit message contains branch name
  3. Commit message contains *

Obviously you can combine this into a single line if you wish.

@kostaz
Copy link

kostaz commented Jan 12, 2017

Doesn't latest git support showing the parent branch in a native way?

@tirans
Copy link

tirans commented Jun 26, 2021

Doesn't latest git support showing the parent branch in a native way?

found the following to work for me (limited testing)
git branch --create-reflog | head -n 1

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment