git.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* Re: How do I specify a revision for "git blame" by date?
  2012-06-14 15:26 How do I specify a revision for "git blame" by date? perryh
@ 2012-06-14 10:05 ` Thomas Rast
  2012-06-15 13:02   ` perryh
  2012-06-14 10:19 ` Andreas Schwab
  1 sibling, 1 reply; 9+ messages in thread
From: Thomas Rast @ 2012-06-14 10:05 UTC (permalink / raw)
  To: perryh; +Cc: git

perryh@pluto.rain.com writes:

> How do I get "git blame" to operate "as of" a particular date in
> the past, without having to manually look up the corresponding
> SHA1 using "git rev-list"?  For example, I can get a report as of
> 2011-12-29 by doing something like:
>
>   $ git rev-list --all --date-order --format="%h %ai" .
>   ...
>   7c69106 2012-01-03 ...
>   b4227af 2011-12-27 ...
>   ...
>
>   $ git blame <file> b4227af
>
> but I want to have git look up the last revision prior to the given
> date, by doing something like
>
>   $ git blame <file> @{2011-12-29}

You are looking at two different dates:

a) The dates stored within the commit object:

   - committer date, similarly shown by %ci: when the commit was created.
   - author date, shown by %ai: when "this" commit was "first created".

   These are properties of the commits, and thus part of the project
   history.  Anyone who clones the project sees the same dates.

b) The dates in the reflog, tracking the movement of *your local* refs
   (like the name implies).  The HEAD reflog tracks what *you* had
   "currently checked out" at a given time.

An automated search in (b) is possible with the @{} syntax, but note
that it tracks the *branch state*.  It says nothing about how "current"
a certain resulting commit was.  For example, if you say

  git checkout v1.6.0
  sleep 2
  git checkout -
  git show '@{1 second ago}'

you will see the commit for v1.6.0 from back in 2008.

An automated search in (a) is hard, mostly because in nonlinear history
there is not usually a single (and well-defined) commit that could be
returned.  Git could attempt to search all of your branches, like you
have done above, but which one among all commits from that date should
it pick?  Furthermore, the result set to pick from will change if you
fetch more history into your repo.

It's even worse with the author (as opposed to committer) dates: those
are not even remotely close to monotonic in most repos, because they are
kept across rewriting.  (The committer dates would be monotonic if
everyone kept their clocks in sync and avoided filter-branch tricks.)

-- 
Thomas Rast
trast@{inf,student}.ethz.ch

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: How do I specify a revision for "git blame" by date?
  2012-06-14 15:26 How do I specify a revision for "git blame" by date? perryh
  2012-06-14 10:05 ` Thomas Rast
