From: Erick Mattos Date: Sun, 14 Mar 2010 21:57:22 GMT Subject: Re: [PATCH v2] git checkout -b: unparent the new branch with -o Message-ID: <55bacdd31003141457t7d2cebe3u9854d3c0a55b7da0@mail.gmail.com> In-Reply-To: <7v4okkegdy.fsf@alter.siamese.dyndns.org> Hi As I see you have found a very good example under your common work flow. Nice. :-) Regards 2010/3/13 Junio C Hamano : > Junio C Hamano writes: > >> As I already said, I do not think "mostly common paths" case should be >> encouraged to begin with.  As far as I know (and you can guess by now that >> I know reasonably well about git), you do not gain anything by not having >> the ancestry link between '?' and 'B', except that it would make conflict >> resolution at '*' extremely difficult.  There is only downside without any >> upside in "mostly common paths" disjoint merge. > > There is one case "mostly common paths" disjoint history can be useful. > > Imagine you have a hitherto proprietary software project and want to go > open source.  Perhaps your intention is to have an open source version and > an enhanced commercial version.  The project contains some third-party > vendor software outside your control, and you have replaced them with open > source equivalents or disabled features that depend on them. > > Your history may look like this: > >      o---o---A oss-base >     / >  ---o---o---o---o master > > where master is the primary version you will continue shipping to your > paying customers, with proprietary third-party components and features > that depend on them.  Commits on oss-base were your work to prepare the > tree into a releasable shape, removing these proprietary stuff along with > some features. > > But you cannot publish oss-base (commit A) to the public.  "git log" will > show all the history that leads to it, with all the third-party stuff you > do not have license to distribute in the source form.  The older parts of > the history may even have site password at customer installation you have > committed by mistake and eradicated long time ago. > > If you run this three command sequence (in this message, I am assuming > that you keep the index and the working tree files intact in an updated > implementation of --orphan, which is different from the suggestion to > support "no common paths" case I mentioned in the previous message): > >    $ git checkout --orphan oss oss-base >    $ git checkout oss-base >    $ git merge -s ours oss > > you will get a history of this shape: > >                X oss >                 \ >      o---o---A---B oss-base >     / >  ---o---o---o---o master > > with commits X, A and B all recording an identical tree.  The oss branch > (commit X) is now safe to publish. > > Once you have done this, further you can: > >    $ git checkout master >    $ git merge oss-base > > which gives you a history of this shape: > >                X oss >                 \ >      o---o---A---B oss-base >     /             \ >  ---o---o---o---o---Y master > > This merge Y has to be done carefully.  It inherently has to be an evil > merge because oss-base wants to replace some proprietary stuff with open > source counterparts while you may want to keep using the proprietary ones > you have support contract for in your paying customer release you will > make from the master branch.  So at Y, you will most likely be reverting > some work you did on oss-base branch since it forked from master. > > After setting it up, this arrangement allows you to: > >  - accept changes from public, and/or build changes for public, to advance >   "community version" on the oss branch on top of X; > >  - from time to time, merge oss to oss-base; > >  - from time to time, merge oss-base to master. > > and the histories will continue like this: > >                X---C---C---C---C oss >                 \           \ >      o---o---A---B-----------* oss-base >     /             \           \ >  ---o---o---o---o---Y---P---P---*---P---P master > > with community commits C (either contributed from the public or you > developed yourself and gave to the community) on oss branch, with > proprietary commits P that record your own proprietary work on master > branch.  Note that oss-base branch is not used to produce nor record any > commit on its own---it is merely to ease the merging from oss and master > by providing X-B link to serve as a convenient common ancestor to make > later merges easier. > > Note also that it would be the most convenient if you kept both the index > and the working tree intact, if "checkout --orphan" is to be used as an > ingredient for this workflow.  It _might_ actually make sense not to make > the "git checkout --orphan" an independent feature that can be randomly > abused or misused, but package the three-command sequence to create the > A-B-X open triangle above into a separate command, i.e. > >    $ git branch --orphan oss > > would create a new branch "oss" with its own root commit X that records > the same tree as the current HEAD A, and immediately merge X back into A > to produce B, again recording the same tree, and advance the current HEAD > to point at B, like so: > >                                             X oss >                                              \ >    ---o---A HEAD       -->         ---o---A---B HEAD >