Merge branch 'jc/blame-reverse'
It is a common mistake to say "git blame --reverse OLD path", expecting that the command line is dwimmed as if asking how lines in path in an old revision OLD have survived up to the current commit. * jc/blame-reverse: blame: dwim "blame --reverse OLD" as "blame --reverse OLD.." blame: improve diagnosis for "--reverse NEW"
This commit is contained in:
commit
1172e16af0
@ -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::
|
||||
|
@ -10,7 +10,7 @@ SYNOPSIS
|
||||
[verse]
|
||||
'git blame' [-c] [-b] [-l] [--root] [-t] [-f] [-n] [-s] [-e] [-p] [-w] [--incremental]
|
||||
[-L <range>] [-S <revs-file>] [-M] [-C] [-C] [-C] [--since=<date>]
|
||||
[--progress] [--abbrev=<n>] [<rev> | --contents <file> | --reverse <rev>]
|
||||
[--progress] [--abbrev=<n>] [<rev> | --contents <file> | --reverse <rev>..<rev>]
|
||||
[--] <file>
|
||||
|
||||
DESCRIPTION
|
||||
|
@ -2456,6 +2456,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;
|
||||
@ -2474,14 +2509,17 @@ static char *prepare_initial(struct scoreboard *sb)
|
||||
if (obj->type != OBJ_COMMIT)
|
||||
die("Non commit %s?", revs->pending.objects[i].name);
|
||||
if (sb->final)
|
||||
die("More than one commit to dig down to %s and %s?",
|
||||
die("More than one commit to dig up from, %s and %s?",
|
||||
revs->pending.objects[i].name,
|
||||
final_commit_name);
|
||||
sb->final = (struct commit *) obj;
|
||||
final_commit_name = revs->pending.objects[i].name;
|
||||
}
|
||||
|
||||
if (!final_commit_name)
|
||||
die("No commit to dig down to?");
|
||||
final_commit_name = dwim_reverse_initial(sb);
|
||||
if (!final_commit_name)
|
||||
die("No commit to dig up from?");
|
||||
return xstrdup(final_commit_name);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user