{"thread":{"id":"42215","subject":"Splitting a project into branches afterwards","startedAt":"2016-05-03T15:20:44Z","lastAt":"2016-05-04T09:52:29Z","messageCount":4,"participants":["Yohann Bénédic","Junio C Hamano","yohann.benedic@orange.com"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"285434","messageId":"loom.20160503T090745-628@post.gmane.org","threadId":"42215","inReplyTo":null,"subject":"Splitting a project into branches afterwards","fromName":"Yohann Bénédic","fromEmail":"yohann.benedic@orange.com","sentAt":"2016-05-03T15:20:44Z","receivedAt":"2016-05-03T15:20:44Z","isPatch":false,"sender":{"key":"yohann.benedic@orange.com","avatar":null},"body":"Hello everyone!\n\nFirst of all, I believe that what I am about to ask is impossible, but I \ngive it a shot because there may be ways to get a close enough result or \nanother approach that I have not thinked of.\n\nWhat I have.\nA git repository cloned from svn (entire repo : 30,000 commits in 60 \nbranches) that contains the source code of several products built around a \ncommon framework. Branches where made to track the delivered version of each \nproduct, so that there is a product_A_v1 branch, a product_B_v2 branch, etc. \nThe key point is that there is only one trunk that is common to all of the \nproducts and framework. The source code is organized in a low-level -> high \nlevel hierarchy which results in not having a clean top level folders for \nproduct_A, product_B, … and framework.\n\nWhat I wish I had.\nA git repository with a framework branch that only contains common code, a \nproduct_A branch that derived from the framework branch at some point, \nintroducing all the product_A-specific source code. Same with the other \nproducts.\n\nMy attempt.\nI started from the master branch and created a framework branch out of it. I \nremoved all the product specific code from it (A, B etc.) and commited \n(let's call that the initial_removal commit for further reference). I then \ncreated a product_A branch from the master branch and removed all the \nproduct-specific code other than product A's (keeping the framework) and \ncommited (that's another initial_removal commit). I then did the same for \nproduct_B, C, etc.\nAt this point, I am happy with the situation, even though the history \nreminds me that the products were not cleanly separated from each other in \nthe past. The problem is with the \"initial_removal\" commits I made on each \nbranch. If the framework branch moves forward, I want my product_A branch to \nbe able follow along : that's a merge of the framework from product_A. In \nproduct_A, I might fix something from the framework and need to patch the \nlatter. That's a merge in the other direction. Both these merges will apply \nthe \"initial_removal\" commits, generating conflics at best, silently \nsucceeding at worst. And that's were I am stuck because and can't find a way \nto tell git to ignore them once and for all so that I can have a normal \nworkflow afterwards.\n\nFurther ideas.\nI feel like sub-trees might help me here, but I haven't learned enough about \nthem to knwo for sure: anyone telling me \"nope they won't help\" or \"yes \nthat's what you are looking for\" would help.\nAny complete procedure is welcomde too :) as weel as pointers to other git \nconcepts.\n\nThank you all for your time.\n\nYohann\n\nPS. I am not a native english speaker. Please, forgive any mistake or \nmisleading sentence I might have written. Corrections are welcomed too!"},{"id":"285438","messageId":"xmqqoa8mi64h.fsf@gitster.mtv.corp.google.com","threadId":"42215","inReplyTo":"loom.20160503T090745-628@post.gmane.org","subject":"Re: Splitting a project into branches afterwards","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2016-05-04T08:23:26Z","receivedAt":"2016-05-04T08:23:26Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Yohann Bénédic <yohann.benedic@orange.com> writes:\n\n> branch. If the framework branch moves forward, I want my product_A branch to \n> be able follow along : that's a merge of the framework from product_A. In \n> product_A, I might fix something from the framework and need to patch the \n> latter. That's a merge in the other direction.\n\nInstead of doing a mixed ball of wax on product specific branch,\ncan't you do the latter by (1) fix something that belongs to the\nframework part of the system on the framework branch, (2) merge that\nto product A branch, and then (3) use that fixed framework code to\nupdate the product A?  That way you would never have to merge\nproduct specific part to the framework, which is meant to be product\nagnistic (which is the whole point of your \"initial removal\" done on\nthe framework branch, if I am reading you correctly).\n"},{"id":"285442","messageId":"xmqqk2jai5fb.fsf@gitster.mtv.corp.google.com","threadId":"42215","inReplyTo":"xmqqoa8mi64h.fsf@gitster.mtv.corp.google.com","subject":"Re: Splitting a project into branches afterwards","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2016-05-04T08:38:32Z","receivedAt":"2016-05-04T08:38:32Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Junio C Hamano <gitster@pobox.com> writes:\n\n> Yohann Bénédic <yohann.benedic@orange.com> writes:\n>\n>> branch. If the framework branch moves forward, I want my product_A branch to \n>> be able follow along : that's a merge of the framework from product_A. In \n>> product_A, I might fix something from the framework and need to patch the \n>> latter. That's a merge in the other direction.\n>\n> Instead of doing a mixed ball of wax on product specific branch,\n> can't you do the latter by (1) fix something that belongs to the\n> framework part of the system on the framework branch, (2) merge that\n> to product A branch, and then (3) use that fixed framework code to\n> update the product A?  That way you would never have to merge\n> product specific part to the framework, which is meant to be product\n> agnistic (which is the whole point of your \"initial removal\" done on\n> the framework branch, if I am reading you correctly).\n\nIn addition, I would imagine that you have this:\n\n      F+B\n     /\n ---X---F\n     \\\n      F+A\n\nwhere F stands for \"framework part\", A stands for \"product A\" and X\nis F+A+B (i.e. everything).  The first thing I would do if that is\nwhat you have is to abandon the product specific branches directly\nforked from the \"everything\" and instead form a history of this\nshape:\n\n          F+B\n         /\n ---X---F\n         \\\n          F+A\n\nThat is, make the commit marked F in the updated history, whose tree\nhas only the framework part, the new \"birth\" of your company's\nsource code, where other product specific branches all fork off of.\n\nThen touch the common framework only on its own branch, occasionally\nmerging that down to (all) product specific branches, change product\nspecific parts only on their own product specific branch, and merge\nonly in one direction (i.e. framework to product), never in reverse.\n\n          F+B\n         /\n ---X---F-----F'-----F''   ... framework evolves this way\n         \\            \\    \n          F+A---F+A'---F''+A'  ... product A evolves this way\n"},{"id":"285450","messageId":"23776_1462355550_5729C65E_23776_11197_1_2D437EEBD32B444FBE10D6D0DC89390A0FC6189C@OPEXCLILM21.corporate.adroot.infra.ftgroup","threadId":"42215","inReplyTo":"xmqqk2jai5fb.fsf@gitster.mtv.corp.google.com","subject":"RE: Splitting a project into branches afterwards","fromName":"","fromEmail":"yohann.benedic@orange.com","sentAt":"2016-05-04T09:52:29Z","receivedAt":"2016-05-04T09:52:29Z","isPatch":false,"sender":{"key":"yohann.benedic@orange.com","avatar":null},"body":">In addition, I would imagine that you have this:\n>\n>      F+B\n>     /\n> ---X---F\n>     \\\n>      F+A\n>\n>(...)\n>          F+B\n>         /\n> ---X---F\n>         \\\n>          F+A\n>\n\nHi,\n\nThank you for your answer :)\nI don't understand the difference between the two diagrams. I can see the branch points are different but why is it relevant?\n\nI 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:\n\n--F1----B1----A1----A2----F2----B2=X\n\nWhat I wish I had\n\n        A1 ---- A2----+=A\n      /                     /\n--F1----------------F2=F\n      \\                      \\\n        B1---------------+-----B2=B\n\nThanks 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).\n\nI 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.\n\n                                                     Bx---------+=A (now contains Ax, which is not suitable)\n                                                    /   \\        /\n--F1----B1----A1----A2----F2----B2---+---F3=F\n                                                    \\   /       \\\n                                                     Ax--------+=B (now contains Bx, which is not suitable)\n\nNotice 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.\n\nNow 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.\n\nThank you\n\nYohann\n\n_________________________________________________________________________________________________________________________\n\nCe message et ses pieces jointes peuvent contenir des informations confidentielles ou privilegiees et ne doivent donc\npas etre diffuses, exploites ou copies sans autorisation. Si vous avez recu ce message par erreur, veuillez le signaler\na l'expediteur et le detruire ainsi que les pieces jointes. Les messages electroniques etant susceptibles d'alteration,\nOrange decline toute responsabilite si ce message a ete altere, deforme ou falsifie. Merci.\n\nThis message and its attachments may contain confidential or privileged information that may be protected by law;\nthey should not be distributed, used or copied without authorisation.\nIf you have received this email in error, please notify the sender and delete this message and its attachments.\nAs emails may be altered, Orange is not liable for messages that have been modified, changed or falsified.\nThank you.\n\n"}]}