ii. For each source in the best order, do the following merge:
(Our base has sources:
- the branch for each direct dep
- - the remote base)
+ - the remote base
+ - the topgit base, if this is a topgit import)
- Find the common ancestor.
+ Find the (latest) common ancestor.
Check for unwanted dependency removals.
An unwanted dependency removal is
which have already occurred on our base; these will be
reverted later.)
For each unwanted dependency removal (ie for each such
- branch), find the most recent commit which unwantedly removed
- the dep from the source's actual included deps ("relevant
- unwanted removal commit"). (Abort if any such commit is a
- merge.) Select the earliest relevant unwanted removal commit
- (from the set of relevant unwanted removal commits
- corresponding to the unwanted dependency removals).
- Merge from the ancestor of the relevant unwanted removal commit.
- Merge from the relevant unwanted removal commit using -s ours.
+ branch), search as follows:
+ * An "unwanted removal commit" is a non-merge commit in the
+ history of the source, which removes the dep from the
+ actual included deps.
+ * But the search stops at any point where we would have to
+ traverse a commit where .topbloke/deps is empty (which
+ stops us looking into the hitory of non-topbloke-controlled
+ branches). This can be done with git-rev-list
+ --remove-empty.
+ * The the relevant unwanted removal commit for that dep is
+ the most recent unwanted removal commit, as defined.
+ Select the unwantedly removed dep whose relevant unwanted
+ removal commit is the earliest. Merge from the ancestor of
+ that relevant unwanted removal commit. Merge from the relevant
+ unwanted removal commit using -s ours.
+
+ Now continue to the next unwanted dependency removal.
(The purpose of this, and the result, is that the unwanted
dependency removal has gone away. Doing things in this order
of a patch affected by an unwanted removal will benefit from
that client's resolution of the situation.)
- Now continue to the next unwanted dependency removal.
-
If there are no (more) unwanted dependency removals, merge
from the source.
* Attempt to apply the appropriate diff to add (resp. remove)
the contents of the relevant patch (adjusted appropriately
for metadata, XXX??? particularly the actual inclusion list)
+ XXX if we want to add a dep we need to update the dep first
* Go round again looking for another discrepancy.
3. Update our branch.
Our branch has sources:
- our base
- the remote for our branch
+ - the topgit branch, if this is a topgit import
For each source in the best order, do the merge.
Double-check the actual dependency inclusions. In
Operations like "go up the stack", goes towards leaf. Hopefully unique.
"Down" the stack, uses a "conventional" linearisation
Stack reordering op ? auto adjust deps
+
+
+When merging, we need to DTRT with our metadata.
+Do this by running write-tree/read-tree etc. ourselves ?
+For a source we're merging from, we make a version where the
+metadata we shouldn't be merging is removed ?
+Or something.
+Have discovered that specifying a custom merge driver for a file does
+not have any effect if the three-way-merge looks trivial based
+on looking at the file contents - at least, if you use git-merge.
+
+Only thing which knows how to do all the gitattributes stuff and
+conflict markers and what have you is git-merge. (git-merge-tree does
+too but the output format is unsuitable.) "git-merge-index
+... git-merge-one-file" does not honour the merge drivers and is,
+contrary to what the git docs seem to suggest but don't actually
+state, not actualy used by git-merge.
+
+OK so here is a plan:
+ Use git-merge --no-commit
+ Perhaps on a HEAD, and/or against a tree, which have been massaged
+ to make the metadata suitable as input.
+ Filtering out the "merge was successful but we aren't committing"
+ message. Use a single pipe for stdout/stderr to get interleaving
+ right; the message from git-merge is not i18n'd.
+ Afterwards we:
+ Check for merge success in the index and compare to exit status
+ from git-merge (which is 1 if the merge failed).
+ Adjust the metadata.
+ Print appropriate big fat warnings if we have merge conflicts in our
+ metadata.
+ Commit, adjusting the parents of the new commit to the original
+ parents if we made the merge with special massaged parents.
+ We may still need to have custom merge drivers for metadata.
+
+
+Strategies for each metadata file merge:
+
+ in base/tip same patch's tip dep -> base base -> tip
+
+ msg T textual merge rm from src not in src
+ deps T list merge rm from src not in src
+ deleted T std existence merge rm from src not in src
+ patch- BT must be same rm from src must be same
+ topgit- T must be same rm from src not in src
+ [^+]*- ?? textual merge rm from src rm from src
+ +included BT list merge rm from non-tb src list merge
+ +*- ?? textual merge rm from non-tb src textual merge
+ *[^-] ?? die, aborting all ops, if found in any tb src or branch