Skip to contentSkip to conversation

add --abbrev to 'git cherry'

PATCH In review Jeff Epler 4 participants 9 messages Jun 15, 2016 2 messages not in the archive Documentation

lore
Share & tools
lore

Jeff Epler

author
#0 lore raw

PATCH v2 1/1 add --abbrev to 'git cherry'

Abbreviating ids makes 'git cherry -v' more useful, since you can see more of the commit message summary:

    git cherry -v --abbrev | less -S

---

An earlier version of this patch added multiple different flags to 'git cherry', but --abbrev (was -a) is really the important one. Thanks to Jakub Narebski and Michael J Gruber for comments on the first patch.

 Documentation/git-cherry.txt |    5 ++++-
 builtin-log.c                |   24 +++++++++++++++++++-----
 2 files changed, 23 insertions(+), 6 deletions(-)
Documentation/git-cherry.txt +4 -1
index 7deefda..5c03da0 100644
@@ -7,7 +7,7 @@ git-cherry - Find commits not merged upstream
 
 SYNOPSIS
 --------
-'git cherry' [-v] [<upstream> [<head> [<limit>]]]
+'git cherry' [-v] [--abbrev[=<n>]] [<upstream> [<head> [<limit>]]]
 
 DESCRIPTION
 -----------
@@ -49,6 +49,9 @@ OPTIONS
 -v::
 	Verbose.
 
+--abbrev[=<n>]::
+	Abbreviate commit ids to the given number of characters
+
 <upstream>::
 	Upstream branch to compare against.
 	Defaults to the first tracked remote branch, if available.
builtin-log.c +19 -5
index f10cfeb..1f3093e 100644
@@ -1130,7 +1130,7 @@ static int add_pending_commit(const char *arg, struct rev_info *revs, int flags)
 }
 
 static const char cherry_usage[] =
