#!/bin/bash # # git-last.sh - helper app for listing the early history of a git head # Copyright (C) 2008 Clifford Wolf # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. export LC_ALL=C SUBDIRECTORY_OK=Yes OPTIONS_SPEC="\ git-last [options] [...] git-last lists the early history of a git head. -- h,help show the help l,limit= larger number results in longer output (default=20) b,branch use git-show-branch instead of normal output s,straight only show first parents (not the merged stuff) x,noextra suppress lookup of extra ref names a,sha1 also print (abbreviated) SHA1 commit name " . "$(git --exec-path)/git-sh-setup" limit=20 withmerges=true withextras=true withsha1=false useshowbranch=false revlist=( ) subjlist=( ) revlist_idx=0 revlist_n=0 while (( $# > 0 )); do if [ "$1" = "--" ]; then shift; break fi if [ "$1" = "-l" ]; then limit=$2 shift; shift; continue fi if [ "$1" = "-b" ]; then useshowbranch=true shift; continue fi if [ "$1" = "-s" ]; then withmerges=false shift; continue fi if [ "$1" = "-x" ]; then withextras=false shift; continue fi if [ "$1" = "-a" ]; then withsha1=true shift; continue fi usage done for r; do revlist=( "${revlist[@]}" "$r" ) (( revlist_n++ )) done if [ $revlist_n -eq 0 ]; then revlist=( "${revlist[@]}" "HEAD" ) (( revlist_n++ )) fi show_branch_args=( "${revlist[@]}" ) get_parents_num() { q="'" qq="'\\\\''" git cat-file commit "$1" | gawk ' BEGIN { c=0; subjectline=0; } /^parent/ { c++; } subjectline { gsub(/'$q'/, "'$qq'"); print "s='$q'" $0 "'$q'"; nextfile; } /^$/ { subjectline=1; } END { print "n=" c; } ' } nicerevname() { if $withsha1; then echo -n "`git rev-parse "$1" | cut -c1-7` " fi echo "$1" | perl -pe 's:((\^1)+)(?![0-9]):"~".length($1)/2:eg;' # s:~1(?![0-9]):^:g;' } sortrevname() { echo "$1" | perl -pe 's:((\^1)+)(?![0-9]):"~".length($1)/2:eg; s:([0-9]+):sprintf"%010d",$1:eg' } while (( $revlist_idx < $revlist_n )) && ( (( limit > 0 )) || ! $useshowbranch ); do r="${revlist[$revlist_idx]}" n="" s="" eval "$( get_parents_num "$r" )" if $withextras; then xtra="$( git show-ref -d | grep "^$(git rev-parse $r) " | sed -r 's,^.* (refs/)?,,'; )" else xtra="" fi if [ -n "$xtra" ]; then subjlist[$revlist_idx]="$s (`echo $xtra`)" else subjlist[$revlist_idx]="$s" fi if (( n == 0 )); then if $useshowbranch; then revlist=( "${revlist[@]}" "$r" ) (( revlist_n++ )) (( limit--)) fi else if (( limit > 0 )); then for ((i=1; i <= n; i++)); do if (( $i == 1 )) || $withmerges; then revlist=( "${revlist[@]}" "$r^$i" ) (( revlist_n++ )) (( limit--)) fi done fi fi (( revlist_idx++ )) done if $useshowbranch; then git show-branch "${show_branch_args[@]}" $( for ((i=revlist_idx; i < revlist_n; i++)); do s=$( sortrevname "${revlist[$i]}" ) r=$( nicerevname "${revlist[$i]}" ) printf "%s\t%s\n" "$s" "$r" done | sort | cut -f2- ) else maxrlen=0; sortlist=( ) for ((i=0; i < revlist_n; i++)); do sortlist[$i]="$( sortrevname "${revlist[$i]}" )" revlist[$i]="$( nicerevname "${revlist[$i]}" )" if (( maxrlen <= ${#revlist[$i]} )); then maxrlen=${#revlist[$i]} fi done for ((i=0; i < revlist_n; i++)); do s="${sortlist[$i]}" r="${revlist[$i]}" printf "%s\t%-*s %s\n" "$s" $maxrlen "$r" "${subjlist[$i]}" done | sort | cut -f2- fi