Git development
 help / color / mirror / Atom feed
* Re: git2rss --- publish changes from git-log via RSS
From: Jakub Narebski @ 2006-07-04 21:09 UTC (permalink / raw)
  To: git
In-Reply-To: <20060704191135.GB10534@rahul.net>

Bennett Todd wrote:

> Just switched Bent Linux[1] from darcs to git (darcs is sexy, but I
> can build git; ghc defeats me). So I hacked up a quick and simple
> git2rss to replace my use of darcs2rss for publishing updates.
> 
> <URL:http://bent.latency.net/git2rss>

Added to http://git.or.cz/gitwiki/InterfacesFrontendsAndTools#git2rss
Please correct/expand the info if needed.

BTW. gitweb includes RSS feed, see e.g.:
  http://www.kernel.org/git/?p=git/git.git;a=rss
  http://www.kernel.org/git/?p=git/git.git;a=opml

> I like to read the back archives before posting to a list I've just
> subscribed to, but couldn't find a downloadable version of the git
> list. If anybody could point me to one, I'd appreciate it.

Both GitWiki and Wikipedia

  http://git.or.cz/gitwiki/GitCommunity
  http://en.wikipedia.org/wiki/Git_%28software%29

mentions several git mailing list archives

-- 
Jakub Narebski
Warsaw, Poland
ShadeHawk on #git

^ permalink raw reply

* Re: [PATCH] Additional merge-base tests
From: Junio C Hamano @ 2006-07-04 21:15 UTC (permalink / raw)
  To: Johannes Schindelin; +Cc: git
In-Reply-To: <Pine.LNX.4.63.0607041019580.29667@wbgn013.biozentrum.uni-wuerzburg.de>

Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:

> We could introduce a time.maximumSkew variable, and just walk only 
> that much further when traversing the commits.

We could have had "commit generation number" in the commit
object header, and use that instead of commit timestamps for
these traversal purposes.  The generation number for a commit is
defined to be max(generation number of its parents)+1 and we
prime the recursive this definition by defining the generation
number for the root commit to be one.  A moral equivalent
alternative would be to notice that the commit timestamp we are
going to use to create for a new commit is smaller than one of
the commit timestamps of its parent commits and adjust the
commit timestamp in such a case by git-commit-tree, perhaps with
a warning.

These are pretty much water under the bridge by now, for two
reasons.  One is that I think it is better to make the tools
that use get_merge_bases() prepared for the case the function
includes suboptimal bases anyway, and the other is once we do
that this is not a strong enough justification to modify the
commit object format.

^ permalink raw reply

* Re: [PATCH] rev-list: free commit_list in ... handler
From: Junio C Hamano @ 2006-07-04 21:37 UTC (permalink / raw)
  To: Rene Scharfe; +Cc: git
In-Reply-To: <20060704192220.GA9500@lsrfire.ath.cx>

Thanks.

^ permalink raw reply

* Re: contrib/ status
From: Eric Wong @ 2006-07-04 21:56 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git
In-Reply-To: <7vbqs6pfhi.fsf@assigned-by-dhcp.cox.net>

Junio C Hamano <junkio@cox.net> wrote:
> Eric Wong <normalperson@yhbt.net> writes:
> 
> > Junio C Hamano <junkio@cox.net> wrote:
> >> Junio C Hamano <junkio@cox.net> writes:
> >> 
> >> > ... the
> >> > things under contrib/ are not part of git.git but are there only
> >> > for convenience....
> >> 
> >> This reminds me of something quite different.  I am getting an
> >> impression that enough people have been helped by git-svn and it
> >> might be a good idea to have it outside contrib/ area.
> >
> > That would be great.  IMHO, it puts git in a position to supplant
> > centralized SVN usage one developer at a time, making it easier
> > to make a gradual transition to git.  Of course, there's also svk
> > in a similar position...
> 
> OK, then let's give a few days (it's a long weekend extendeding
> into July 4th in the US) to let others from the list chime in,
> and then please help me migrate your test scripts and Makefile
> pieces into the toplevel project.

Ok, I'll have a patch ready by then.  I'm not sure which number family I
should take for the tests, 8xxx and 9xxx don't have any rules for their
use, but the [89]0xx area seems taken.  Would naming them 91xx be good?

Also, the tests can be extremely slow since they rely on svn, so there
will be a way to skip the tests if users are not interested.

-- 
Eric Wong

^ permalink raw reply

* Re: [PATCH] Add a custom ./configure script
From: Petr Baudis @ 2006-07-04 21:57 UTC (permalink / raw)
  To: Jakub Narebski; +Cc: git
In-Reply-To: <e8drmq$8ec$1@sea.gmane.org>

Dear diary, on Tue, Jul 04, 2006 at 03:50:16PM CEST, I got a letter
where Jakub Narebski <jnareb@gmail.com> said that...
> Petr Baudis wrote:
> 
> > The patch is on top of pu, that is Jakub Narebski's autoconf patch, because
> > it reuses most of its infrastructure and just replaces the configure script.
> 
> If you named it for example configure.sh, then autoconf generated version, 
> and your by hand created version could coexist.

I'm not opposed to it per se, but I'm just not sure if it makes any
sense to support them both in parallel, since then you have parallel
infrastructure doing the exactly same thing, or worse yet - performing
a subtly different set of tests. The benefit is unclear to me.

Another thing is that it's named *everywhere* ./configure and if I use a
different name now then it will be hard to rename.

-- 
				Petr "Pasky" Baudis
Stuff: http://pasky.or.cz/
Snow falling on Perl. White noise covering line noise.
Hides all the bugs too. -- J. Putnam

^ permalink raw reply

