threads / discuss / 9056

A question about git-rev-list

Subject: A question about git-rev-list

## tl;dr

4 messages between Jul 16, 2007 and Jul 17, 2007.

replies: 3people: 3as markdown or json

David Kastrup· Jul 16, 2007, 08:55 UTC · lore
Hi,
if I do
git-rev-list --remove-empty HEAD --not some-commit -- filename | tail -1

do I have any guarantee that the commit id I get (if any) is a direct descendant of some-commit? I _think_ --remove-empty might be necessary for that option, but have no idea whether this hunch is correct. Do I need additional options like --topo-order, or is that unnecessary?

Thanks,
-- 
David Kastrup
Linus Torvalds· Jul 16, 2007, 20:05 UTC · re: David Kastrup · lore

Re: A question about git-rev-list

On Mon, 16 Jul 2007, David Kastrup wrote:
Show 7 quoted lines
> 
> if I do
> 
> git-rev-list --remove-empty HEAD --not some-commit -- filename | tail -1
> 
> do I have any guarantee that the commit id I get (if any) is a direct
> descendant of some-commit?
No. You get the guarantee that
 - it's some kind of parent of HEAD
 - it's *not* a parent of some-commit
But the trivial case is a simple history like
	 /-B-\
	A     D
         \-C-/

(where "A" is the root commit, and "D" is the current HEAD, and there are two development lines from A to D).

If you now do
	git-rev-list HEAD --not C

you would generally see B on the list of commits, even though it's obviously not a direct descendant of C.

No amount of flags will change that. Of course, B might not show up for _other_ reasons (ie simply because it doesn't change "filename" at all), but generally you must always think of git-rev-list (and git log) as a _set_ operation.

There are no git operations that will look for "chain of commits from C to D" if that is what you want. No such chain necessarily even exists, and quite often it is ambiguous when it *does* exist (ie there is not a single chain from A to D, there are two chains).

You could add some kind of function that looks for the "shortest chain of commits from X to Y", but that would really be something fundamentally different from what git-rev-list gives you.

			Linus
David Kastrup· Jul 16, 2007, 21:16 UTC · re: Linus Torvalds · lore

Re: A question about git-rev-list

Linus Torvalds <torvalds@linux-foundation.org> writes:
Show 29 quoted lines
> On Mon, 16 Jul 2007, David Kastrup wrote:
>> 
>> if I do
>> 
>> git-rev-list --remove-empty HEAD --not some-commit -- filename | tail -1
>> 
>> do I have any guarantee that the commit id I get (if any) is a direct
>> descendant of some-commit?
>
> No. You get the guarantee that
>
>  - it's some kind of parent of HEAD
>  - it's *not* a parent of some-commit
>
> But the trivial case is a simple history like
>
> 	 /-B-\
> 	A     D
>        \-C-/
>
> (where "A" is the root commit, and "D" is the current HEAD, and there are 
> two development lines from A to  D).
>
> If you now do
>
> 	git-rev-list HEAD --not C
>
> you would generally see B on the list of commits, even though it's 
> obviously not a direct descendant of C.

Ok, thanks. As explained in a different posting, I try to tackle this now with the equivalent of

git-rev-list HEAD --parents --not B -- somefile.c | awk '/ B/{print $1}'

This will give me one descendant if there is one. The problem I have with that is that "somefile.c" renders commits uninteresting, but not if they have interesting parents (what do their parents have to do with it?). So if I have

A -> B -> B1 -> C -> HEAD

where somefile.c does not change between B and B1, then git-rev-list HEAD --not B -- somefile.c spews out HEAD C and that's it. Quite as expected. However, git-rev-list HEAD --not B --parents -- somefile.c spews out HEAD C C B1 B1 B

and look and behold, B1 became interesting because of its unlisted parent B.

There is something wrong with that.
-- 
David Kastrup, Kriemhildstr. 15, 44793 Bochum
Junio C Hamano· Jul 17, 2007, 04:33 UTC · re: David Kastrup · lore

Re: A question about git-rev-list

David Kastrup <dak@gnu.org> writes:
Show 23 quoted lines
> ...  The problem I have
> with that is that "somefile.c" renders commits uninteresting, but
> not if they have interesting parents (what do their parents have to do
> with it?).  So if I have
>
> A -> B -> B1 -> C -> HEAD
>
> where somefile.c does not change between B and B1, then
> git-rev-list HEAD --not B -- somefile.c
> spews out
> HEAD
> C
> and that's it.  Quite as expected.  However, 
> git-rev-list HEAD --not B --parents -- somefile.c
> spews out
> HEAD C
> C B1
> B1 B
>
> and look and behold, B1 became interesting because of its unlisted
> parent B.
>
> There is something wrong with that.
There indeed is, and that is not what I am seeing.
Running this script in an empty directory gives me:
    #!/bin/sh
    GIT_AUTHOR_NAME='A U Thor'
    GIT_AUTHOR_EMAIL=a.u.thor@example.xz
    GIT_COMMITTER_NAME="$GIT_AUTHOR_NAME"
    GIT_COMMITTER_EMAIL="$GIT_AUTHOR_EMAIL"
    GIT_AUTHOR_DATE='2007-07-16 00:00:00 +0000'
    GIT_COMMITTER_DATE='2007-07-16 00:00:00 +0000'
    export GIT_AUTHOR_NAME GIT_AUTHOR_EMAIL GIT_COMMITTER_NAME GIT_COMMITTER_EMAIL \
            GIT_AUTHOR_DATE GIT_COMMITTER_DATE
    rm -fr .git
    git init
    echo A >somefile.c; git add somefile.c; git commit -m 'A'; git tag A
    echo B >somefile.c; git add somefile.c; git commit -m 'B'; git tag B
    echo B1 >another; git add another; git commit -m 'B1'; git tag B1
    echo C >somefile.c; git add somefile.c; git commit -m 'C'; git tag C
    echo H >somefile.c; git add somefile.c; git commit -m 'H'; git tag H
    git rev-list --parents HEAD --not B -- somefile.c |
    git name-rev --tags --stdin
$ sh t000.sh
Initialized empty Git repository in .git/
Created initial commit 7a13cf5: A
 1 files changed, 1 insertions(+), 0 deletions(-)
 create mode 100644 somefile.c
Created commit b66d40b: B
 1 files changed, 1 insertions(+), 1 deletions(-)
Created commit 5530c91: B1
 1 files changed, 1 insertions(+), 0 deletions(-)
 create mode 100644 another
Created commit 7ee2b7e: C
 1 files changed, 1 insertions(+), 1 deletions(-)
Created commit 71fafc0: H
 1 files changed, 1 insertions(+), 1 deletions(-)
71fafc0f49ffb82b123c09ec0857f9f458ed32c4 (tags/H) 7ee2b7ed072190c56a2eedda3130f6bb729d0da1 (tags/C)
7ee2b7ed072190c56a2eedda3130f6bb729d0da1 (tags/C) b66d40bd7ed6d7403c16d8e37e6e410852598247 (tags/B)

The commit listed are H and then C; their (rewritten) parents are C and B, respectively.

← back to recent threads