-"git cherry [-v] [<upstream> [<head> [<limit>]]]";
+"git cherry [-v] [--abbrev[=<n>]] [<upstream> [<head> [<limit>]]]";
 int cmd_cherry(int argc, const char **argv, const char *prefix)
 {
 	struct rev_info revs;
@@ -1142,9 +1142,23 @@ int cmd_cherry(int argc, const char **argv, const char *prefix)
 	const char *head = "HEAD";
 	const char *limit = NULL;
 	int verbose = 0;
+	int abbrev = 40;
+
+	while(argc > 1 && argv[1][0] == '-') {
+		if (!strcmp(argv[1], "-v")) {
+			verbose = 1;
+		} else if(!strcmp(argv[1], "--abbrev")) {
+			abbrev = DEFAULT_ABBREV;
+		} else if(!prefixcmp(argv[1], "--abbrev=")) {
+			abbrev = strtol(argv[1] + 9, NULL, 10);
+			if(abbrev < MINIMUM_ABBREV)
+				abbrev = MINIMUM_ABBREV;
+			else if(abbrev > 40)
+				abbrev = 40;
+		} else {
+			die("unrecognized argument: %s", argv[1]);
+		}
 
-	if (argc > 1 && !strcmp(argv[1], "-v")) {
-		verbose = 1;
 		argc--;
 		argv++;
 	}
@@ -1218,12 +1232,12 @@ int cmd_cherry(int argc, const char **argv, const char *prefix)
 			struct strbuf buf = STRBUF_INIT;
 			pretty_print_commit(CMIT_FMT_ONELINE, commit,
 			                    &buf, 0, NULL, NULL, 0, 0);
-			printf("%c %s %s\n", sign,
+			printf("%c %.*s %s\n", sign, abbrev,
 			       sha1_to_hex(commit->object.sha1), buf.buf);
 			strbuf_release(&buf);
 		}
 		else {
-			printf("%c %s\n", sign,
+			printf("%c %.*s\n", sign, abbrev,
 			       sha1_to_hex(commit->object.sha1));
 		}
 
Signature · 1 line
1.5.4.3
#1 lore raw

Jeff Epler, 30.05.2009:

Quoted 3 lines
 Documentation/git-cherry.txt |    5 ++++-
 builtin-log.c                |   24 +++++++++++++++++++-----
 2 files changed, 23 insertions(+), 6 deletions(-)

You could also add --abbrev= to the bash completion.

Documentation/git-cherry.txt OPTIONS · line 53

Quoted 10 lines
Documentation/git-cherry.txt +2 -0
index 7deefda..5c03da0 100644
@@ -49,6 +49,9 @@ OPTIONS
 -v::
 	Verbose.
 
+--abbrev[=<n>]::
+	Abbreviate commit ids to the given number of characters

The full stop is missing :)
And you could add "The default value is 7." as in the git-branch docs. Or even copy the whole description from there for consistency, it also mentions that this sets the minimum length, the displayed SHA1 may be longer, but more about this below.

Quoted 8 lines
builtin-log.c +0 -0
index f10cfeb..1f3093e 100644
@@ -1218,12 +1232,12 @@ int cmd_cherry(int argc, const char **argv, const char *prefix)
 			struct strbuf buf = STRBUF_INIT;
 			pretty_print_commit(CMIT_FMT_ONELINE, commit,
 			                    &buf, 0, NULL, NULL, 0, 0);

builtin-log.c int cmd_cherry(int argc, const char **argv, const char *prefix) · line 1242

Quoted 10 lines
builtin-log.c +2 -2
-			printf("%c %s %s\n", sign,
+			printf("%c %.*s %s\n", sign, abbrev,
 			       sha1_to_hex(commit->object.sha1), buf.buf);
 			strbuf_release(&buf);
 		}
 		else {
-			printf("%c %s\n", sign,
+			printf("%c %.*s\n", sign, abbrev,
 			       sha1_to_hex(commit->object.sha1));
 		}

There is no test for unique ids. "git cherry --abbrev=4" always prints 4 chars per SHA1, so "git show" on these SHA1s mostly gives "error: short SHA1 xxxx is ambiguous." in git.git.

find_unique_abbrev() will help.

Markus

author
#2 lore raw

PATCH v3 1/1 add --abbrev to 'git cherry'

Abbreviating ids makes 'git cherry -v' more useful, since you can see more of the commit message summary:

    git cherry -v --abbrev | less -S

---

Compared to the last patch, this adds to the bash completion, improves doc consistency, and uses find_unique_abbrev to shorten commit ids. Thanks to Markus Heidelberg for feedback.

 Documentation/git-cherry.txt           |    6 +++++-
 builtin-log.c                          |   24 +++++++++++++++++++-----
 contrib/completion/git-completion.bash |   10 +++++++++-
 3 files changed, 33 insertions(+), 7 deletions(-)
Documentation/git-cherry.txt +5 -1
index 7deefda..c8cbbcc 100644
@@ -7,7 +7,7 @@ git-cherry - Find commits not merged upstream
 
 SYNOPSIS
 --------
-'git cherry' [-v] [<upstream> [<head> [<limit>]]]
+'git cherry' [-v] [--abbrev[=<n>]] [<upstream> [<head> [<limit>]]]
 
 DESCRIPTION
 -----------
@@ -49,6 +49,10 @@ OPTIONS
 -v::
 	Verbose.
 
+--abbrev[=<n>]::
+	Alter the sha1's minimum display length in the output listing.
+	The default value is 7.
+
 <upstream>::
 	Upstream branch to compare against.
 	Defaults to the first tracked remote branch, if available.
builtin-log.c +19 -5
index f10cfeb..c115a8e 100644
@@ -1130,7 +1130,7 @@ static int add_pending_commit(const char *arg, struct rev_info *revs, int flags)
 }
 
 static const char cherry_usage[] =
-"git cherry [-v] [<upstream> [<head> [<limit>]]]";
+"git cherry [-v] [--abbrev[=<n>]] [<upstream> [<head> [<limit>]]]";
 int cmd_cherry(int argc, const char **argv, const char *prefix)
 {
 	struct rev_info revs;
@@ -1142,9 +1142,23 @@ int cmd_cherry(int argc, const char **argv, const char *prefix)
 	const char *head = "HEAD";
 	const char *limit = NULL;
 	int verbose = 0;
+	int abbrev = 40;
+
+	while(argc > 1 && argv[1][0] == '-') {
+		if (!strcmp(argv[1], "-v")) {
+			verbose = 1;
+		} else if(!strcmp(argv[1], "--abbrev")) {
+			abbrev = DEFAULT_ABBREV;
+		} else if(!prefixcmp(argv[1], "--abbrev=")) {
+			abbrev = strtol(argv[1] + 9, NULL, 10);
+			if(abbrev < MINIMUM_ABBREV)
+				abbrev = MINIMUM_ABBREV;
+			else if(abbrev > 40)
+				abbrev = 40;
+		} else {
+			die("unrecognized argument: %s", argv[1]);
+		}
 
-	if (argc > 1 && !strcmp(argv[1], "-v")) {
-		verbose = 1;
 		argc--;
 		argv++;
 	}
@@ -1219,12 +1233,12 @@ int cmd_cherry(int argc, const char **argv, const char *prefix)
 			pretty_print_commit(CMIT_FMT_ONELINE, commit,
 			                    &buf, 0, NULL, NULL, 0, 0);
 			printf("%c %s %s\n", sign,
-			       sha1_to_hex(commit->object.sha1), buf.buf);
+			       find_unique_abbrev(commit->object.sha1, abbrev), buf.buf);
 			strbuf_release(&buf);
 		}
 		else {
 			printf("%c %s\n", sign,
-			       sha1_to_hex(commit->object.sha1));
+			       find_unique_abbrev(commit->object.sha1, abbrev));
 		}
 
 		list = list->next;
contrib/completion/git-completion.bash +9 -1
index c84d765..536a769 100755
@@ -804,7 +804,15 @@ _git_checkout ()
 
 _git_cherry ()
 {
-	__gitcomp "$(__git_refs)"
+	local cur="${COMP_WORDS[COMP_CWORD]}"
+	case "$cur" in
+	-*)
+		__gitcomp "-v --abbrev --abbrev="
+		;;
+	*)
+		__gitcomp "$(__git_refs)"
+		;;
+	esac
 }
 
 _git_cherry_pick ()
