git/list[1] front-page[2] threads[3] people[4] search[5] about
 

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   private

Unlike "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 public

This 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   private

Then, 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   private

On 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   private
and merge it to public:
                       a---a---a---a  feature-A
                      /             \   
                     O---o---o---o---*  public
                      \
 ...---x---x---x---X---S---x---x   private

I 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-------*  private

in 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----------*  private

in 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----------*  private

and after a year, you can merge it to public to arrive at the previous picture.

Previous: Jerome MartinNext: Jerome Martin
Message 4 of 8 in “Private/public branches/repos workflow”
  1. Jerome MartinMay 5, 2011
  2. Seth RobertsonMay 5, 2011
  3. Jerome MartinMay 5, 2011
  4. Junio C HamanoMay 5, 2011
  5. Jerome MartinMay 5, 2011
  6. Junio C HamanoMay 6, 2011
  7. Jerome MartinMay 6, 2011
  8. Jerome MartinMay 5, 2011

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.