threads / discuss / 42215

Splitting a project into branches afterwards

Subject: Splitting a project into branches afterwards

## tl;dr

4 messages between May 3, 2016 and May 4, 2016.

replies: 3people: 2as markdown or json

Yohann Bénédic· May 3, 2016, 15:20 UTC · lore
Hello everyone!

First of all, I believe that what I am about to ask is impossible, but I give it a shot because there may be ways to get a close enough result or another approach that I have not thinked of.

What I have. A git repository cloned from svn (entire repo : 30,000 commits in 60 branches) that contains the source code of several products built around a common framework. Branches where made to track the delivered version of each product, so that there is a product_A_v1 branch, a product_B_v2 branch, etc. The key point is that there is only one trunk that is common to all of the products and framework. The source code is organized in a low-level -> high level hierarchy which results in not having a clean top level folders for product_A, product_B, … and framework.

What I wish I had. A git repository with a framework branch that only contains common code, a product_A branch that derived from the framework branch at some point, introducing all the product_A-specific source code. Same with the other products.

My attempt. I started from the master branch and created a framework branch out of it. I removed all the product specific code from it (A, B etc.) and commited (let's call that the initial_removal commit for further reference). I then created a product_A branch from the master branch and removed all the product-specific code other than product A's (keeping the framework) and commited (that's another initial_removal commit). I then did the same for product_B, C, etc. At this point, I am happy with the situation, even though the history reminds me that the products were not cleanly separated from each other in the past. The problem is with the "initial_removal" commits I made on each branch. If the framework branch moves forward, I want my product_A branch to be able follow along : that's a merge of the framework from product_A. In product_A, I might fix something from the framework and need to patch the latter. That's a merge in the other direction. Both these merges will apply the "initial_removal" commits, generating conflics at best, silently succeeding at worst. And that's were I am stuck because and can't find a way to tell git to ignore them once and for all so that I can have a normal workflow afterwards.

Further ideas. I feel like sub-trees might help me here, but I haven't learned enough about them to knwo for sure: anyone telling me "nope they won't help" or "yes that's what you are looking for" would help. Any complete procedure is welcomde too :) as weel as pointers to other git concepts.

Thank you all for your time.
Yohann

PS. I am not a native english speaker. Please, forgive any mistake or misleading sentence I might have written. Corrections are welcomed too!

Junio C Hamano· May 4, 2016, 08:23 UTC · re: Yohann Bénédic · lore

Re: Splitting a project into branches afterwards

Yohann Bénédic <yohann.benedic@orange.com> writes:
> branch. If the framework branch moves forward, I want my product_A branch to 
> be able follow along : that's a merge of the framework from product_A. In 
> product_A, I might fix something from the framework and need to patch the 
> latter. That's a merge in the other direction.

Instead of doing a mixed ball of wax on product specific branch, can't you do the latter by (1) fix something that belongs to the framework part of the system on the framework branch, (2) merge that to product A branch, and then (3) use that fixed framework code to update the product A? That way you would never have to merge product specific part to the framework, which is meant to be product agnistic (which is the whole point of your "initial removal" done on the framework branch, if I am reading you correctly).

Junio C Hamano· May 4, 2016, 08:38 UTC · re: Junio C Hamano · lore

Re: Splitting a project into branches afterwards

Junio C Hamano <gitster@pobox.com> writes:
Show 15 quoted lines
> Yohann Bénédic <yohann.benedic@orange.com> writes:
>
>> branch. If the framework branch moves forward, I want my product_A branch to 
>> be able follow along : that's a merge of the framework from product_A. In 
>> product_A, I might fix something from the framework and need to patch the 
>> latter. That's a merge in the other direction.
>
> Instead of doing a mixed ball of wax on product specific branch,
> can't you do the latter by (1) fix something that belongs to the
> framework part of the system on the framework branch, (2) merge that
> to product A branch, and then (3) use that fixed framework code to
> update the product A?  That way you would never have to merge
> product specific part to the framework, which is meant to be product
> agnistic (which is the whole point of your "initial removal" done on
> the framework branch, if I am reading you correctly).
In addition, I would imagine that you have this:
      F+B
     /
 ---X---F
     \
      F+A

where F stands for "framework part", A stands for "product A" and X is F+A+B (i.e. everything). The first thing I would do if that is what you have is to abandon the product specific branches directly forked from the "everything" and instead form a history of this shape:

          F+B
         /
 ---X---F
         \
          F+A

That is, make the commit marked F in the updated history, whose tree has only the framework part, the new "birth" of your company's source code, where other product specific branches all fork off of.

Then touch the common framework only on its own branch, occasionally merging that down to (all) product specific branches, change product specific parts only on their own product specific branch, and merge only in one direction (i.e. framework to product), never in reverse.

          F+B
         /
 ---X---F-----F'-----F''   ... framework evolves this way
         \            \    
          F+A---F+A'---F''+A'  ... product A evolves this way
yohann.benedic@orange.com· May 4, 2016, 09:52 UTC · re: Junio C Hamano · lore

RE: Splitting a project into branches afterwards

Show 15 quoted lines
>In addition, I would imagine that you have this:
>
>      F+B
>     /
> ---X---F
>     \
>      F+A
>
>(...)
>          F+B
>         /
> ---X---F
>         \
>          F+A
>
Hi,

Thank you for your answer :) I don't understand the difference between the two diagrams. I can see the branch points are different but why is it relevant?

I probably should have included diagrams in my original post. Here is what I have, with your notations, and with Ai, Bi, Fi denoting commits that introduce changes in product A, product B and the framework respectively:
--F1----B1----A1----A2----F2----B2=X
What I wish I had
        A1 ---- A2----+=A
      /                     /
--F1----------------F2=F
      \                      \
        B1---------------+-----B2=B
Thanks to your post, I now realize that merges should only bring new framework stuff into product specific branches and not the other way around (ie. If I happened to have fixed a framework issue in a branch derived from product A, I should rebase it onto the framework, merge it in the framework and then merge the framework into the product A branch, it makes perfect sense).
I don't really care if I can rewrite the history this way (unless it turns out to be super easy) as long as I can set up the repository so that I can work this way from now on. So here is my attempt from the current history, introducing the framework branch and the new product branches with their respective "initial_removal" commits: Ax means remove product A specific code, same for Bx.
                                                     Bx---------+=A (now contains Ax, which is not suitable)
                                                    /   \        /
--F1----B1----A1----A2----F2----B2---+---F3=F
                                                    \   /       \
                                                     Ax--------+=B (now contains Bx, which is not suitable)
Notice that I applied Ax and Bx to F in order to clear it from the product specific code. Yet, doing so will eventually bring Ax to branch A and Bx to branch B, killing them. I can't find a way to avoid this while clearing the F branch other than cherry-picking F3 or any rebase solutions.
Now I believe you're suggesting not to apply Ax and Bx to F, and hence have the product specific code remain in a dead state in F. That will do and it probably is what I will end up doing, unless another idea comes out.
Thank you
Yohann
_________________________________________________________________________________________________________________________

Ce message et ses pieces jointes peuvent contenir des informations confidentielles ou privilegiees et ne doivent donc pas etre diffuses, exploites ou copies sans autorisation. Si vous avez recu ce message par erreur, veuillez le signaler a l'expediteur et le detruire ainsi que les pieces jointes. Les messages electroniques etant susceptibles d'alteration, Orange decline toute responsabilite si ce message a ete altere, deforme ou falsifie. Merci.

This message and its attachments may contain confidential or privileged information that may be protected by law; they should not be distributed, used or copied without authorisation. If you have received this email in error, please notify the sender and delete this message and its attachments. As emails may be altered, Orange is not liable for messages that have been modified, changed or falsified. Thank you.

← back to recent threads