@ 2012-06-14 10:19 ` Andreas Schwab
  2012-06-14 17:22   ` Junio C Hamano
  2012-06-15 13:03   ` perryh
  1 sibling, 2 replies; 9+ messages in thread
From: Andreas Schwab @ 2012-06-14 10:19 UTC (permalink / raw)
  To: perryh; +Cc: git

perryh@pluto.rain.com writes:

> How do I get "git blame" to operate "as of" a particular date in
> the past, without having to manually look up the corresponding
> SHA1 using "git rev-list"?  For example, I can get a report as of
> 2011-12-29 by doing something like:
>
>   $ git rev-list --all --date-order --format="%h %ai" .
>   ...
>   7c69106 2012-01-03 ...
>   b4227af 2011-12-27 ...
>   ...
>
>   $ git blame <file> b4227af

You can use any rev-list option, so --until=2011-12-27 should work.

Andreas.

-- 
Andreas Schwab, schwab@linux-m68k.org
GPG Key fingerprint = 58CA 54C7 6D53 942B 1756  01D3 44D5 214B 8276 4ED5
"And now for something completely different."

^ permalink raw reply	[flat|nested] 9+ messages in thread

* How do I specify a revision for "git blame" by date?
@ 2012-06-14 15:26 perryh
  2012-06-14 10:05 ` Thomas Rast
  2012-06-14 10:19 ` Andreas Schwab
  0 siblings, 2 replies; 9+ messages in thread
From: perryh @ 2012-06-14 15:26 UTC (permalink / raw)
  To: git

How do I get "git blame" to operate "as of" a particular date in
the past, without having to manually look up the corresponding
SHA1 using "git rev-list"?  For example, I can get a report as of
2011-12-29 by doing something like:

  $ git rev-list --all --date-order --format="%h %ai" .
  ...
  7c69106 2012-01-03 ...
  b4227af 2011-12-27 ...
  ...

  $ git blame <file> b4227af

but I want to have git look up the last revision prior to the given
date, by doing something like

  $ git blame <file> @{2011-12-29}

This does not work as written:  it ignores the date parameter with
a warning:

  warning: Log for '' only goes back to Thu, 10 May 2012 08:14:16 -0700.

If I use HEAD@ instead of just @ I get the same message with 'HEAD'
in place of '', and everything else I've tried gives a "fatal: bad
revision" message.

Clearly, as shown by git rev-list, the log for the _repository_
goes back farther than May 10, so this is a problem of finding the
correct syntax rather than of wanting to do something "impossible".
What do I need to put in front of the @ to cause the entire log to
be examined?

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: How do I specify a revision for "git blame" by date?
  2012-06-14 10:19 ` Andreas Schwab
@ 2012-06-14 17:22   ` Junio C Hamano
  2012-06-15 13:03   ` perryh
  1 sibling, 0 replies; 9+ messages in thread
From: Junio C Hamano @ 2012-06-14 17:22 UTC (permalink / raw)
  To: Andreas Schwab; +Cc: perryh, git

Andreas Schwab <schwab@linux-m68k.org> writes:

> perryh@pluto.rain.com writes:
>
>> How do I get "git blame" to operate "as of" a particular date in
>> the past, without having to manually look up the corresponding
>> SHA1 using "git rev-list"?  For example, I can get a report as of
>> 2011-12-29 by doing something like:
>>
>>   $ git rev-list --all --date-order --format="%h %ai" .
>>   ...
>>   7c69106 2012-01-03 ...
>>   b4227af 2011-12-27 ...
>>   ...
>>
>>   $ git blame <file> b4227af
>
> You can use any rev-list option, so --until=2011-12-27 should work.