* Re: [PATCH] Additional merge-base tests
From: Johannes Schindelin @ 2006-07-04 22:25 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git
In-Reply-To: <7v8xn9gjh5.fsf@assigned-by-dhcp.cox.net>

Hi,

On Tue, 4 Jul 2006, Junio C Hamano wrote:

> Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:
> 
> > We could introduce a time.maximumSkew variable, and just walk only 
> > that much further when traversing the commits.
> 
> We could have had "commit generation number" in the commit
> object header, and use that instead of commit timestamps for
> these traversal purposes.  The generation number for a commit is
> defined to be max(generation number of its parents)+1 and we
> prime the recursive this definition by defining the generation
> number for the root commit to be one.

Are you really, really sure this is a remedy? I, for one, am quite sure of 
the opposite. What you propose is just another time scale, only this time, 
it is not universally true (not even minus local incompetence to keep the 
clock accurate).

If that should be not true, you always could rely on topo order. Which 
does not seem to solve the problem for you.

Ciao,
Dscho

^ permalink raw reply

* [PATCH] Beautifulise git-show output
From: beber.mailing @ 2006-07-04 22:34 UTC (permalink / raw)
  To: git; +Cc: Bertrand Jacquin

From: Bertrand Jacquin (Beber) <beber.mailing@gmail.com>

diff --git a/log-tree.c b/log-tree.c
index ebb49f2..55f77ad 100644
--- a/log-tree.c
+++ b/log-tree.c
@@ -164,7 +164,7 @@ int log_tree_diff_flush(struct rev_info 
 	}
 
 	if (opt->loginfo && !opt->no_commit_id)
-		show_log(opt, opt->loginfo, opt->diffopt.with_stat ? "---\n" : "\n");
+		show_log(opt, opt->loginfo, opt->diffopt.with_stat ? "\n---\n" : "\n");
 	diff_flush(&opt->diffopt);
 	return 1;
 }
-- 
1.4.1

^ permalink raw reply related

* Experimental "git prune"
From: Linus Torvalds @ 2006-07-04 22:41 UTC (permalink / raw)
  To: Junio C Hamano, Git Mailing List


This is an example of how "git prune" could be speeded up a lot.

This needs the builtin magic to actually enable it, and the "printf" needs 
to be made a real unlink, but as far as I can tell it actually works.

Comments?

		Linus

----
/*
 * builtin-prune.c
 */
#include "cache.h"
#include "refs.h"
#include "tag.h"
#include "commit.h"
#include "tree.h"
#include "blob.h"
#include "tree-walk.h"
#include "diff.h"
#include "revision.h"
#include "builtin.h"
#include "cache-tree.h"

static struct rev_info revs;

static int prune_object(char *path, const char *filename, const unsigned char *sha1)
{
	printf("%s/%s should be pruned\n", path, filename);
	return 0;
}

static int prune_dir(int i, char *path)
{
	DIR *dir = opendir(path);
	struct dirent *de;

	if (!dir)
		return 0;

	while ((de = readdir(dir)) != NULL) {
		char name[100];
		unsigned char sha1[20];
		int len = strlen(de->d_name);

		switch (len) {
		case 2:
			if (de->d_name[1] != '.')
				break;
		case 1:
			if (de->d_name[0] != '.')
				break;
			continue;
		case 38:
			sprintf(name, "%02x", i);
			memcpy(name+2, de->d_name, len+1);
			if (get_sha1_hex(name, sha1) < 0)
				break;

			/*
			 * Do we know about this object?
			 * It must have been reachable
			 */
			if (lookup_object(sha1))
				continue;

			prune_object(path, de->d_name, sha1);
			continue;
		}
		fprintf(stderr, "bad sha1 file: %s/%s\n", path, de->d_name);
	}
	closedir(dir);
	return 0;
}

static void prune_object_dir(const char *path)
{
	int i;
	for (i = 0; i < 256; i++) {
		static char dir[4096];
		sprintf(dir, "%s/%02x", path, i);
		prune_dir(i, dir);
	}
}

static void process_blob(struct blob *blob,
			 struct object_array *p,
			 struct name_path *path,
			 const char *name)
{
	struct object *obj = &blob->object;

	if (obj->flags & SEEN)
		return;
	obj->flags |= SEEN;
	/* Nothing to do, really .. The blob lookup was the important part */
}

static void process_tree(struct tree *tree,
			 struct object_array *p,
			 struct name_path *path,
			 const char *name)
{
	struct object *obj = &tree->object;
	struct tree_desc desc;
	struct name_entry entry;
	struct name_path me;

	if (obj->flags & SEEN)
		return;
	obj->flags |= SEEN;
	if (parse_tree(tree) < 0)
		die("bad tree object %s", sha1_to_hex(obj->sha1));
	name = strdup(name);
	add_object(obj, p, path, name);
	me.up = path;
	me.elem = name;
	me.elem_len = strlen(name);

	desc.buf = tree->buffer;
	desc.size = tree->size;

	while (tree_entry(&desc, &entry)) {
		if (S_ISDIR(entry.mode))
			process_tree(lookup_tree(entry.sha1), p, &me, entry.path);
		else
			process_blob(lookup_blob(entry.sha1), p, &me, entry.path);
	}
	free(tree->buffer);
	tree->buffer = NULL;
}

static void process_tag(struct tag *tag, struct object_array *p, const char *name)
{
	struct object *obj = &tag->object;
	struct name_path me;

	if (obj->flags & SEEN)
		return;
	obj->flags |= SEEN;

	me.up = NULL;
	me.elem = "tag:/";
	me.elem_len = 5;

	if (parse_tag(tag) < 0)
		die("bad tag object %s", sha1_to_hex(obj->sha1));
	add_object(tag->tagged, p, NULL, name);
}

