git/list[1] front-page[2] threads[3] people[4] search[5] about
 

Re: git-rev-list feature request

From
Linus Torvalds <torvalds@osdl.org>
Date
Mar 10, 2006, 05:14 UTC
Message-ID
<Pine.LNX.4.64.0603092056300.18022@g5.osdl.org>
In-Reply-To
<17425.1459.786864.172060@cargo.ozlabs.ibm.com>
On Fri, 10 Mar 2006, Paul Mackerras wrote:
Show 14 quoted lines
> Linus Torvalds writes:
> 
> > Yeah. I _think_ what you want is
> > 
> >  - phase 1: generate the current graph that we already do for
> > 
> > 	git-rev-list --all ^cmit
> > 
> >  - phase 2: start at "cmit", and mark everything that refers to it as 
> >    "show me" (including "cmit" itself, which was originally marked 
> >    uninteresting)
> 
> I'm not sure if that's what I want.  Is that how "git-rev-list -- foo" 
> works?

Nope. "git-rev-list -- foo" will just start from the heads given, and walk down.

Show 5 quoted lines
> What I want is basically just what "git-rev-list -- foo" does, but
> with some extra flexibility in choosing what commits are interesting -
> that is, to be able to say that a commit is interesting if it affects
> some file, has a reference under .git/refs, or if it is one of a set
> of specified commits.
Ahh, ok, you actually wanted something simpler than I thought you might.

What you want is (in its most trivial form) really trivial: mark the special commits you want to save with TREECHANGE, so that they aren't pruned by the logic that prunes off the "this commit doesn't change the file, so ignore it" commits.

HOWEVER. That trivial thing has problems. What if the history got simplified at a merge because one side of the merge changed it, and the other one did not - in that case we'll follow the history down the leg that didn't change (since that's the history that ended up being the final one). Now, that means that we will totally prune out the other parent info, and the commits you want to remain simply won't be "connected" any more.

To explain that better, let's say that history looks like this:
	     a
	    / \
	   b   c
	   |   |
	   d   e
	    \ /
	     f

and you're following file "foo", which is the same in "a" and "c". The fact that they are the same there means that the name pruning will decide that the history that led to "a" through "b" wasn't interesting, so it will prune that out, and make the whole history be

	   a
	   |
	   c
	   |
	   e
	   |
	   f

and then after that, it will remove all commits that didn't actually change foo at all (we know "a" was such a commit since we already simplified the merge, but let's say that "e" was one too), so you get

	   c
	   |
	   f
as the final simplified history right now.

Now, the problem is that what should you do if you want to tag "d" and "e" as inherently interesting (perhaps because they are tagged releases)?

Now, the "e" case is the above trivial case: just mark any "inherently interesting" commit with the TREECHANGE flag, and the history won't be pruned away. So it now looks like

	   c
	   |
	   e    <- faked "interesting"
	   |
	   f

however, the fact that you did the same to "d" means that we will have that too on our list of "interesting" commits, even though we've pruned away all of the history leading _from_ it, so the trivial algorithm would actually result in

	     c
	     |
	 d   e
	  \ /
	   f

in that case. We'd see "d" because it's somehow intrisically interesting, but it ends up being shown as that "dead tip", because the merge that would reach it was simplified away.

Is that what you'd want?

If so, then the appended trivial path should effectively do what you ask for. It keeps all the revs you passed in as "interesting" whether they are or not, so now you can effectively just pass in all the refs you want, and it will never remove any of the positive refs you passed it.

If you want a commit that has a ref pointing to it be marked as interesting only if we see it while parsing the tree, then you need to do slightly more (in "rewrite_one()", you should look up whether that commit has a ref pointing to it).

		Linus
----
diff --git a/revision.c b/revision.c
index 713f27e..90d3764 100644
--- a/revision.c
+++ b/revision.c
@@ -149,7 +149,8 @@ static struct commit *get_commit_referen
 		if (flags & UNINTERESTING) {
 			mark_parents_uninteresting(commit);
 			revs->limited = 1;
-		}
+		} else
+			object->flags |= TREECHANGE;
 		return commit;
 	}
 
Previous: Paul MackerrasNext: Linus Torvalds
Message 6 of 7 in “git-rev-list feature request”
  1. Paul MackerrasMar 10, 2006
  2. Linus TorvaldsMar 10, 2006
  3. Junio C HamanoMar 10, 2006
  4. Linus TorvaldsMar 10, 2006
  5. Paul MackerrasMar 10, 2006
  6. Linus TorvaldsMar 10, 2006
  7. Linus TorvaldsMar 10, 2006

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.