On Sun, 31 Jul 2005, Andrew Morton wrote:
> So I finally decided to take a look at my git problems.  Discovered I
> couldn't fix them with zero git knowledge :(

Heh. We're here to please.

I'll cc the git list too, because there really _are_ a lot of people out 
there that know it fairly well, and may even have better suggestions than 
I do.

> What I want to do is to pull zillions of people's git trees into one repo
> and then run some magic command to give me unified diffs from everyone's
> trees which will apply to your latest.


Here's how to do it:

 - start off by fetching every single tree you want to have into its own 
   local branch. I think you basically do this already. If you're using 
   cogito, I think a simple "cg-pull" will do it for you.

   If you are using raw git, the easiest thing to do is to really just do

        result=$(git-fetch-pack "$repo" "$head") || exit

   which will fetch the named "head" from the named "repo", and stuff the 
   result in the "result" variable. You can then stuff that result 
   anywhere, so for example, if you pull _my_ repostiry, you could then 
   name the result "linus-tree" by just doing

        echo $result > .git/refs/heads/linus-tree

   and it really is that easy.

   So just do this for all the repos you want to pull, so that you have 
   <n> heads in the same tree, names however you wish (it the head naming
   _you_ have in your tree do not necessarily have anything at all to do 
   with the head naming in the heads in the trees the data came from. In
   fact, that's very important, because there can be multiple HEAD or
   "master" source branches, of course, and you need to make _your_ heads
   be unique).

 - second phase is to select some kind of order for these things, and just 
   start merging. Start off with a known base, and for each tree you merge 
   it against the previous merge, and then just generate the diff against 
   the previous merge.

   Now, one downside is that the current "git resolve" will _always_ 
   resolve into HEAD, which is admittedly a bit of a bummer: you can't 
   resolve into a totally temporary tree, which is what your usage might 

   This might be something git could do better for you, but the upside is
   that "git resolve" will always leave the previous tree in ORIG_HEAD,
   and since you really need to generate a temporary branch for all your
   merges anyway, you might as well just do exactly that, and switch to it
   before you start the merge process.

   Anyway, this example script will jusy always create a temporary branch
   called "merge-branch" that starts at whatever point you use as your
   base. Not a biggie. You can choose whatever as your starting point, I'm 
   just assuming that it's the "master" branch, and that you'd keep (for 
   example) my last release in there as the base.

   But if you want to keep the result of your quilt stuff, that should be 
   doable too, for example. I'm _assuming_ that you'd do the git merge 
   diffs first, and then do the quilt stuff on top of the result, but 
   there's nothing really that forces that order.

   So it should literally be as simple as something like this:

        # Start off from "master", create a new branch "merge-branch"
        # off that state.
        git checkout -f master
        git-rev-parse master > .git/refs/heads/merge-branch

        # Switch to it, always leaving "master" untouched
        git checkout -f merge-branch

        # For each tree you want to merge, just do so..
        # This also decides the order of the patches
        for i in linus-tree davem-net-tree davem-sparc-tree ...
                git resolve HEAD $i "Merging $i"
                if [ "$?" -ne 0 ]; then
                        echo "Automatic resolve failed, skipping $i" >&2

                        # Revert back to previous state, we're not going
                        # to do any manual fixups here.
                        git checkout -f
                        # Yay! The resolve worked, let's just diff what
                        # it did and continue onward from here
                        git diff ORIG_HEAD.. > merge-diff-$i

        # Finally, just switch back to "master", throw away all the work
        # we did (the objects will stay around, but you can do a
        #       git prune
        # once a week to get rid of the temporary objects. Don't do it
        # here, it's too expensive and there's no real point).
        git checkout -f master
        rm .git/refs/heads/merge-branch

and you're hopefully done. It really _should_ be that easy.

The above will leave you with a series of diffs called


which are all relative to each other (ie order very much matters, and 
comes directly from the order you did the merging in).

NOTE NOTE NOTE! I wrote the above in this email client, I've not tested it 
at all. It _looks_ straightforward enough, but hey, maybe I'm a retard.

And btw, this should all be quite efficient. It really shouldn't take many 
seconds per tree. The most expensive op _should_ be downloading the 
changes, and the fact that "git resolve" will always do a "diffstat" of 
the result..

To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to