static void walk_commit_list(struct rev_info *revs)
{
	int i;
	struct commit *commit;
	struct object_array objects = { 0, 0, NULL };

	/* Walk all commits, process their trees */
	while ((commit = get_revision(revs)) != NULL)
		process_tree(commit->tree, &objects, NULL, "");

	/* Then walk all the pending objects, recursively processing them too */
	for (i = 0; i < revs->pending.nr; i++) {
		struct object_array_entry *pending = revs->pending.objects + i;
		struct object *obj = pending->item;
		const char *name = pending->name;
		if (obj->type == TYPE_TAG) {
			process_tag((struct tag *) obj, &objects, name);
			continue;
		}
		if (obj->type == TYPE_TREE) {
			process_tree((struct tree *)obj, &objects, NULL, name);
			continue;
		}
		if (obj->type == TYPE_BLOB) {
			process_blob((struct blob *)obj, &objects, NULL, name);
			continue;
		}
		die("unknown pending object %s (%s)", sha1_to_hex(obj->sha1), name);
	}
}

static int add_one_ref(const char *path, const unsigned char *sha1)
{
	struct object *object = parse_object(sha1);
	if (!object)
		die("bad object ref: %s:%s", path, sha1_to_hex(sha1));
	add_pending_object(&revs, object, "");
	return 0;        
}

static void add_one_tree(const unsigned char *sha1)
{
	struct tree *tree = lookup_tree(sha1);
	add_pending_object(&revs, &tree->object, "");
}

static void add_cache_tree(struct cache_tree *it)
{
	int i;

	if (it->entry_count >= 0)
		add_one_tree(it->sha1);
	for (i = 0; i < it->subtree_nr; i++)
		add_cache_tree(it->down[i]->cache_tree);
}

static void add_cache_refs(void)
{
	int i;

 	read_cache();
	for (i = 0; i < active_nr; i++) {
		lookup_blob(active_cache[i]->sha1);
		/*
		 * We could add the blobs to the pending list, but quite
		 * frankly, we don't care. Once we've looked them up, and
		 * added them as objects, we've really done everything 
		 * there is to do for a blob
		 */
	}
	if (active_cache_tree)
		add_cache_tree(active_cache_tree);
}

int cmd_prune(int argc, const char **argv, char **envp)
{
	/*
	 * Set up revision parsing, and mark us as being interested
	 * in all object types, not just commits.
	 */
	init_revisions(&revs);
	revs.tag_objects = 1;
	revs.blob_objects = 1;
	revs.tree_objects = 1;

	/* Add all external refs */
	for_each_ref(add_one_ref);

	/* Add all refs from the index file */
	add_cache_refs();

	/*
	 * Set up the revision walk - this will move all commits
	 * from the pending list to the commit walking list.
	 */
	prepare_revision_walk(&revs);

	walk_commit_list(&revs);

	prune_object_dir(get_object_directory());

	return 0;
}

^ permalink raw reply

* Re: [PATCH] Additional merge-base tests
From: Junio C Hamano @ 2006-07-04 22:42 UTC (permalink / raw)
  To: Johannes Schindelin; +Cc: git
In-Reply-To: <Pine.LNX.4.63.0607050021330.29667@wbgn013.biozentrum.uni-wuerzburg.de>

Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:

> If that should be not true, you always could rely on topo order. Which 
> does not seem to solve the problem for you.

The computation of merge-base is about computing topo order
cheaply, so that is a recursive definition of the problem, not a
solution, I am afraid.  

With the generation counter, we know the clean-up phase needs to
parse and traverse unparsed parents with the same or higher
generation counter than the lowest we have in the result list,
which would limit our clean-up traversal.  In order to look at
the generation number of parent, we would need to parse it, so
we would end up parsing one level more than needed at the edge,
though.

^ permalink raw reply

* Re: [PATCH] Beautifulise git-show output
From: Junio C Hamano @ 2006-07-04 22:51 UTC (permalink / raw)
  To: beber.mailing; +Cc: git
In-Reply-To: <11520525682686-git-send-email-beber.mailing@gmail.com>

Why?

A patch like this needs to be justified with a bit more
explanation; the word "beautiful" is subjective.

(current)
	Change this and that file

        Signed-off-by: A U Thor <a.u.thor@example.com>
	---
         this-file |   20 +++++++----
	 that-file |    4 ++++
	 2 files changed, 20 insertions(+), 4 deletions(-)

        diff --git a/this-file b/this-file
	...
 
(yours -- and I think 1.3.0 did it like this)
	Change this and that file

        Signed-off-by: A U Thor <a.u.thor@example.com>

	---
         this-file |   20 +++++++----
	 that-file |    4 ++++
	 2 files changed, 20 insertions(+), 4 deletions(-)

        diff --git a/this-file b/this-file
	...
 
It _might_ be easier to read if it were like this, though:
 
	Change this and that file

        Signed-off-by: A U Thor <a.u.thor@example.com>
	---

         this-file |   20 +++++++----
	 that-file |    4 ++++
	 2 files changed, 20 insertions(+), 4 deletions(-)

        diff --git a/this-file b/this-file
	...

However, the screen real estate, especially in the vertical
direction, is a scarce resource; I do not think the three-dash
is a too weak visual separator that needs to be helped by an
extra newline.

^ permalink raw reply

* Re: Experimental "git prune"
From: Junio C Hamano @ 2006-07-04 22:55 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: git
In-Reply-To: <Pine.LNX.4.64.0607041539550.12404@g5.osdl.org>

Linus Torvalds <torvalds@osdl.org> writes:

> This is an example of how "git prune" could be speeded up a lot.

Ah, you are avoiding the verification cost of fsck-objects.  Neat.

