Instead of always requiring both ends of a range, we could DWIM "OLD", which could be a misspelt "OLD..", to be a range that ends at the current commit. Signed-off-by: Junio C Hamano <gitster@xxxxxxxxx> --- * I am not convinced that this is a good change, though. It is true that there is no other sensible interpretation of the user's intent when --reverse is given a single positive commit without any other revision, but at the same time, this feels a bit too much special casing that could hurt casual users when they are still forming their mental world model by learning from examples. Documentation/blame-options.txt | 5 +++-- builtin/blame.c | 38 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 41 insertions(+), 2 deletions(-) diff --git a/Documentation/blame-options.txt b/Documentation/blame-options.txt index 02cb684..6c6c78f 100644 --- a/Documentation/blame-options.txt +++ b/Documentation/blame-options.txt @@ -28,12 +28,13 @@ include::line-range-format.txt[] -S <revs-file>:: Use revisions from revs-file instead of calling linkgit:git-rev-list[1]. ---reverse:: +--reverse <rev>..<rev>:: Walk history forward instead of backward. Instead of showing the revision in which a line appeared, this shows the last revision in which a line has existed. This requires a range of revision like START..END where the path to blame exists in - START. + START. `git blame --reverse START` is taken as `git blame + --reverse START..HEAD` for convenience. -p:: --porcelain:: diff --git a/builtin/blame.c b/builtin/blame.c index a027b8a..574b47d 100644 --- a/builtin/blame.c +++ b/builtin/blame.c @@ -2447,6 +2447,41 @@ static char *prepare_final(struct scoreboard *sb) return xstrdup_or_null(name); } +static const char *dwim_reverse_initial(struct scoreboard *sb) +{ + /* + * DWIM "git blame --reverse ONE -- PATH" as + * "git blame --reverse ONE..HEAD -- PATH" but only do so + * when it makes sense. + */ + struct object *obj; + struct commit *head_commit; + unsigned char head_sha1[20]; + + if (sb->revs->pending.nr != 1) + return NULL; + + /* Is that sole rev a committish? */ + obj = sb->revs->pending.objects[0].item; + obj = deref_tag(obj, NULL, 0); + if (obj->type != OBJ_COMMIT) + return NULL; + + /* Do we have HEAD? */ + if (!resolve_ref_unsafe("HEAD", RESOLVE_REF_READING, head_sha1, NULL)) + return NULL; + head_commit = lookup_commit_reference_gently(head_sha1, 1); + if (!head_commit) + return NULL; + + /* Turn "ONE" into "ONE..HEAD" then */ + obj->flags |= UNINTERESTING; + add_pending_object(sb->revs, &head_commit->object, "HEAD"); + + sb->final = (struct commit *)obj; + return sb->revs->pending.objects[0].name; +} + static char *prepare_initial(struct scoreboard *sb) { int i; @@ -2472,6 +2507,9 @@ static char *prepare_initial(struct scoreboard *sb) sb->final = (struct commit *) obj; final_commit_name = revs->pending.objects[i].name; } + + if (!final_commit_name) + final_commit_name = dwim_reverse_initial(sb); if (!final_commit_name) die("No commit to dig up from?"); return xstrdup(final_commit_name); -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html