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 BIs 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