Signature · 1 line
1.5.4.3
#3 lore raw
Quoted 11 lines · Jeff Epler
builtin-log.c +7 -0
@@ -1142,9 +1142,23 @@ int cmd_cherry(int argc, const char **argv, const char *prefix)
        const char *head = "HEAD";
        const char *limit = NULL;
        int verbose = 0;
+       int abbrev = 40;
+
+       while(argc > 1 && argv[1][0] == '-') {
+               if (!strcmp(argv[1], "-v")) {
+                       verbose = 1;
+               } else if(!strcmp(argv[1], "--abbrev")) {
+                       abbrev = DEFAULT_ABBREV;

builtin-log.c int cmd_cherry(int argc, const char **argv, const char *prefix) · line 1161

Quoted 10 lines
builtin-log.c +9 -0
+               } else if(!prefixcmp(argv[1], "--abbrev=")) {
+                       abbrev = strtol(argv[1] + 9, NULL, 10);
+                       if(abbrev < MINIMUM_ABBREV)
+                               abbrev = MINIMUM_ABBREV;
+                       else if(abbrev > 40)
+                               abbrev = 40;
+               } else {
+                       die("unrecognized argument: %s", argv[1]);
+               }
 

You might want to look at using the parse options API. It has options for verbose and abbrev builtin, so you don't have to do any extra work. Plus you get a nice usage message for free. See Documentation/technical/api-parse-options.txt for more info.

Quoted 8 lines
contrib/completion/git-completion.bash +0 -0
index c84d765..536a769 100755
@@ -804,7 +804,15 @@ _git_checkout ()
 
  _git_cherry ()
  {

contrib/completion/git-completion.bash _git_checkout () · line 815

Quoted 10 lines
contrib/completion/git-completion.bash +9 -1
-       __gitcomp "$(__git_refs)"
+       local cur="${COMP_WORDS[COMP_CWORD]}"
+       case "$cur" in
+       -*)
+               __gitcomp "-v --abbrev --abbrev="
+               ;;
+       *)
+               __gitcomp "$(__git_refs)"
+               ;;
+       esac

