Zsh Mailing List Archive
Messages sorted by: Reverse Date, Date, Thread, Author

git commit descriptions

Next bit of git completion output usability.

Sometimes it would be useful to get a one-line summary of the
commit corresponding to what you're about to e.g. checkout.  I have lots
of similarly named branches and seeing the commit at the head of each
branch would help me work out which one I want to checkout.

The problem here is that you can get offered so many commit objects that
trying to do this for all of them in a big completion would be loopy.
So this probably shouldn't be tied to a standard style like verbose.

Here's my first go, but it's not there yet.  The max-verbose style
compares against the number of completions so far to decide if it's
worth doing this.  The reason this doesn't really work is you don't yet
know which of the sets of tags is going to be the most useful, and in
particular you don't yet know which of the list of object just passed in
is actually going to match.  What you really want to do is do the
matching, and only then decide how you're going to describe it.  I don't
know of a way to do that without second-guessing the matcher which isn't
a great thing to do; with the tags loop offering tags at equal priority
and running in an essentially random order the problem may be

One way of doing it would be to impose the limit instead over the
potential matches, but that's quite poor if actually there's a huge
list (e.g. you're looking at commit hashes) but actually only one
matches (e.g. you've put an unambiguous prefix on the command line
already and simply typed ^D to check if it's really the commit you
want, something I've been used to doing with other SCM systems for a
long time).

Note that with the standard style mechanism we already have the
capability to say only describe this style, and in that case
the max-verbose style may only be useful set to a large value to
enable it on the assumption that there won't actually be too many.
But that doesn't help with the many-are-called-but-few-are-chosen

I'm posting this to inspire suggestions.  With tags limited in the way
suggested by Oliver in the heads-local thread this isn't too bad, but in
that case having the limit is pretty useless --- you've got one set of
objects and at the point where you test the limit none of them have
matched yet.

Note also the locations using __git_describe_commit aren't well
chosen: I naively looked for all the locations using -M 'r:|/=**' and
switched those.

There are obviously other ways of extending this if it can be made


diff --git a/Completion/Unix/Command/_git b/Completion/Unix/Command/_git
index 1fcde90..2f42900 100644
--- a/Completion/Unix/Command/_git
+++ b/Completion/Unix/Command/_git
@@ -5004,6 +5004,28 @@ __git_is_in_middle_of_merge () {
   [[ -f $gitdir/MERGE_HEAD ]]
+(( $+functions[__git_describe_commit] )) ||
+__git_describe_commit () {
+  local __commits_in=$1
+  local __tag=$2
+  local __desc=$3
+  shift 3
+  integer maxverbose
+  if zstyle -s :completion:$curcontext max-verbose maxverbose &&
+    (( ${compstate[nmatches]} <= maxverbose )); then
+    local __c
+    local -a __commits
+    for __c in ${(P)__commits_in}; do
+      __commits+=("${__c}:${$(_call_program describe git log -1 --oneline $__c)//:/\\:}")
+    done
+    _describe -t $__tag $__desc __commits -M 'r:|/=**'
+  else
+    local expl
+    _wanted $__tag expl $__desc compadd -M 'r:|/=**' "$@" -a - $__commits_in
+  fi
 # Completion Wrappers
 (( $+functions[__git_ignore_line] )) ||
@@ -5536,24 +5558,22 @@ __git_branch_names () {
 (( $+functions[__git_remote_branch_names] )) ||
 __git_remote_branch_names () {
-  local expl
   declare -a branch_names
   branch_names=(${${(f)"$(_call_program remote-branch-refs git for-each-ref --format='"%(refname)"' refs/remotes 2>/dev/null)"}#refs/remotes/})
   __git_command_successful $pipestatus || return 1
-  _wanted remote-branch-names expl 'remote branch name' compadd -M 'r:|/=**' "$@" -a - branch_names
+  __git_describe_commit branch_names remote-branch-names 'remote branch name' "$@"
 (( $+functions[__git_remote_branch_names_noprefix] )) ||
 __git_remote_branch_names_noprefix () {
-  local expl
   declare -a heads
   branch_names=(${${${(f)"$(_call_program remote-branch-refs-noprefix git for-each-ref --format='"%(refname)"' refs/remotes 2>/dev/null)"}##*/}:#HEAD})
   __git_command_successful $pipestatus || return 1
-  _wanted remote-branch-names-noprefix expl 'remote branch name' compadd -M 'r:|/=**' "$@" -a - branch_names
+  __git_describe_commit branch_names remote-branch-names-noprefix 'remote branch name' "$@"
 (( $+functions[__git_commit_objects_prefer_recent] )) ||
@@ -5593,7 +5613,7 @@ __git_heads () {
 (( $+functions[__git_heads_local] )) ||
 __git_heads_local () {
-  local gitdir expl start
+  local gitdir
   declare -a heads
   heads=(${(f)"$(_call_program headrefs git for-each-ref --format='"%(refname:short)" refs/heads' 2>/dev/null)"})
@@ -5605,17 +5625,16 @@ __git_heads_local () {
     [[ -f $gitdir/refs/stash ]] && heads+=stash
-  _wanted heads-local expl "local head" compadd -M 'r:|/=**' "$@" -a - heads
+  __git_describe_commit heads heads-local "local head" "$@"
 (( $+functions[__git_heads_remote] )) ||
 __git_heads_remote () {
-  local gitdir expl start
   declare -a heads
   heads=(${(f)"$(_call_program headrefs git for-each-ref --format='"%(refname:short)" refs/remotes' 2>/dev/null)"})
-  _wanted heads-remote expl "remote head" compadd -M 'r:|/=**' "$@" -a - heads
+  __git_describe_commit heads heads-remote "remote head" "$@"
 (( $+functions[__git_commit_objects] )) ||

Messages sorted by: Reverse Date, Date, Thread, Author