Thread (5 messages) flat view 5 messages, 2 authors, 2016-06-15

Re: More gitweb queries..

From: Thomas Glanzmann <hidden>
Date: 2016-06-15 22:41:58

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
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help