^ permalink raw reply

* Re: [PATCH] Beautifulise git-show output
From: Bertrand Jacquin @ 2006-07-04 22:59 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git
In-Reply-To: <7vejx1f0fz.fsf@assigned-by-dhcp.cox.net>

On 7/5/06, Junio C Hamano <junkio@cox.net> wrote:
> Why?
>
> A patch like this needs to be justified with a bit more
> explanation; the word "beautiful" is subjective.

Arg, git-send-email seems to made a bad job after git-format-patch, sorry.

So explanation don't go here. So here it is :
Git-show actually show (for example) :

    Makefile: Create Makefile for Beamer theme
    rules are : install & uninstall (be careful on this one)

    Also, I hacked presentation oral's Makefile to check them presence or not
---

 docs/presentation_oral/Makefile        |    5 +-
 docs/presentation_oral/themes/Makefile |   91 ++++++++++++++++++++++++++++++++
 2 files changed, 95 insertions(+), 1 deletions(-)
 create mode 100644 docs/presentation_oral/themes/Makefile

I would like to have a newline after commit mesage too as there is one
before diff-stat.

-- 
# Beber : beber@gna.org
# IM : beber@jabber.fr
# http://guybrush.ath.cx, irc://irc.freenode.net/#{e.fr,gentoofr}

^ permalink raw reply

* Re: [PATCH] Additional merge-base tests
From: A Large Angry SCM @ 2006-07-04 23:07 UTC (permalink / raw)
  To: Johannes Schindelin, git; +Cc: Junio C Hamano
In-Reply-To: <Pine.LNX.4.63.0607050021330.29667@wbgn013.biozentrum.uni-wuerzburg.de>

Johannes Schindelin wrote:
> Hi,
> 
> On Tue, 4 Jul 2006, Junio C Hamano wrote:
> 
>> Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:
>>
>>> We could introduce a time.maximumSkew variable, and just walk only 
>>> that much further when traversing the commits.
>> We could have had "commit generation number" in the commit
>> object header, and use that instead of commit timestamps for
>> these traversal purposes.  The generation number for a commit is
>> defined to be max(generation number of its parents)+1 and we
>> prime the recursive this definition by defining the generation
>> number for the root commit to be one.
> 
> Are you really, really sure this is a remedy? I, for one, am quite sure of 
> the opposite. What you propose is just another time scale, only this time, 
> it is not universally true (not even minus local incompetence to keep the 
> clock accurate).

It works[*] and it does what using the timestamp was trying to do. 
Namely, work from "more recent" (or "closer") commits toward "older" (or 
"farther") commits until you've gone past the point you care about.

It's a little late to be changing the structure of a commit and you'd 
have to deal with some size/scale issues, but it's do-able. A better 
idea may be to generate and keep the generation number on a per 
repository basis, and you'd be able to work around changing grafts.

[*] Grafts do _really_ nasty things to this. Just like clock skew does now.

^ permalink raw reply

* Re: [PATCH] Additional merge-base tests
From: Jakub Narebski @ 2006-07-04 23:14 UTC (permalink / raw)
  To: git
In-Reply-To: <44AAF49F.6090008@gmail.com>

A Large Angry SCM wrote:

> It works[*] and it does what using the timestamp was trying to do. 
> Namely, work from "more recent" (or "closer") commits toward "older" (or 
> "farther") commits until you've gone past the point you care about.
> 
> It's a little late to be changing the structure of a commit and you'd 
> have to deal with some size/scale issues, but it's do-able. A better 
> idea may be to generate and keep the generation number on a per 
> repository basis, and you'd be able to work around changing grafts.

What about timestamp = MAX(now(), timestamps of parents) idea, which
doesn't need changing the structure of a commit?

-- 
Jakub Narebski
Warsaw, Poland
ShadeHawk on #git

^ permalink raw reply

* Re: [PATCH] Additional merge-base tests
From: Junio C Hamano @ 2006-07-04 23:39 UTC (permalink / raw)
  To: jnareb; +Cc: git
In-Reply-To: <e8esnn$mb5$1@sea.gmane.org>

Jakub Narebski <jnareb@gmail.com> writes:

> What about timestamp = MAX(now(), timestamps of parents) idea, which
> doesn't need changing the structure of a commit?

It changes the semantics without change syntax, which is not any
better (and in fact I think it is worse).

^ permalink raw reply

* Re: [PATCH] Additional merge-base tests
From: Junio C Hamano @ 2006-07-05  0:24 UTC (permalink / raw)
  To: gitzilla, Johannes Schindelin; +Cc: git
In-Reply-To: <44AAF49F.6090008@gmail.com>

A Large Angry SCM <gitzilla@gmail.com> writes:

>
> It works[*] and it does what using the timestamp was trying to
> do. Namely, work from "more recent" (or "closer") commits toward
> "older" (or "farther") commits until you've gone past the point you
> care about.

If you really really care, now we have clear_commit_marks() with
get_merge_bases() infrastructure in, you _could_ run another
round of get_merge_bases() on the commit on the result list to
see which ones are reachable from others by performing an
equivalent of fast-forward/already-up-to-date check.

^ permalink raw reply

* Re: [PATCH] Additional merge-base tests
From: A Large Angry SCM @ 2006-07-05  0:26 UTC (permalink / raw)
  To: Jakub Narebski, git
In-Reply-To: <e8esnn$mb5$1@sea.gmane.org>

