--- /dev/null
+#!/bin/sh
+##
+## Copyright (c) 2010, Sebastian Schwarz <seschwar@googlemail.com>
+##
+## Licensed under the MIT License; see accompanying `LICENSE` file.
+##
+
+USAGE="[OPTION | git-log-OPTION]..."
+LONG_USAGE="\
+Options:
+-a, --all list all branches/heads
+-b, --branch, --branches list branches
+ --contains [COMMIT] list only branches containing COMMIT
+ --head, --heads list heads; the default
+-h, --help
+-l, --local list only local branches/heads; the default
+ --merged [COMMIT] list only branches reachable from COMMIT
+ --no-merged [COMMIT] list only branches not reachable COMMIT
+-r, --remote list only remote branches/heads
+
+For the git-log-OPTION see git-log(1)'s manual page."
+OPTIONS_SPEC=
+SUBDIRECTORY_OK="true"
+
+git_exec_path="`git --exec-path`"
+
+ifs="$IFS"
+IFS=":"
+for dir in $git_exec_path; do
+ test -f "$dir/git-sh-setup" -a -r "$dir/git-sh-setup" \
+ && . "$dir/git-sh-setup" && break
+done || {
+ echo "fatal: unable to find and source git-sh-setup in $git_exec_path" >&2
+ exit 1
+}
+IFS="$ifs"
+
+## A newline character.
+N="
+"
+
+
+branch_refs() {
+ git branch "$@" --color=never | sed -e 's/^[ *] //' \
+ -e 's/^(no branch)$/HEAD/' -e 's/ -> .*$//'
+}
+
+
+## git-rev-list topologically sort the revs and annotates the with their
+## children. Commits without children are heads.
+childless_commits() {
+ branch_refs "$@" | git rev-list --children --stdin --topo-order \
+ | sane_grep -v ' '
+}
+
+
+## prefix PREFIX STRING
+prefix() {
+ test "${2#$1}" != "$2"
+}
+
+
+main() {
+ if git config --get-colorbool color.log; then
+ color_auto="always"
+ else
+ color_auto="never"
+ fi
+ git_branch_args="--color=never"
+ git_branch_scope=""
+ git_log_args="--color=$color_auto$N--max-count=1"
+ mode="heads"
+
+ while test "$#" -gt 0; do
+ case "$1" in
+ (-h|--help) ## Automatically handled by git(1) and git-sh-setup. Just
+ usage ## set $USAGE.
+ ;;
+ (-a|--all)
+ git_branch_scope="-a"
+ shift
+ ;;
+ (-l|--local)
+ git_branch_scope=""
+ shift
+ ;;
+ (-r|--remote)
+ git_branch_scope="-r"
+ shift
+ ;;
+ (-b|--branch|--branches)
+ mode="branches"
+ shift
+ ;;
+ (--head|--heads)
+ mode="heads"
+ shift
+ ;;
+ (--contains|--merged|--no-merged)
+ if test "$#" -lt 2 || prefix - "$2"; then ## $2 is
+ git_branch_args="$git_branch_args$N$1=HEAD" ## another
+ shift ## argument
+ else
+ git_branch_args="$git_branch_args$N$1=$2"
+ shift 2
+ fi
+ mode="branches"
+ ;;
+ (--contains=*|--merged=*|--no-merged=*)
+ git_branch_args="$git_branch_args$N$1"
+ mode="branches"
+ shift
+ ;;
+ (--color)
+ case "$2" in
+ (always|never)
+ git_log_args="$git_log_args$N--color=$2"
+ shift 2
+ ;;
+ (auto)
+ git_log_args="$git_log_args$N--color=$color_auto"
+ shift 2
+ ;;
+ (*)
+ git_log_args="$git_log_args$N--color"
+ shift
+ ;;
+ esac
+ ;;
+ (--color=auto)
+ git_log_args="$git_log_args$N--color=$color_auto"
+ shift
+ ;;
+ (*)
+ git_log_args="$git_log_args$N$1"
+ shift
+ ;;
+ esac
+ done
+
+ IFS="$N"
+ case "$mode" in
+ (branches)
+ branch_refs $git_branch_args $git_branch_scope
+ ;;
+ (heads)
+ childless_commits $git_branch_scope
+ ;;
+ (*)
+ die "unable to list commits for mode $mode"
+ ;;
+ esac | git rev-list --date-order --stdin --no-walk \
+ | while IFS= read -r ref; do
+ echo
+ git log $git_log_args "$ref" -- || exit "$?"
+ done | tail -n +2 | git_pager
+}
+
+
+main "$@"
+
--- /dev/null
+.TH "GIT\-HEADS" "1" "" "GIT\-HEADS(1)" ""
+.SH NAME
+.PP
+git\-heads \[en] show branches without any child commits with
+\f[C]git\-log\f[](1)
+.SH SYNOPSIS
+.PP
+\f[C]git\-heads\f[] [\f[C]\-\-all\f[] | \f[C]\-\-local\f[] |
+\f[C]\-\-remote\f[]] [\f[C]\-\-branches\f[]] [(\f[C]\-\-contains\f[] |
+\f[C]\-\-merged\f[] | \f[C]\-\-no\-merged\f[]) [\f[I]commit\f[]]]
+[\f[I]git\-log\-option\f[]]\&...
+.PP
+\f[C]git\-heads\f[] [\f[C]\-\-all\f[] | \f[C]\-\-local\f[] |
+\f[C]\-\-remote\f[]] [\f[C]\-\-heads\f[]]
+[\f[I]git\-log\-option\f[]]\&...
+.SH DESCRIPTION
+.PP
+Inspired by Mercurial's \f[C]heads\f[] command this Git command's
+purpose is to display information about so\-called \[lq]heads\[rq].
+Heads are commits which have no child commits.
+This also means that they are branches that have not been merged with
+any other branch.
+Do not confuse this definition of a head with Git's \f[C]HEAD\f[] ref
+which points to the lastly checked out commit.
+Furthermore you also must not confuse it with
+\f[C]$GIT_DIR/refs/heads\f[], the directory where the references to your
+local branches are stored.
+.PP
+\f[C]git\-heads\f[]' functionality is similar to the follow programs:
+.IP
+.nf
+\f[C]
+hg\ heads
+git\ branch\ ...\ |\ xargs\ \-n1\ git\ log\ ...
+git\ wtf
+\f[]
+.fi
+.PP
+It uses \f[C]git\-log\f[](1) to display the commit information.
+.SH OPTIONS
+.TP
+.B \-a, \-\-all
+Show both local and remote branches which have no child commits.
+.RS
+.RE
+.TP
+.B \-b, \-\-branch, \-\-branches
+Show branches regardless whether they have child commits or not.
+Similar to \f[C]git\-branch\f[](1).
+.RS
+.RE
+.TP
+.B \-\-contains [\f[I]commit\f[]], \-\-merged [\f[I]commit\f[]],
+\-\-no\-merged [\f[I]commit\f[]]
+Passed to \f[C]git\-branch\f[](1).
+Implies \f[C]\-\-branches\f[].
+.RS
+.RE
+.TP
+.B \-\-head, \-\-heads
+Show only the tips of the branches without any children.
+This is the default behavior.
+.RS
+.RE
+.TP
+.B \-l, \-\-local
+Show only local branches.
+This is the default behavior.
+.RS
+.RE
+.TP
+.B \-r, \-\-remote
+Show only remote branches.
+.RS
+.RE
+.TP
+.B \f[I]git\-log\-option\f[]
+These options are passed to \f[C]git\-log\f[](1) which is used to
+display the matching branches.
+.RS
+.RE
+.SH EXAMPLES
+.PP
+Show the last five commits for every remote branch which has been merged
+with the current branch:
+.IP
+.nf
+\f[C]
+git\ heads\ \-\-remote\ \-\-branches\ \-\-merged\ \-\-format=oneline\ \-n\ 5
+\f[]
+.fi
+.PP
+Show the last three commits on every head in a graph:
+.IP
+.nf
+\f[C]
+git\ heads\ \-\-all\ \-\-graph\ \-n\ 3
+\f[]
+.fi
+.SH SEE ALSO
+.PP
+\f[C]git\f[](1), \f[C]git\-branch\f[](1), \f[C]git\-log\f[](1),
+\f[C]git\ wtf\ \-h\f[], \f[C]hg\ heads\ \-\-help\f[].
+.PP
+Homepage: <http://github.com/seschwar/git-heads>
+.SH BUGS
+.PP
+If you find a bug please report it at
+<http://github.com/seschwar/git-heads/issues>.
+.SH AUTHORS
+Sebastian Schwarz <seschwar@googlemail.com>.