Re: Dealing with an upstream cherry-picked branch

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Sun, Mar 14, 2010 at 11:17 PM, Jay Soffian <jaysoffian@xxxxxxxxx> wrote:
> The question is how to best integrate the fixes on upstream-a into
> local-master, w/o causing a headache when upstream cuts the next
> tentative release branch, at which point upstrea-master will again
> need to be merged into local-master (and that will also have other
> local development). Here are two options I've considered:

You forgot option 0: tell upstream not to do that.

0a) Have them do their bugfixes directly in the upstream-a branch,
then merge sometimes from upstream-a to upstream-master.  Then when
they cut upstream-b from upstream-master, it should be an easy merge
for you (since they've already resolved any conflicts between
upstream-a and upstream-master as they arose over time).

0b) If they really need to do their bugfixes on upstream-master and
then cherry-pick them back to upstream-a, have them merge upstream-a
into upstream-master sometimes *anyway*, resolving any (probably
trivial) conflicts as they arise.  I say the conflicts should be
trivial because they're just cherry-picks anyway, so git will mostly
notice they're identical and ignore them.  This is easy to do a little
at a time, but gets more complicated if you wait a long time between
merges.

0c) Like 0b), only use 'git merge -s ours' to merge from upstream-a
into upstream-master.  This assumes that upstream-a *never* has a fix
other than one that is already in upstream-master, so that all
conflicts necessarily resolve to exactly what's already in
upstream-master.  This makes it easier for downstream people to merge
but doesn't actually cost any extra effort.

As for your original suggestions:

> 1) Create a local-a integration branch, merged from upstream-a and
> local-master. Keep this branch up-to-date by periodically merging
> local-master and upstream-a:

This will be inconvenient since local-master won't actually be useful;
if upstream-a contains a critical patch, you won't be able to test
your changes in local-master until you merge them into local-a.  Thus
the history of local-master, while "clean", will actually be
meaningless.

> 2) Periodically merge upstream-a into local-master:
> [...]
> Then when it is next time to merge upstream-master into local-master either:
>
> (a) Backout the upstream-a merges to local-master by reverting the
> merge commits which introduced them to local-master, then merge
> upstream-master.

Don't try to revert merge commits; that generally ends in disaster,
both in terms of your tree's correctness and your ability to
accurately retrace the history of your branch.  Possibly you can make
it work, but I don't know anybody who has.  Even if you can, you'll
still hate yourself in the morning.

> (b) Just merge upstream-master and carefully deal with all the
> conflicts. I think this will necessarily be an evil merge.

This is probably not as hard as it sounds, particularly if upstream-a
is *purely* a subset (in terms of cherry-picks, not in terms of
history) of upstream-master.  I'd recommend something like this (just
once when it's time to move to a new release branch):

       git checkout -b mergey upstream-master
       # take the history of upstream-a but not the content:
       git merge -s ours upstream-a
       # assuming local-master is your branch based on upstream-a:
       git checkout -b local-b local-master
       # merge the changes from upstream-a to upstream-master into local-b:
       git merge mergey

> (c) Create a new branch at point Ma and cherry-pick only the local
> commits from local-master past point Ma. This essentially gives me the
> clean local-master I would've had if I'd been doing (1) all along.

This will work, but the short form for exactly the same operation is:

        git checkout -b local-b local-master
        git rebase --onto upstream-master upstream-a

It will result in a cleaner history, and importantly, one that
upstream would probably be willing to merge someday.  You won't have
any extra cherry-picked commits confusingly merged into your history
with the original commits.

The disadvantage is that each of your branches will have a disjoint
history: there will be no branch showing how you got from local-a to
local-b, since they're actually two totally different things.  In git,
the ideal case is that if you look at the history of HEAD, you can see
the *entire* evolution of the product, and using a different
merge-base for each branch gets in the way of that.

The best option above, IMHO, is my proposed option 0.  But any of the
others will work.

Have fun,

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

[Index of Archives]     [Linux Kernel Development]     [Gcc Help]     [IETF Annouce]     [DCCP]     [Netdev]     [Networking]     [Security]     [V4L]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux SCSI]     [Fedora Users]