News to me.

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: How do I specify a revision for "git blame" by date?
  2012-06-14 10:05 ` Thomas Rast
@ 2012-06-15 13:02   ` perryh
  2012-06-15 15:01     ` Jeff King
  0 siblings, 1 reply; 9+ messages in thread
From: perryh @ 2012-06-15 13:02 UTC (permalink / raw)
  To: trast; +Cc: git

Thomas Rast <trast@student.ethz.ch> wrote:

> perryh@pluto.rain.com writes:
>
> > How do I get "git blame" to operate "as of" a particular date in
> > the past, without having to manually look up the corresponding
> > SHA1 using "git rev-list"?  For example, I can get a report as
> > of 2011-12-29 by doing something like:
> >
> >   $ git rev-list --all --date-order --format="%h %ai" .
> >   ...
> >   7c69106 2012-01-03 ...
> >   b4227af 2011-12-27 ...
> >   ...
> >
> >   $ git blame <file> b4227af
> >
> > but I want to have git look up the last revision prior to the
> > given date, by doing something like
> >
> >   $ git blame <file> @{2011-12-29}
>
> You are looking at two different dates:
>
> a) The dates stored within the commit object:
>
>    - committer date, similarly shown by %ci: when the commit
>      was created.
>    - author date, shown by %ai: when "this" commit was "first
>      created".
>
>    These are properties of the commits, and thus part of the project
>    history.  Anyone who clones the project sees the same dates.
>
> b) The dates in the reflog, tracking the movement of *your local*
>    refs (like the name implies).  The HEAD reflog tracks what *you*
>    had "currently checked out" at a given time.
>
> An automated search in (b) is possible with the @{} syntax, but
> note that it tracks the *branch state*.  It says nothing about how
> "current" a certain resulting commit was.  For example, if you say
>
>   git checkout v1.6.0
>   sleep 2
>   git checkout -
>   git show '@{1 second ago}'
>
> you will see the commit for v1.6.0 from back in 2008.
>
> An automated search in (a) is hard, mostly because in nonlinear
> history there is not usually a single (and well-defined) commit
> that could be returned.

Given that we are discussing "git blame", which reports on the
history of a file (specifically the commit in which each line
originated), I think (a) must logically be included in the search
-- especially if (as in the example) the date specified is earlier
than any time in (b).  Perhaps such a request needs to use some
other syntax rather than @{}, but surely the capability ought to
be provided somehow.

> Git could attempt to search all of your branches, like you have
> done above ...

Actually, I am not at all sure that one would want --all in the
general case; it works well in my particular case because all
branches in this repository have been merged back to master.

Intuitively, I suspect that the default search set should be all
commits reachable from HEAD.  (BTW I may not have the terminology
exactly right; while I have been working with other CM systems
for a couple of decades, I am quite new to git and there is much
about it that I do not yet understand.)

> but which one among all commits from that date should it pick?

The latest one that is not later than the specified date (and time
-- a timestamp within {} can provide more granularity than just
the day; in the example provided there were in fact no commits on
2011-12-29 so no ambiguity would arise from using the date alone.)

> Furthermore, the result set to pick from will change if you
> fetch more history into your repo.

Using the "commits reachable from HEAD" strategy above, I think
not, unless I also merge from some of that additional history.

> It's even worse with the author (as opposed to committer) dates:
> those are not even remotely close to monotonic in most repos,
> because they are kept across rewriting.  (The committer dates
> would be monotonic if everyone kept their clocks in sync and
> avoided filter-branch tricks.)

Since it is the file's included commits that "git blame" reports on,
I doubt it would be all that useful to deal in anything other than
commit dates.  (I seem to have copy-pasted the wrong format in the
rev-list part of the example -- it should be "%h %ci".)

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: How do I specify a revision for "git blame" by date?
  2012-06-14 10:19 ` Andreas Schwab
  2012-06-14 17:22   ` Junio C Hamano
@ 2012-06-15 13:03   ` perryh
  1 sibling, 0 replies; 9+ messages in thread
From: perryh @ 2012-06-15 13:03 UTC (permalink / raw)
  To: schwab; +Cc: git

Andreas Schwab <schwab@linux-m68k.org> wrote:

> perryh@pluto.rain.com writes:
> > How do I get "git blame" to operate "as of" a particular date in
> > the past, without having to manually look up the corresponding
> > SHA1 using "git rev-list"?
>
> You can use any rev-list option, so --until=2011-12-27 should work.

That gets rid of the warning message, but it doesn't produce the
desired results.  Whether specified as

  $ git blame <file> --until=2011-12-27

or

  $ git blame --until=2011-12-27 <file>

the report still includes commits that are much more recent than
2011-12-27, and it omits material that was deleted since then --
material which _is_ included when specifying the SHA1 of the commit
which the --until should have identified.  IOW, the --until seems
to be silently ignored.