Jakub Narebski wrote:
> A Large Angry SCM wrote:
> 
>> It works[*] and it does what using the timestamp was trying to do. 
>> Namely, work from "more recent" (or "closer") commits toward "older" (or 
>> "farther") commits until you've gone past the point you care about.
>>
>> It's a little late to be changing the structure of a commit and you'd 
>> have to deal with some size/scale issues, but it's do-able. A better 
>> idea may be to generate and keep the generation number on a per 
>> repository basis, and you'd be able to work around changing grafts.
> 
> What about timestamp = MAX(now(), timestamps of parents) idea, which
> doesn't need changing the structure of a commit?
> 

So, do you really want your name as committer on a commit with a date 
300 years in the future because one of the parents had a bad date?

^ permalink raw reply

* [PATCH] Additional merge-base tests (revised)
From: A Large Angry SCM @ 2006-07-05  0:35 UTC (permalink / raw)
  To: Junio C Hamano, git

Signed-off-by: A Large Angry SCM <gitzilla@gmail.com>
---
This demonstrates a problem with git-merge-base.

This is a slightly revised version of the same patch as before.

 t/t6010-merge-base.sh |   45 +++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 45 insertions(+)

diff --git a/t/t6010-merge-base.sh b/t/t6010-merge-base.sh
index 1dce123..2b7b51c 100755
--- a/t/t6010-merge-base.sh
+++ b/t/t6010-merge-base.sh
@@ -44,6 +44,43 @@ A=$(doit 1 A $B)
 G=$(doit 7 G $B $E)
 H=$(doit 8 H $A $F)
 
+# Setup for second test to demonstrate that relying on timestamps in a
+# distributed SCM to provide a _consistent_ partial ordering of commits
+# leads to insanity.
+#
+#               Relative
+# Structure     timestamps
+#
+#   PL  PR        +4  +4
+#  /  \/  \      /  \/  \
+# L2  C2  R2    +3  -1  +3
+# |   |   |     |   |   |
+# L1  C1  R1    +2  -2  +2
+# |   |   |     |   |   |
+# L0  C0  R0    +1  -3  +1
+#   \ |  /        \ |  /
+#     S             0
+#
+# The left and right chains of commits can be of any length and complexity as
+# long as all of the timestamps are greater than that of S.
+
+S=$(doit  0 S)
+
+C0=$(doit -3 C0 $S)
+C1=$(doit -2 C1 $C0)
+C2=$(doit -1 C2 $C1)
+
+L0=$(doit  1 L0 $S)
+L1=$(doit  2 L1 $L0)
+L2=$(doit  3 L2 $L1)
+
+R0=$(doit  1 R0 $S)
+R1=$(doit  2 R1 $R0)
+R2=$(doit  3 R2 $R1)
+
+PL=$(doit  4 PL $L2 $C2)
+PR=$(doit  4 PR $C2 $R2)
+
 test_expect_success 'compute merge-base (single)' \
     'MB=$(git-merge-base G H) &&
      expr "$(git-name-rev "$MB")" : "[0-9a-f]* tags/B"'
@@ -56,4 +93,12 @@ test_expect_success 'compute merge-base 
     'MB=$(git-show-branch --merge-base G H) &&
      expr "$(git-name-rev "$MB")" : "[0-9a-f]* tags/B"'
 
+test_expect_success 'compute merge-base (single)' \
+    'MB=$(git-merge-base PL PR) &&
+     expr "$(git-name-rev "$MB")" : "[0-9a-f]* tags/C2"'
+
+test_expect_success 'compute merge-base (all)' \
+    'MB=$(git-merge-base --all PL PR) &&
+     expr "$(git-name-rev "$MB")" : "[0-9a-f]* tags/C2"'
+
 test_done

^ permalink raw reply related

* Re: [PATCH] Additional merge-base tests
From: Junio C Hamano @ 2006-07-05  0:59 UTC (permalink / raw)
  To: git
In-Reply-To: <7vpsgllsnp.fsf@assigned-by-dhcp.cox.net>

Junio C Hamano <junkio@cox.net> writes:

> It may be interesting to run tests on real merges (I believe the
> kernel repository has a handful merges that have more than one
> merge bases) to see how effective the current clean-up pass is.
> It may turn out to be ineffective in practice, in which case we
> could kill it off.

So I counted.

There are 23 commits in the kernel history that have more than
one merge-bases.  The current merge-base code tells us that all
of them have two merge-bases.

None of them suffers from the horizon effect; the two bases
are not ancestor/descendant of each other.

A good news is that get_merge_bases() gives the same answer
without the clean-up pass mark_reachable_commits().

d0e5f39f1ee2e55d140064bb6d74c8bad25d71d0
361ea93cbff0e42cbc6a0f3c7a8238db9ed15648
4b2d9cf00962d0a0e697f887f3ecaa155cbde555
ba9b28d19a3251bb1dfe6a6f8cc89b96fb85f683
db21e578e551421d76641d72cb3f8296ed3f9e61
b425c8c5922562c562dc55a636c3c8d758ed6d17
2e9ff56efbc005ab2b92b68df65940c7459446c6
75e47b36004d136edff68295420424cba3a5ccd0
c45ae87ec9d03c9adfc466a6b560cb38b154813a
09e4f9029da1b53e835555c353a89c36b71233b0
0b310f36d7d96e27f6941ec0f9b95e15142f1e78
db9ace7083dbdcc3d02bdd6a1d26132c80b5b726
80c7af4074cbb4cb6be5d35c443ea6d5e8838a84
701db69d6647f61e4660c9102d7f2fd5dffc203d
5e3c2b95dd560baa41b08c8f5f00bbd6fbeebdcb
c7fb577e2a6cb04732541f2dc402bd46747f7558
ba9b543d5bec0a7605952e2ba501fb8b0f3b6407
84ffa747520edd4556b136bdfc9df9eb1673ce12
da28c12089dfcfb8695b6b555cdb8e03dda2b690
3190186362466658f01b2e354e639378ce07e1a9
0c168775709faa74c1b87f1e61046e0c51ade7f3
0e396ee43e445cb7c215a98da4e76d0ce354d9d7
467ca22d3371f132ee225a5591a1ed0cd518cb3d

