Re: More gitweb queries..

From: Thomas Glanzmann <sithglan@stud.uni-erlangen.de>
Date: 2005-05-30 18:36:53
Hello,

[ => Skip till next ']' if you want because my approach doesn't work out
for all cases in the optimal way.

> "An empty tree (no HEAD)"?  Is your definition of "an empty
> tree" the same as "empty" directory after you do "mkdir empty &&
> cd empty && git-init-db", followed by bunch of git-*-pull to get
> the objects and commits from other reposititories being involved
> in the merge but without touching .git/HEAD?

Yep. In practice it isn't anything else than just using the first
'remote' HEAD as 'local' HEAD if there is no 'local' HEAD. But for merge
this doesn't really matter.

> If so, why cannot I do the git-*-pull from multiple repositories and
> merge them together?  Why "there is only one head in this array that
> is remote_head"?  Oh, I guess I am missing your definition of
> "remote_head".  Puzzled...

My intention by writing this note was to clear things up. That it also
works for cases where you do the 'initial clone' for one and multiple
remotes.

> Anyhow I presume that if your ${GIT-.git}/HEAD exists, you
> include it as the first element of MERGE_HEADS.

Affirmative.

> TG> I have a function merge which gets a sorted array of heads. Heads can be
> TG> unlimited at the time because some of the heads can be included into
> TG> other heads (they're a subset) and so they don't show up in the commit
> TG> object. I call this array MERGE_HEADS.

Here is a typo: MERGE_HEADS is *not* sorted. But it is 'ordered'.

> Sorry I am not very good at this "thinking" thing, and I need to
> draw pictures.  Please bear with me.

Of course, I do.

>     (line of dev C)-------------C    We are here, trying to merge
>     (line of dev B)---(merge)---B    these three lines of devs:
>     (line of dev A)---A/             A, B and C

>     MERGE_HEADS = (A B C)
>     A is actually a "subset" of B

> Is this what you mean by "subset"?  Are these "subset" HEAD the
> only thing that causes fast forwards?

Exactly, but it has not to be a merge it also can be a linear
development. What matters that A is referenced in any way in the history
of B.

In this case where A is referenced in the history of B, we just discard
HEAD A, because it is already merged. So A will never show up in
git-commit-tree in one of its "-p" options. But I mention it in the
commit-text as 'there was nothing todo'.

If we take now your example and switch the order A and B we have

MERGE_HEADS = (B A C) and A is still in the history of B:

We do exactly the same here only that in the above scenario we have to
kick out the previous COMMIT_HEAD when processing B while we drop the
current COMMIT_HEAD when processing A in this scenario. So to clear
things up:

The HEAD we are working on is surrouned by '*'s.

MERGE_HEADS = (*B* A C) => COMMIT_HEADS = (B)
MERGE_HEADS = (B *A* C) => COMMIT_HEADS = (B) /* note: A never did it in COMMIT_HEADS because it was referenced in history of B */
MERGE_HEADS = (B A *C*) => COMMIT_HEADS = (B C)

while in the above example with your initial order it is:

MERGE_HEADS = (*A* B C) => COMMIT_HEADS = (A)
MERGE_HEADS = (A *B* C) => COMMIT_HEADS = (B) /* note: A is kicked out of COMMIT_HEADS ... see above */
MERGE_HEADS = (A B *C*) => COMMIT_HEADS = (B C) 

]

> My gut feeling without thinking much is that it might be easier
> to first cull such fast forward heads by using N-way rev-tree
> before you do anything else.  If only one head survives after
> that, then that head would be your new head and you do not have
> to go through any merges.  Otherwise you merge those independent
> heads without worrying about fast forwards.  How does that
> sound?

You're right. Because this would work out bad (unneccessary
automatic/threeway/manual merge) if we twist MERGE_HEADS again:

MERGE_HEADS = (*C* A B) => COMMIT_HEADS (C)
MERGE_HEADS = (C *A* B) => COMMIT_HEADS (C A) /* A stays in because it is not in the history of C; -> unneccessary merge */
MERGE_HEADS = (C A *B*) => COMMIT_HEADS (C A B)

Okay, so I have to elminate all fast forward conditions in the first
place? How do I do this:

foreach CURRENT_HEAD (@MERGE_HEADS) {
	foreach COMPARE_HEAD (@MERGE_HEADS) {
		if (COMPARE_HEAD != CURRENT_HEAD
		&&  COMPARE_HEAD is_included_into_history_of CURRENT_HEAD) {
			@WIPE_HEADS += COMPARE_HEAD;
		}
	}
}

foreach (@WIPE_HEADS) {
	grep -v @WIPE_HEADS @MERGE_HEADS;
}

	Thomas
-
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Received on Mon May 30 18:37:32 2005

This archive was generated by hypermail 2.1.8 : 2005-05-30 18:37:33 EST