git/list[1] front-page[2] threads[3] people[4] search[5] about
 

Re: Help breaking up a large merge.

From
Avery Pennarun <apenwarr@gmail.com>
Date
Sep 18, 2008, 17:40 UTC
Message-ID
<32541b130809181040p4785f877s7502c578e46745d8@mail.gmail.com>
In-Reply-To
<20080918152154.GA27019@linode.davidb.org>
On Thu, Sep 18, 2008 at 11:21 AM, David Brown <git@davidb.org> wrote:
Show 7 quoted lines
> The difficulty I'm having is that there are a lot of conflicts
> resulting from the merge (expected), and it would be nice to somehow
> be able to work on a smaller set of these conflicts at a time.
>
> Some of the conflicts are caused by a single change in the other tree.
> This is easy to cherry-pick into my tree, resolve, and then test those
> changes independently.

I've had the same sort of problem at work and I've gone through several iterations trying to solve a problem. The short version is that all the solutions proposed here so far, plus some other ones I thought of, don't seem to cut down the work for me :)

But here's one that has helped quite a bit, assuming that breaking up the merge by *files* makes sense.

...

Let's say you have two branches, A and B, derived from a base X. We want to merge the branch with fewer changes on top of the branch with more changes, because it'll be less work to divide up :) Let's assume the branch with fewer changes is A.

1) Generate a giant patch file using 'git diff X..A'.  Call the patch P.
2) Using an editor, divide up the patch by files/subdirs based on how
you want to subdivide the work.  Or alternatively, do that with 'git
diff' itself, but beware of accidentally forgetting to ask for some
files if you do it that way.  Call these n individual patches P1..Pn.
3) Create new branches called A1..An, copied directly from X.
4) Apply each patch P1..Pn to each branch A1..An.  (They will all
apply cleanly, because they are all patches against X in the first
place.)
5) Create new branches called B1..Bn, copied directly from *B*.
6) 'git merge' A1 into B1, A2 into B2, and so on.  Resolve the conflicts.
7) Create a new branch, TEST, copied from B.  Do an octopus merge from
B1..Bn.  There will be no conflicts, because those branches all make
mutually exclusive changes, and they're all based on B.  You now have
a combined branch containing A+B, but the history from A is missing.
8) Create a new patch, PFINAL, using 'git diff B..TEST'.  This is the
complete set of changes to turn B into A+B.
9) Checkout B.  'git merge A'; there will be conflicts.  'git checkout
HEAD .' to go back to B's files. Patch in PFINAL, and commit.

Now you have a single merge commit with all the changes, and the history will be correct.

10) Optional: 'git merge B1..Bn' so that you don't lose the history of
the individual sub-merges (you might want to look at them later or use
them for blame purposes).  There shouldn't be any conflicts, as the
changes in those branches are identical to the changes you just
committed, and git will discard them in the extra merge.

10b) Optional advanced-only trick: amend the main commit so that it looks like an octopus merge of B, A, and B1..Bn, instead of having a separate fake merge commit.

Note that this also helps a lot (for me) even if it's just a single person doing the merge: I like to do the library changes first, get all the library unit tests passing, then move up to bigger and bigger components.

Hope this helps.
Have fun,
Avery
Previous: Johannes SixtNext: David Brown
Message 5 of 6 in “Help breaking up a large merge.”
  1. David BrownSep 18, 2008
  2. Santi BéjarSep 18, 2008
  3. David BrownSep 18, 2008
  4. Johannes SixtSep 18, 2008
  5. Avery PennarunSep 18, 2008
  6. David BrownSep 18, 2008

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.