I guess this is a bug if rev-list options are supposed to work in
"git blame".  If they are _not_ supposed to work there, I would
claim that the failure to generate an error or warning message (when
I've asked for something that's not intended to work) is a bug.

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: How do I specify a revision for "git blame" by date?
  2012-06-15 13:02   ` perryh
@ 2012-06-15 15:01     ` Jeff King
  2012-06-15 15:53       ` Junio C Hamano
  0 siblings, 1 reply; 9+ messages in thread
From: Jeff King @ 2012-06-15 15:01 UTC (permalink / raw)
  To: perryh; +Cc: trast, git

On Fri, Jun 15, 2012 at 06:02:39AM -0700, perryh@pluto.rain.com wrote:

> > You are looking at two different dates:
> >
> > a) The dates stored within the commit object:
> >
> >    - committer date, similarly shown by %ci: when the commit
> >      was created.
> >    - author date, shown by %ai: when "this" commit was "first
> >      created".
> >
> >    These are properties of the commits, and thus part of the project
> >    history.  Anyone who clones the project sees the same dates.
> >
> > b) The dates in the reflog, tracking the movement of *your local*
> >    refs (like the name implies).  The HEAD reflog tracks what *you*
> >    had "currently checked out" at a given time.
> >
> > An automated search in (b) is possible with the @{} syntax, but
> > note that it tracks the *branch state*.  It says nothing about how
> > "current" a certain resulting commit was.  For example, if you say
> >
> >   git checkout v1.6.0
> >   sleep 2
> >   git checkout -
> >   git show '@{1 second ago}'
> >
> > you will see the commit for v1.6.0 from back in 2008.
> >
> > An automated search in (a) is hard, mostly because in nonlinear
> > history there is not usually a single (and well-defined) commit
> > that could be returned.
> 
> Given that we are discussing "git blame", which reports on the
> history of a file (specifically the commit in which each line
> originated), I think (a) must logically be included in the search
> -- especially if (as in the example) the date specified is earlier
> than any time in (b).  Perhaps such a request needs to use some
> other syntax rather than @{}, but surely the capability ought to
> be provided somehow.

It would have to use a different syntax, as reflog times (selected by
@{}) and commit dates (usually selected via --since and --until) are
measuring fundamentally different things, and have no meaningful
relation to each other.

But that still doesn't address the issue that (a) is not well-defined.
Imagine I have this history:


  A--B--C---G--H
   \       /
    D--E--F

that is, two lines of development splitting at A and merging at H. And
imagine the commit timestamps are (let's just refer to them as integers
for the sake of simplicity, but they are representing days or seconds or
whatever):

  A(1)--B(2)--C(3)--G(7)--H(8)
   \               /
    D(2)--E(4)--F(6)

What does it mean to ask for the commit at time=5? If you were to choose
the commit with the highest timestamp <= 5, you would pick E. But there
are two independent, simultaneous lines of development, and at time=5 on
the top branch, the most current commit was C.

So the question doesn't make sense. There was no one commit at time=5;
there were multiple (as many as you have simultaneous branches). You can
pick a winner out of them, but there are multiple ways to do it. For
example, you might want to say "of all lines of development, the one
that had most recently committed as of time=5" (and of course you can
still have a tie there). Or you could say "along the first-parent
ancestry, the commit that was most recent as of time=5". I am sure one
could come up with others, as well.

Git-blame expects you to give it a well-defined point (as it must, since
it is a backwards walk down history showing what led to a particular set
of content; it wouldn't make sense to feed it multiple starting points).
You could do so by asking rev-list to walk the graph according to your
requirements and feeding the result to blame, like:

  # most recent on any line of development that is merged to HEAD
  git blame `git rev-list -1 --until=5 HEAD`

  # most recent on any line of development in the whole repo
  git blame `git rev-list -1 --until=5 --all`

  # most recent version on the first-parent; if you follow a
  # topic-branch workflow and always merge up into "master", then this
  # will blame what was on master at time=5
  git blame `git rev-list -1 --until=5 --first-parent HEAD`

-Peff

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: How do I specify a revision for "git blame" by date?
  2012-06-15 15:01     ` Jeff King
@ 2012-06-15 15:53       ` Junio C Hamano
  2012-06-16  4:13         ` perryh
  0 siblings, 1 reply; 9+ messages in thread
From: Junio C Hamano @ 2012-06-15 15:53 UTC (permalink / raw)
  To: Jeff King; +Cc: perryh, trast, git

Jeff King <peff@peff.net> writes:

> But that still doesn't address the issue that (a) is not well-defined.
> Imagine I have this history:
>
>   A--B--C---G--H
>    \       /
>     D--E--F
>
> that is, two lines of development splitting at A and merging at H. And
> imagine the commit timestamps are (let's just refer to them as integers
> for the sake of simplicity, but they are representing days or seconds or
> whatever):
>
>   A(1)--B(2)--C(3)--G(7)--H(8)
>    \               /
>     D(2)--E(4)--F(6)
>
> What does it mean to ask for the commit at time=5?
> ...
> Git-blame expects you to give it a well-defined point (as it must, since
> it is a backwards walk down history showing what led to a particular set
> of content; it wouldn't make sense to feed it multiple starting points).
> You could do so by asking rev-list to walk the graph according to your
> requirements and feeding the result to blame, like:
>
>   # most recent on any line of development that is merged to HEAD
>   git blame `git rev-list -1 --until=5 HEAD`
>
>   # most recent on any line of development in the whole repo
>   git blame `git rev-list -1 --until=5 --all`
>
>   # most recent version on the first-parent; if you follow a
>   # topic-branch workflow and always merge up into "master", then this
>   # will blame what was on master at time=5
>   git blame `git rev-list -1 --until=5 --first-parent HEAD`

Very well explained.  Thanks.

The short answer to the question on "Subject:" line is "You don't".

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: How do I specify a revision for "git blame" by date?
  2012-06-15 15:53       ` Junio C Hamano
@ 2012-06-16  4:13         ` perryh
  0 siblings, 0 replies; 9+ messages in thread
From: perryh @ 2012-06-16  4:13 UTC (permalink / raw)
  To: gitster, peff; +Cc: git, trast

Junio C Hamano <gitster@pobox.com> wrote:
> Jeff King <peff@peff.net> writes:
> > But that still doesn't address the issue that (a) is not
> > well-defined.  Imagine I have this history:
> >
> >   A--B--C---G--H
> >    \       /
> >     D--E--F
> >
> > that is, two lines of development splitting at A and merging
> > at H. And imagine the commit timestamps are (let's just refer
> > to them as integers for the sake of simplicity, but they are
> > representing days or seconds or whatever):
> >
> >   A(1)--B(2)--C(3)--G(7)--H(8)
> >    \               /
> >     D(2)--E(4)--F(6)
> >
> > What does it mean to ask for the commit at time=5?
> > ...
> > Git-blame expects you to give it a well-defined point ...
> > You could do so by asking rev-list to walk the graph according
> > to your requirements and feeding the result to blame, like:
> >
> >   # most recent on any line of development that is merged to HEAD
> >   git blame `git rev-list -1 --until=5 HEAD`
> >
> >   # most recent on any line of development in the whole repo
> >   git blame `git rev-list -1 --until=5 --all`
> >
> >   # most recent version on the first-parent; if you follow a
> >   # topic-branch workflow and always merge up into "master",
> >   # then this will blame what was on master at time=5
> >   git blame `git rev-list -1 --until=5 --first-parent HEAD`
>
> Very well explained.  Thanks.

+1

> The short answer to the question on "Subject:" line is "You don't".

The slightly longer, but perhaps more practically useful, answer is
"You use 'git rev-list' to look up the correct commit, and shell
'command substitution' to pass the result to 'git blame', as Jeff
has illustrated."  That solution sure beats displaying the entire
revision list, and then manually selecting the desired commit from
it.

^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2012-06-16 20:50 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-06-14 15:26 How do I specify a revision for "git blame" by date? perryh
2012-06-14 10:05 ` Thomas Rast
2012-06-15 13:02   ` perryh
2012-06-15 15:01     ` Jeff King
2012-06-15 15:53       ` Junio C Hamano
2012-06-16  4:13         ` perryh
2012-06-14 10:19 ` Andreas Schwab
2012-06-14 17:22   ` Junio C Hamano
2012-06-15 13:03   ` perryh

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).