Completion doesn't include short options (-v). This also means that --* is used instead of -*

Finally, you'll want to Cc Shawn (Shawn O. Pearce
<[email protected]>) on bash completion.

#4 lore raw
Quoted 3 lines · Stephen Boyd

You might want to look at using the parse options API. It has options for verbose and abbrev builtin, so you don't have to do any extra work....

Why do people even think a change like this to a _plumbing_ command is desirable?

Admittedly, there already is "verbose" option that adds redundant information to the output of this particular plumbing, which might arguably be equally wrong as what this patch does, but I think it is excusable. At least it lets the Porcelain script that uses the command avoid calling 'git cat-file commit' to find out the title of the commit.

But --abbrev does not even add any information. If implemented correctly (which earlier iteration did not even do), it may not lose information by choping the output too short to make it ambiguous, but as others pointed out about using grep in the calling Porcelain to filter (or more likely, sift the lines into "+" and "-" bins) to shoot down -d/-D options, I do not see the point of adding --abbrev to this plumbing command very much.

#5 lore raw

Junio C Hamano, 31.05.2009:

Quoted 2 lines

Why do people even think a change like this to a _plumbing_ command is desirable?

git-cherry is plumbing? In git(1) it is listed as porcelain. And the plumbings show-ref, ls-files and ls-tree support --abbrev.

Markus

#6 lore raw
Quoted 5 lines · Markus Heidelberg

Junio C Hamano, 31.05.2009:

Quoted 2 lines

Why do people even think a change like this to a _plumbing_ command is desirable?

git-cherry is plumbing? In git(1) it is listed as porcelain.

I'd say it is a miscategorization, but I do not care too deeply, as I never use it myself (even though my Porcelain scripts would).

author
#9 lore raw
In reply to a message not in the archive
Quoted 3 lines · Junio C Hamano

Stopping here would be a good idea if "log --left-right --cherry-pick A...B" (perhaps with a custom --pretty option) covers what you originally wanted to do.

Yes, I now see that 'git log' can pretty much do what I want. Having learned of 'git cherry', it didn't cross my mind that 'git log' was set up to do all 'git cherry' did and more.

Quoted 4 lines

But if the reason why you wanted --abbrev was because you wanted to use it in your scripted Porcelain, and if the reason why you have your scripted Porcelain is because you wanted to add some _other_ information that "log" does not give you easily, perhaps it would be a good idea to share _that_.

No, this is all about displaying directly to the user (me) in a pager, specifically about getting as much of the change summary in the first 80 columns as possible.

Jeff

#10 lore raw
In reply to Junio C Hamano
Quoted 14 lines · Junio C Hamano
Quoted 3 lines · Stephen Boyd

You might want to look at using the parse options API. It has options for verbose and abbrev builtin, so you don't have to do any extra work....

Why do people even think a change like this to a _plumbing_ command is desirable?

Admittedly, there already is "verbose" option that adds redundant information to the output of this particular plumbing, which might arguably be equally wrong as what this patch does, but I think it is excusable. At least it lets the Porcelain script that uses the command avoid calling 'git cat-file commit' to find out the title of the commit.

Quoted 6 lines

But --abbrev does not even add any information. If implemented correctly (which earlier iteration did not even do), it may not lose information by choping the output too short to make it ambiguous, but as others pointed out about using grep in the calling Porcelain to filter (or more likely, sift the lines into "+" and "-" bins) to shoot down -d/-D options, I do not see the point of adding --abbrev to this plumbing command very much.

I was tempted to say the same thing, but I decided to leave it up to the maintainer ;-) Maybe if there was a compelling use case it would make more sense?

Or, would it make more sense to just use git-log? Right now you can do git log --oneline --cherry-pick <head>..<upstream> and get close. Maybe we can add a "--cherry" option to git-log which will act like git-cherry by finding unmerged commits?