Skip to content

Commit e1d0970

Browse files
committed
blame: dwim "blame --reverse OLD" as "blame --reverse OLD.."
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 <[email protected]>
1 parent d993ce1 commit e1d0970

File tree

2 files changed

+41
-2
lines changed

2 files changed

+41
-2
lines changed

Documentation/blame-options.txt

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,12 +28,13 @@ include::line-range-format.txt[]
2828
-S <revs-file>::
2929
Use revisions from revs-file instead of calling linkgit:git-rev-list[1].
3030

31-
--reverse::
31+
--reverse <rev>..<rev>::
3232
Walk history forward instead of backward. Instead of showing
3333
the revision in which a line appeared, this shows the last
3434
revision in which a line has existed. This requires a range of
3535
revision like START..END where the path to blame exists in
36-
START.
36+
START. `git blame --reverse START` is taken as `git blame
37+
--reverse START..HEAD` for convenience.
3738

3839
-p::
3940
--porcelain::

builtin/blame.c

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2447,6 +2447,41 @@ static char *prepare_final(struct scoreboard *sb)
24472447
return xstrdup_or_null(name);
24482448
}
24492449

2450+
static const char *dwim_reverse_initial(struct scoreboard *sb)
2451+
{
2452+
/*
2453+
* DWIM "git blame --reverse ONE -- PATH" as
2454+
* "git blame --reverse ONE..HEAD -- PATH" but only do so
2455+
* when it makes sense.
2456+
*/
2457+
struct object *obj;
2458+
struct commit *head_commit;
2459+
unsigned char head_sha1[20];
2460+
2461+
if (sb->revs->pending.nr != 1)
2462+
return NULL;
2463+
2464+
/* Is that sole rev a committish? */
2465+
obj = sb->revs->pending.objects[0].item;
2466+
obj = deref_tag(obj, NULL, 0);
2467+
if (obj->type != OBJ_COMMIT)
2468+
return NULL;
2469+
2470+
/* Do we have HEAD? */
2471+
if (!resolve_ref_unsafe("HEAD", RESOLVE_REF_READING, head_sha1, NULL))
2472+
return NULL;
2473+
head_commit = lookup_commit_reference_gently(head_sha1, 1);
2474+
if (!head_commit)
2475+
return NULL;
2476+
2477+
/* Turn "ONE" into "ONE..HEAD" then */
2478+
obj->flags |= UNINTERESTING;
2479+
add_pending_object(sb->revs, &head_commit->object, "HEAD");
2480+
2481+
sb->final = (struct commit *)obj;
2482+
return sb->revs->pending.objects[0].name;
2483+
}
2484+
24502485
static char *prepare_initial(struct scoreboard *sb)
24512486
{
24522487
int i;
@@ -2472,6 +2507,9 @@ static char *prepare_initial(struct scoreboard *sb)
24722507
sb->final = (struct commit *) obj;
24732508
final_commit_name = revs->pending.objects[i].name;
24742509
}
2510+
2511+
if (!final_commit_name)
2512+
final_commit_name = dwim_reverse_initial(sb);
24752513
if (!final_commit_name)
24762514
die("No commit to dig up from?");
24772515
return xstrdup(final_commit_name);

0 commit comments

Comments
 (0)