^ permalink raw reply

* merge-base: update the clean-up postprocessing
From: Junio C Hamano @ 2006-07-05  2:07 UTC (permalink / raw)
  To: A Large Angry SCM; +Cc: git
In-Reply-To: <44AB0948.9070606@gmail.com>

This is "for concepts" only -- it still seems to have bugs
somewhere to break other tests, although it passes your new
tests.
-- >8 --
This removes the "contaminate the well even more" approach
taken in the current merge-base postprosessing code.  Instead,
when there are more than one merge-base results, we compute the
merge-base between them and see if one is a fast-forward of the
other, in which case the ancestor is removed from the result.

Signed-off-by: Junio C Hamano <junkio@cox.net>
---

 * This is on top of Johannes/Rene's merge-base work (in "next").

 commit.c |  279 ++++++++++++++++++++------------------------------------------
 1 files changed, 89 insertions(+), 190 deletions(-)

diff --git a/commit.c b/commit.c
index c6bf10d..1bd6dca 100644
--- a/commit.c
+++ b/commit.c
@@ -854,6 +854,7 @@ void sort_in_topological_order_fn(struct
 #define PARENT1		(1u<< 8)
 #define PARENT2		(1u<< 9)
 #define STALE		(1u<<10)
+#define RESULT		(1u<<11)
 
 static struct commit *interesting(struct commit_list *list)
 {
@@ -867,183 +868,42 @@ static struct commit *interesting(struct
 	return NULL;
 }
 
-/*
- * A pathological example of how this thing works.
- *
- * Suppose we had this commit graph, where chronologically
- * the timestamp on the commit are A <= B <= C <= D <= E <= F
- * and we are trying to figure out the merge base for E and F
- * commits.
- *
- *                  F
- *                 / \
- *            E   A   D
- *             \ /   /
- *              B   /
- *               \ /
- *                C
- *
- * First we push E and F to list to be processed.  E gets bit 1
- * and F gets bit 2.  The list becomes:
- *
- *     list=F(2) E(1), result=empty
- *
- * Then we pop F, the newest commit, from the list.  Its flag is 2.
- * We scan its parents, mark them reachable from the side that F is
- * reachable from, and push them to the list:
- *
- *     list=E(1) D(2) A(2), result=empty
- *
- * Next pop E and do the same.
- *
- *     list=D(2) B(1) A(2), result=empty
- *
- * Next pop D and do the same.
- *
- *     list=C(2) B(1) A(2), result=empty
- *
- * Next pop C and do the same.
- *
- *     list=B(1) A(2), result=empty
- *
- * Now it is B's turn.  We mark its parent, C, reachable from B's side,
- * and push it to the list:
- *
- *     list=C(3) A(2), result=empty
- *
- * Now pop C and notice it has flags==3.  It is placed on the result list,
- * and the list now contains:
- *
- *     list=A(2), result=C(3)
- *
- * We pop A and do the same.
- *
- *     list=B(3), result=C(3)
- *
- * Next, we pop B and something very interesting happens.  It has flags==3
- * so it is also placed on the result list, and its parents are marked
- * stale, retroactively, and placed back on the list:
- *
- *    list=C(7), result=C(7) B(3)
- *
- * Now, list does not have any interesting commit.  So we find the newest
- * commit from the result list that is not marked stale.  Which is
- * commit B.
- *
- *
- * Another pathological example how this thing used to fail to mark an
- * ancestor of a merge base as STALE before we introduced the
- * postprocessing phase (mark_reachable_commits).
- *
- *		  2
- *		  H
- *	    1    / \
- *	    G   A   \
- *	    |\ /     \
- *	    | B       \
- *	    |  \       \
- *	     \  C       F
- *	      \  \     /
- *	       \  D   /
- *		\ |  /
- *		 \| /
- *		  E
- *
- *	 list			A B C D E F G H
- *	 G1 H2			- - - - - - 1 2
- *	 H2 E1 B1		- 1 - - 1 - 1 2
- *	 F2 E1 B1 A2		2 1 - - 1 2 1 2
- *	 E3 B1 A2		2 1 - - 3 2 1 2
- *	 B1 A2			2 1 - - 3 2 1 2
- *	 C1 A2			2 1 1 - 3 2 1 2
- *	 D1 A2			2 1 1 1 3 2 1 2
- *	 A2			2 1 1 1 3 2 1 2
- *	 B3			2 3 1 1 3 2 1 2
- *	 C7			2 3 7 1 3 2 1 2
- *
- * At this point, unfortunately, everybody in the list is
- * stale, so we fail to complete the following two
- * steps to fully marking stale commits.
- *
- *	 D7			2 3 7 7 3 2 1 2
- *	 E7			2 3 7 7 7 2 1 2
- *
- * and we ended up showing E as an interesting merge base.
- * The postprocessing phase re-injects C and continues traversal
- * to contaminate D and E.
- */
-
-static void mark_reachable_commits(struct commit_list *result,
-				   struct commit_list *list)
-{
-	struct commit_list *tmp;
-
-	/*
-	 * Postprocess to fully contaminate the well.
-	 */
-	for (tmp = result; tmp; tmp = tmp->next) {
-		struct commit *c = tmp->item;
-		/* Reinject stale ones to list,
-		 * so we can scan their parents.
-		 */
-		if (c->object.flags & STALE)
-			commit_list_insert(c, &list);
-	}
-	while (list) {
-		struct commit *c = list->item;
-		struct commit_list *parents;
-
-		tmp = list;
-		list = list->next;
-		free(tmp);
-
-		/* Anything taken out of the list is stale, so
-		 * mark all its parents stale.  We do not
-		 * parse new ones (we already parsed all the relevant
-		 * ones).
-		 */
-		parents = c->parents;
-		while (parents) {
-			struct commit *p = parents->item;
-			parents = parents->next;
-			if (!(p->object.flags & STALE)) {
-				p->object.flags |= STALE;
-				commit_list_insert(p, &list);
-			}
-		}
-	}
-}
-
-struct commit_list *get_merge_bases(struct commit *rev1, struct commit *rev2,
-                                    int cleanup)
+static struct commit_list *merge_bases(struct commit *one, struct commit *two)
 {
 	struct commit_list *list = NULL;
 	struct commit_list *result = NULL;
-	struct commit_list *tmp = NULL;
 
-	if (rev1 == rev2)
-		return commit_list_insert(rev1, &result);
+	if (one == two)
+		/* We do not mark this even with RESULT so we do not
+		 * have to clean it up.
+		 */
+		return commit_list_insert(one, &result);
 
-	parse_commit(rev1);
-	parse_commit(rev2);
+	parse_commit(one);
+	parse_commit(two);
 
-	rev1->object.flags |= PARENT1;
-	rev2->object.flags |= PARENT2;
-	insert_by_date(rev1, &list);
-	insert_by_date(rev2, &list);
+	one->object.flags |= PARENT1;
+	two->object.flags |= PARENT2;
+	insert_by_date(one, &list);
+	insert_by_date(two, &list);
 
 	while (interesting(list)) {
-		struct commit *commit = list->item;
+		struct commit *commit;
 		struct commit_list *parents;
-		int flags = commit->object.flags
-			& (PARENT1 | PARENT2 | STALE);
+		struct commit_list *n;
+		int flags;
 
-		tmp = list;
-		list = list->next;
-		free(tmp);
-		if (flags == (PARENT1 | PARENT2)) {
-			insert_by_date(commit, &result);
+		commit = list->item;
+		n = list->next;
+		free(list);
+		list = n;
 
+		flags = commit->object.flags & (PARENT1 | PARENT2 | STALE);
+		if (flags == (PARENT1 | PARENT2)) {
+			if (!(commit->object.flags & RESULT)) {
+				commit->object.flags |= RESULT;
+				insert_by_date(commit, &result);
+			}
 			/* Mark parents of a found merge stale */
 			flags |= STALE;
 		}
@@ -1059,35 +919,74 @@ struct commit_list *get_merge_bases(stru
 		}
 	}
 
-	if (!result)
-		goto finish;
-
-	if (result->next && list)
-		mark_reachable_commits(result, list);
+	/* Clean up the result to remove stale ones */
+	list = result; result = NULL;
+	while (list) {
+		struct commit_list *n = list->next;
+		if (!(list->item->object.flags & STALE))
+			insert_by_date(list->item, &result);
+		free(list);
+		list = n;
+	}
+	return result;
+}
 
-	/* cull duplicates */
-	for (tmp = result, list = NULL; tmp; ) {
-		struct commit *commit = tmp->item;
-		struct commit_list *next = tmp->next;
-		if (commit->object.flags & STALE) {
-			if (list != NULL)
-				list->next = next;
-			free(tmp);
-		} else {
-			if (list == NULL)
-				result = tmp;
-			list = tmp;
-			commit->object.flags |= STALE;
+struct commit_list *get_merge_bases(struct commit *one,
+				    struct commit *two,
+                                    int cleanup)
+{
+	struct commit_list *result = merge_bases(one, two);
+	struct commit_list *list;
+	struct commit **rslt;
+	unsigned all_flags = (PARENT1 | PARENT2 | STALE | RESULT);
+	int cnt, i, j;
+
+	if (one == two)
+		return result;
+	if (!result || !result->next) {
+		if (cleanup) {
+			clear_commit_marks(one, all_flags);
+			clear_commit_marks(two, all_flags);
 		}
-
-		tmp = next;
+		return result;
 	}
 
- finish:
-	if (cleanup) {
-		clear_commit_marks(rev1, PARENT1 | PARENT2 | STALE);
-		clear_commit_marks(rev2, PARENT1 | PARENT2 | STALE);
+	/* There are more than one */
+	cnt = 0;
+	list = result;
+	while (list) {
+		list = list->next;
+		cnt++;
+	}
+	rslt = xcalloc(cnt, sizeof(*rslt));
+	for (list = result, i = 0; list; list = list->next)
+		rslt[i] = list->item;
+	free_commit_list(result);
+
+	clear_commit_marks(one, all_flags);
+	clear_commit_marks(two, all_flags);
+	for (i = 0; i < cnt - 1; i++) {
+		for (j = i+1; j < cnt; j++) {
+			if (!rslt[i] || !rslt[j])
+				continue;
+			result = merge_bases(rslt[i], rslt[j]);
+			clear_commit_marks(rslt[i], all_flags);
+			clear_commit_marks(rslt[j], all_flags);
+			for (list = result; list; list = list->next) {
+				if (rslt[i] == list->item)
+					rslt[i] = NULL;
+				if (rslt[j] == list->item)
+					rslt[j] = NULL;
+			}
+		}
 	}
 
+	/* Surviving ones in rslt[] are the independent results */
+	result = NULL;
+	for (i = 0; i < cnt; i++) {
+		if (rslt[i])
+			insert_by_date(rslt[i], &result);
+	}
+	free(rslt);
 	return result;
 }
-- 
1.4.1.g7993

^ permalink raw reply related

* Re: git-fetch per-repository speed issues
From: Jeff King @ 2006-07-05  6:47 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: Git Mailing List
In-Reply-To: <Pine.LNX.4.64.0607032007290.12404@g5.osdl.org>

On Mon, Jul 03, 2006 at 08:07:49PM -0700, Linus Torvalds wrote:

> > Fetching by ssh actually makes two ssh connections (the second is to
> > grab tags).
> True. Although that should happen only if there are any new tags.

Either you're wrong or there's a bug in git-fetch. 

I think you're missing the call to git-ls-remote --tags to get the list
of tags (which we will then auto-follow if necessary). So in that case,
there would actually be 3 ssh connections. If everything is up to date,
we still make 2 connections (one to check refs from remotes file, and
one to check remote tag list).

-Peff

^ permalink raw reply

* Strange date format in git-send-email
From: Martijn Kuipers @ 2006-07-05  7:17 UTC (permalink / raw)
  To: git

Dear list,

My email is sorted by date and a number of email-patches list the date format 
as unknown (in kmail, that is).

When checking the headers of these mails I see the following pattern:

Date: mer, 05 jui 2006 00:36:08 +0200
X-Mailer: git-send-email 1.4.1

Date: wto, 20 cze 2006 17:59:19 +0200
X-Mailer: git-send-email 1.3.0

Date: Tue, Mar 14 12:12:35 2006 -0500
User-Agent: send_patch 0.1

Date: Tue Feb 7 18:21:02 2006 +0100


Some of these are quite old, and it has been sometime since I last noticed it 
(I actually thought it was fixed). But today I received another patch-email 
from the list ([PATCH] Beautifulise git-show output), which showed the same 
problem.

Is this my problem (or kmail), or is there something funny with 
git-send-email? I just don't git it.

If you need more info, just holler.

Kind regards,
Martijn
----------------------------------------------------------------------------------------------
Actually, did actually notice actually how many times non-native English 
speaker actually use actually?

^ permalink raw reply

* Re: merge-base: update the clean-up postprocessing
From: Johannes Schindelin @ 2006-07-05  7:50 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: A Large Angry SCM, git
In-Reply-To: <7vy7v8dctz.fsf@assigned-by-dhcp.cox.net>

Hi,

On Tue, 4 Jul 2006, Junio C Hamano wrote:

> This is "for concepts" only -- it still seems to have bugs
> somewhere to break other tests, although it passes your new
> tests.

Doesn't this introduce a nasty O(n*m) performance (where m is the 
number of merge bases, and n the number of traversed commits)? I think 
possibly many commits are traversed multiple times.

BTW ALAS' argument about grafts not only shot down my maximumSkew, but 
AFAICT also the generation number thing. Besides, the generation number 
could be manipulated by a mean-spirited person also.

Ciao,
Dscho

^ permalink raw reply

* Re: merge-base: update the clean-up postprocessing
From: Junio C Hamano @ 2006-07-05  7:51 UTC (permalink / raw)
  To: A Large Angry SCM; +Cc: git
In-Reply-To: <7vy7v8dctz.fsf@assigned-by-dhcp.cox.net>

A fixed up version of this patch, along with your updated test,
is at the tip of "pu".

It does affect the processing time for cases where there are
more than one merge bases negatively.  To compute all merge-base
for the 23 merges in the kernel reporitory, the old code with
the "contaminate the well a bit more" clean-up phase takes 2.5
seconds, while the new code takes 3.9 seconds.

Processing all 2215 merges in the kernel repository (the other
2192 merges have one merge-base between the parents) takes 160
seconds either way.  In other words, multi merge-base merges are
relatively rare and a bit more time spent to clean-up with the
new code is lost in the noise.

The numbers are taken from /usr/bin/time on an Athron 64X2 3800.

^ permalink raw reply

* Re: [PATCH] Additional merge-base tests
From: Johannes Schindelin @ 2006-07-05  7:56 UTC (permalink / raw)
  To: A Large Angry SCM; +Cc: git, Junio C Hamano
In-Reply-To: <44AAF49F.6090008@gmail.com>

Hi,

On Tue, 4 Jul 2006, A Large Angry SCM wrote:

> Johannes Schindelin wrote:
> > Hi,
> > 
> > On Tue, 4 Jul 2006, Junio C Hamano wrote:
> > 
> > > Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:
> > > 
> > > > We could introduce a time.maximumSkew variable, and just walk only that
> > > > much further when traversing the commits.
> > > We could have had "commit generation number" in the commit
> > > object header, and use that instead of commit timestamps for
> > > these traversal purposes.  The generation number for a commit is
> > > defined to be max(generation number of its parents)+1 and we
> > > prime the recursive this definition by defining the generation
> > > number for the root commit to be one.
> > 
> > Are you really, really sure this is a remedy? I, for one, am quite sure of
> > the opposite. What you propose is just another time scale, only this time,
> > it is not universally true (not even minus local incompetence to keep the
> > clock accurate).
> 
> It works[*] and it does what using the timestamp was trying to do. Namely,
> work from "more recent" (or "closer") commits toward "older" (or "farther")
> commits until you've gone past the point you care about.
> 
> It's a little late to be changing the structure of a commit and you'd have to
> deal with some size/scale issues, but it's do-able. A better idea may be to
> generate and keep the generation number on a per repository basis, and you'd
> be able to work around changing grafts.

Like, inside the cache? I dunno. IMHO it is way too late to change the 
structure of a commit in that particular manner, _plus_ you would get 
overflow issues.

> [*] Grafts do _really_ nasty things to this. Just like clock skew does now.

Grafts can do much nastier things to you, for example having a circular 
history. _But_ they cannot do that nasty thing outside of your repo. Clock 
skews can.

Ciao,
Dscho

^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox