Re: Private/public branches/repos workflow
- From
Junio C Hamano <gitster@pobox.com>
- Date
- May 5, 2011, 18:14 UTC
- Message-ID
- <7v4o598164.fsf@alter.siamese.dyndns.org>
- In-Reply-To
- <BANLkTi=TLeePH0JDvnE0XPiCzXFxid9BWQ@mail.gmail.com>
Jerome Martin <tramjoe.merin@gmail.com> writes:
Show 9 quoted lines
> I have an application that lives in a git tree. That application is a > commercial product, but we have decided to dual-licence it and release > an open-source version of it, along with all further commits to it. > Preparatory work for this has been done, and I now have two (let's > ignore the other) branches in my git tree, 'public' and 'private'. > > The problem is, I cannot simply push the public branch on a public > repository, because the history contains a lot of stuff that are not > to be publicly released.
To do this properly without heavy cherry-picking, you would need a lot of discipline. Not just "you" as an integrator, but everybody in your development organization who has an access to the 'private' branch.
What you have is something like this:
O public
...---x---x---x---X private
where X is the tip of private branch that contains unreleasable stuff, while O is the tip of public branch, a redacted version fit for releasing to the general public. The former has a lot of history behind it, commits marked with 'x' that you are ashamed of showing to the public ;-), while the latter does not have any history behind it (the initial code dump).
Of course, if you build some feature that is not proprietary directly on
top of X and make a commit 'a', and try to merge that to the public
branch, the resulting history will become this, pulling all the history
behind X:
O----* public
/
...---x---x---x---X---a privateUnlike "merge tracking" tacked on to some other systems, a merge in git is a statement you make: "I looked at all the histories behind all the commits I am merging, and decided that this tree I am recording as the merge suits the purpose of my branch better than any of the parents". Merging 'a' is not "The change between a's parent and a was cherry picked onto this branch" (i.e. what mergeinfo records for SVN). In short, if you want to keep your x's private, you have to promise yourself that you will never ever merge private to public.
Side note. This is exactly a same discipline for managing the
maintenance track for the released version and the development
track for the next release in the open source world. You queue
fixes to the maintenance track, and you may merge the maintenance
to the development, but you never merge the development track to
the maintenance, because you do not want to pull new features from
the development branch into the bugfix only branch.First of all, you would do this once before making any changes:
$ git checkout private
$ git merge -s ours publicThis will create a new commit at the tip of private, that records that all the histories of public is now contained in private, but the recorded state (i.e. the tree) is identical to that of X. Let's call this commit S (it is a merge that synchronizes two independent histories):
O public
\
...---x---x---x---X---S privateThen, from here on, your developers have a choice to make whenever starting to work on a new thing, be it a bugfix or a feature.
If the change will _never_ be released to the public, you can continue building on your private branch.
O public
\
...---x---x---x---X---S---x---x privateOn the other hand, if it will _eventually_ be merged to the public, then you fork a topic branch from public, build it on that branch:
a---a---a---a feature-A
/
O---o---o---o public
\
...---x---x---x---X---S---x---x privateand merge it to public:
a---a---a---a feature-A
/ \
O---o---o---o---* public
\
...---x---x---x---X---S---x---x privateI depicted such a topic as "feature-A" that consists of four commits 'a' in the pictures above. Since you made the initial merge S, open source world may have added three commits 'o' to improve your system and you also have a few more commits 'x' that are secret.
The private branch can take the result of the work done on the topic branch, either by merging public wholesale:
a---a---a---a feature-A
/ \
O---o---o---o---* public
\ \
...---x---x---x---X---S---x---x-------* privatein which case you will also get the open source improvements 'o', or by merging that particular topic alone:
a---a---a---a... feature-A
/ \ .
O---o---o---o---* . public
\ .
...---x---x---x---X---S---x---x----------* privatein which case your private branch will not (yet) have the three 'o' open source improvements.
Note that you may consider some of your features "differentiating edge" that you may want to keep private for one year and then release it to the public. In such a case, you can even choose to merge feature-A to private first:
a---a---a---a... feature-A
/ .
O---o---o---o . public
\ .
...---x---x---x---X---S---x---x----------* privateand after a year, you can merge it to public to arrive at the previous picture.