Re: [PATCH v2] git checkout -b: unparent the new branch with -o

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

 



Junio C Hamano <gitster@xxxxxxxxx> 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
--
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]