From: Jerome Martin Date: Thu, 05 May 2011 20:43:09 GMT Subject: Re: Private/public branches/repos workflow Message-ID: In-Reply-To: <7v4o598164.fsf@alter.siamese.dyndns.org> Junio, Thanks a lot for your lengthy email and nice ASCII art making it a lot clearer to me why I was running in circles with the wrong idea on merge semantics :-) I think I understand clearly what you suggest, and the part about discipline is the conclusion I was drawing myself when answering Seth above. I understand there is no silver bullet, and that an orphan branch + discipline (regarding merges) + clever usage/planning of development branches is as good as the system might get with that 'hidden' history restriction. However, I am still wondering how (un?)practical this is in real life. It is probably just me not being fluent enough with git, but I still cannot help feeling the whole workflow as being awkward and error-prone for a daily usage. But hey, you seem to say that it is already used around a lot, at least for the maintenance/development branches case, so I guess it must be usable ;-) Could you tell me how you would see usage of rebasing inside the workflow you describe ? I am thinking about features (mistakenly) implemented on top of the private branch that need later to be release in the public branch. Can this be the shortcut to avoid lengthy cherry-picks ? On Thu, May 5, 2011 at 8:14 PM, Junio C Hamano wrote: > Jerome Martin writes: > >> 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. > > -- Jérôme Martin