{"thread":{"id":"27267","subject":"Private/public branches/repos workflow","startedAt":"2011-05-05T15:16:34Z","lastAt":"2011-05-06T09:27:11Z","messageCount":8,"participants":["Jerome Martin","Seth Robertson","Junio C Hamano"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"167113","messageId":"BANLkTi=TLeePH0JDvnE0XPiCzXFxid9BWQ@mail.gmail.com","threadId":"27267","inReplyTo":null,"subject":"Private/public branches/repos workflow","fromName":"Jerome Martin","fromEmail":"tramjoe.merin@gmail.com","sentAt":"2011-05-05T15:16:34Z","receivedAt":"2011-05-05T15:16:34Z","isPatch":false,"sender":{"key":"tramjoe.merin@gmail.com","avatar":null},"body":"Hello list,\n\nI have an application that lives in a git tree. That application is a\ncommercial product, but we have decided to dual-licence it and release\nan open-source version of it, along with all further commits to it.\nPreparatory work for this has been done, and I now have two (let's\nignore the other) branches in my git tree, 'public' and 'private'.\n\nThe problem is, I cannot simply push the public branch on a public\nrepository, because the history contains a lot of stuff that are not\nto be publicly released.\n\nI thought I could squash all commits on that 'public' branch for the\ninitial public release and resume working from there, keeping the\nability to happily merge subsequent commits between 'public' and\n'private', but this does not work: I am always left with the initial\ncommit of my whole tree (which unfortunately is not releasable) and\nthe big sqashed commit.\n\nSo what we did for now is to create a new git tree completely from\nscratch, containing only the public code tree. However, I am afraid\nthis will lead to a nightmarish workflow, as it involves me working on\nour internal tree 'public'/'private' branches, and from there,\nreplicate the commits to my internal 'public' branch to that published\nrepository. As pushing/pulling there results in having all the history\ncommitted back to the published repo, I must resort to either having\nto cherry pick all those commits one by one, or manually apply them to\nthe published repo. Maintenance hell.\n\nIs there any recommended workflow to achieve the result I am looking\nfor ? How are other people doing it ?\n\nBest Regards,\n-- \nJérôme Martin\n"},{"id":"167119","messageId":"201105051535.p45FZQDY019419@no.baka.org","threadId":"27267","inReplyTo":"BANLkTi=TLeePH0JDvnE0XPiCzXFxid9BWQ@mail.gmail.com","subject":"Re: Private/public branches/repos workflow","fromName":"Seth Robertson","fromEmail":"in-gitvger@baka.org","sentAt":"2011-05-05T15:35:26Z","receivedAt":"2011-05-05T15:35:26Z","isPatch":false,"sender":{"key":"in-gitvger@baka.org","avatar":null},"body":"\nIn message <BANLkTi=TLeePH0JDvnE0XPiCzXFxid9BWQ@mail.gmail.com>, Jerome Martin\nwrites:\n\n    Is there any recommended workflow to achieve the result I am looking\n    for ? How are other people doing it ?\n\nCreate an orphan branch.  Commit what you want onto it.  Push branch\nto a new repo as master.\n\ngit checkout <basesha>\ngit checkout --orphan cleanmaster\ngit add -A\ngit commit -m \"base of public release\"\n(mkdir ../newrepo; cd ../newrepo; git init --bare)\ngit remote add cleanremote ../newrepo\ngit push cleanremote cleanmaster:master\n\nYou can then cherry pick/rebase from previous branches onto\ncleanmaster any subsequent commits that you want to keep history for.\n\nAnother approach might be to finesse a shallow clone to do what you\nwant.\n\n\t\t\t\t\t-Seth Robertson\n"},{"id":"167117","messageId":"BANLkTinL6UYAKeBtLnU5+rvwmd+N0dYErw@mail.gmail.com","threadId":"27267","inReplyTo":"201105051535.p45FZQDY019419@no.baka.org","subject":"Re: Private/public branches/repos workflow","fromName":"Jerome Martin","fromEmail":"tramjoe.merin@gmail.com","sentAt":"2011-05-05T15:53:40Z","receivedAt":"2011-05-05T15:53:40Z","isPatch":false,"sender":{"key":"tramjoe.merin@gmail.com","avatar":null},"body":"Thanks for your quick answer!\nIt seems to be a solution a bit alike one I tested before sending my\ninitial question, using :\ngit symbolic-ref HEAD refs/heads/cleanmaster\nBut I am unsure of the result I am getting.\nAre you suggesting that I should entirely replace my current 'public'\nbranch (there is no important history in there to keep apart from what\nis already in the other, private, branch) by cleanmaster or that I\nshould keep using three branches and push from that third one\n(cleanmaster) to the published repo ?\nOne thing I do not understand clearly is why with a detached (I guess\nthis is synonym to orphan ? At least when creating it ?) branch cannot\nbe then merged with the branch that was initially copied to create it\nand just get the additional commits. Instead, it gets the whole\nhistory. Being used to using merge between my public/private branches,\nI am afraid that using that orphan branch might lead to disaster\neventually.\n\nOn Thu, May 5, 2011 at 5:35 PM, Seth Robertson <in-gitvger@baka.org> wrote:\n>\n> In message <BANLkTi=TLeePH0JDvnE0XPiCzXFxid9BWQ@mail.gmail.com>, Jerome Martin\n> writes:\n>\n>    Is there any recommended workflow to achieve the result I am looking\n>    for ? How are other people doing it ?\n>\n> Create an orphan branch.  Commit what you want onto it.  Push branch\n> to a new repo as master.\n>\n> git checkout <basesha>\n> git checkout --orphan cleanmaster\n> git add -A\n> git commit -m \"base of public release\"\n> (mkdir ../newrepo; cd ../newrepo; git init --bare)\n> git remote add cleanremote ../newrepo\n> git push cleanremote cleanmaster:master\n>\n> You can then cherry pick/rebase from previous branches onto\n> cleanmaster any subsequent commits that you want to keep history for.\n>\n> Another approach might be to finesse a shallow clone to do what you\n> want.\n>\n>                                        -Seth Robertson\n\n\n\n--\nJérôme Martin\n"},{"id":"167140","messageId":"7v4o598164.fsf@alter.siamese.dyndns.org","threadId":"27267","inReplyTo":"BANLkTi=TLeePH0JDvnE0XPiCzXFxid9BWQ@mail.gmail.com","subject":"Re: Private/public branches/repos workflow","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2011-05-05T18:14:43Z","receivedAt":"2011-05-05T18:14:43Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Jerome Martin <tramjoe.merin@gmail.com> writes:\n\n> I have an application that lives in a git tree. That application is a\n> commercial product, but we have decided to dual-licence it and release\n> an open-source version of it, along with all further commits to it.\n> Preparatory work for this has been done, and I now have two (let's\n> ignore the other) branches in my git tree, 'public' and 'private'.\n>\n> The problem is, I cannot simply push the public branch on a public\n> repository, because the history contains a lot of stuff that are not\n> to be publicly released.\n\nTo do this properly without heavy cherry-picking, you would need a lot of\ndiscipline.  Not just \"you\" as an integrator, but everybody in your\ndevelopment organization who has an access to the 'private' branch.\n\nWhat you have is something like this:\n\n                   O   public\n\n ...---x---x---x---X   private\n\nwhere X is the tip of private branch that contains unreleasable stuff,\nwhile O is the tip of public branch, a redacted version fit for releasing\nto the general public.  The former has a lot of history behind it, commits\nmarked with 'x' that you are ashamed of showing to the public ;-), while\nthe latter does not have any history behind it (the initial code dump).\n\nOf course, if you build some feature that is not proprietary directly on\ntop of X and make a commit 'a', and try to merge that to the public\nbranch, the resulting history will become this, pulling all the history\nbehind X:\n                    O----*   public\n                        /\n ...---x---x---x---X---a   private\n\nUnlike \"merge tracking\" tacked on to some other systems, a merge in git is\na statement you make: \"I looked at all the histories behind all the\ncommits I am merging, and decided that this tree I am recording as the\nmerge suits the purpose of my branch better than any of the parents\".\nMerging 'a' is not \"The change between a's parent and a was cherry picked\nonto this branch\" (i.e. what mergeinfo records for SVN).  In short, if you\nwant to keep your x's private, you have to promise yourself that you will\nnever ever merge private to public.\n\n        Side note.  This is exactly a same discipline for managing the\n        maintenance track for the released version and the development\n        track for the next release in the open source world.  You queue\n        fixes to the maintenance track, and you may merge the maintenance\n        to the development, but you never merge the development track to\n        the maintenance, because you do not want to pull new features from\n        the development branch into the bugfix only branch.\n\nFirst of all, you would do this once before making any changes:\n\n    $ git checkout private\n    $ git merge -s ours public\n\nThis will create a new commit at the tip of private, that records that all\nthe histories of public is now contained in private, but the recorded\nstate (i.e. the tree) is identical to that of X.  Let's call this commit S\n(it is a merge that synchronizes two independent histories):\n\n                     O   public\n                      \\\n ...---x---x---x---X---S   private\n\nThen, from here on, your developers have a choice to make whenever\nstarting to work on a new thing, be it a bugfix or a feature.\n\nIf the change will _never_ be released to the public, you can continue\nbuilding on your private branch.\n\n                     O   public\n                      \\\n ...---x---x---x---X---S---x---x   private\n\nOn the other hand, if it will _eventually_ be merged to the public, then\nyou fork a topic branch from public, build it on that branch:\n\n                       a---a---a---a  feature-A\n                      /\n                     O---o---o---o  public\n                      \\\n ...---x---x---x---X---S---x---x   private\n\nand merge it to public:\n\n                       a---a---a---a  feature-A\n                      /             \\   \n                     O---o---o---o---*  public\n                      \\\n ...---x---x---x---X---S---x---x   private\n\nI depicted such a topic as \"feature-A\" that consists of four commits 'a'\nin the pictures above.  Since you made the initial merge S, open source\nworld may have added three commits 'o' to improve your system and you also\nhave a few more commits 'x' that are secret.\n\nThe private branch can take the result of the work done on the topic\nbranch, either by merging public wholesale:\n\n                       a---a---a---a  feature-A\n                      /             \\   \n                     O---o---o---o---*  public\n                      \\               \\ \n ...---x---x---x---X---S---x---x-------*  private\n\nin which case you will also get the open source improvements 'o', or by\nmerging that particular topic alone:\n\n                       a---a---a---a...    feature-A\n                      /             \\  . \n                     O---o---o---o---*  .  public\n                      \\                  .\n ...---x---x---x---X---S---x---x----------*  private\n\nin which case your private branch will not (yet) have the three 'o' open\nsource improvements.\n\nNote that you may consider some of your features \"differentiating edge\"\nthat you may want to keep private for one year and then release it to the\npublic.  In such a case, you can even choose to merge feature-A to private\nfirst:\n\n                       a---a---a---a...    feature-A\n                      /                . \n                     O---o---o---o      .  public\n                      \\                  .\n ...---x---x---x---X---S---x---x----------*  private\n\nand after a year, you can merge it to public to arrive at the previous\npicture.\n"},{"id":"167187","messageId":"BANLkTimggn-E+JsXp78_a2P3eWku3oTSbQ@mail.gmail.com","threadId":"27267","inReplyTo":"7v4o598164.fsf@alter.siamese.dyndns.org","subject":"Re: Private/public branches/repos workflow","fromName":"Jerome Martin","fromEmail":"tramjoe.merin@gmail.com","sentAt":"2011-05-05T20:43:09Z","receivedAt":"2011-05-05T20:43:09Z","isPatch":false,"sender":{"key":"tramjoe.merin@gmail.com","avatar":null},"body":"Junio,\n\nThanks a lot for your lengthy email and nice ASCII art making it a lot\nclearer to me why I was running in circles with the wrong idea on\nmerge semantics :-) I think I understand clearly what you suggest, and\nthe part about discipline is the conclusion I was drawing myself when\nanswering Seth above.\n\nI understand there is no silver bullet, and that an orphan branch +\ndiscipline (regarding merges) + clever usage/planning of development\nbranches is as good as the system might get with that 'hidden' history\nrestriction. However, I am still wondering how (un?)practical this is\nin real life.\n\nIt is probably just me not being fluent enough with git, but I still\ncannot help feeling the whole workflow as being awkward and\nerror-prone for a daily usage. But hey, you seem to say that it is\nalready used around a lot, at least for the maintenance/development\nbranches case, so I guess it must be usable ;-)\n\nCould you tell me how you would see usage of rebasing inside the\nworkflow you describe ? I am thinking about features (mistakenly)\nimplemented on top of the private branch that need later to be release\nin the public branch. Can this be the shortcut to avoid lengthy\ncherry-picks ?\n\nOn Thu, May 5, 2011 at 8:14 PM, Junio C Hamano <gitster@pobox.com> wrote:\n> Jerome Martin <tramjoe.merin@gmail.com> writes:\n>\n>> I have an application that lives in a git tree. That application is a\n>> commercial product, but we have decided to dual-licence it and release\n>> an open-source version of it, along with all further commits to it.\n>> Preparatory work for this has been done, and I now have two (let's\n>> ignore the other) branches in my git tree, 'public' and 'private'.\n>>\n>> The problem is, I cannot simply push the public branch on a public\n>> repository, because the history contains a lot of stuff that are not\n>> to be publicly released.\n>\n> To do this properly without heavy cherry-picking, you would need a lot of\n> discipline.  Not just \"you\" as an integrator, but everybody in your\n> development organization who has an access to the 'private' branch.\n>\n> What you have is something like this:\n>\n>                   O   public\n>\n>  ...---x---x---x---X   private\n>\n> where X is the tip of private branch that contains unreleasable stuff,\n> while O is the tip of public branch, a redacted version fit for releasing\n> to the general public.  The former has a lot of history behind it, commits\n> marked with 'x' that you are ashamed of showing to the public ;-), while\n> the latter does not have any history behind it (the initial code dump).\n>\n> Of course, if you build some feature that is not proprietary directly on\n> top of X and make a commit 'a', and try to merge that to the public\n> branch, the resulting history will become this, pulling all the history\n> behind X:\n>                    O----*   public\n>                        /\n>  ...---x---x---x---X---a   private\n>\n> Unlike \"merge tracking\" tacked on to some other systems, a merge in git is\n> a statement you make: \"I looked at all the histories behind all the\n> commits I am merging, and decided that this tree I am recording as the\n> merge suits the purpose of my branch better than any of the parents\".\n> Merging 'a' is not \"The change between a's parent and a was cherry picked\n> onto this branch\" (i.e. what mergeinfo records for SVN).  In short, if you\n> want to keep your x's private, you have to promise yourself that you will\n> never ever merge private to public.\n>\n>        Side note.  This is exactly a same discipline for managing the\n>        maintenance track for the released version and the development\n>        track for the next release in the open source world.  You queue\n>        fixes to the maintenance track, and you may merge the maintenance\n>        to the development, but you never merge the development track to\n>        the maintenance, because you do not want to pull new features from\n>        the development branch into the bugfix only branch.\n>\n> First of all, you would do this once before making any changes:\n>\n>    $ git checkout private\n>    $ git merge -s ours public\n>\n> This will create a new commit at the tip of private, that records that all\n> the histories of public is now contained in private, but the recorded\n> state (i.e. the tree) is identical to that of X.  Let's call this commit S\n> (it is a merge that synchronizes two independent histories):\n>\n>                     O   public\n>                      \\\n>  ...---x---x---x---X---S   private\n>\n> Then, from here on, your developers have a choice to make whenever\n> starting to work on a new thing, be it a bugfix or a feature.\n>\n> If the change will _never_ be released to the public, you can continue\n> building on your private branch.\n>\n>                     O   public\n>                      \\\n>  ...---x---x---x---X---S---x---x   private\n>\n> On the other hand, if it will _eventually_ be merged to the public, then\n> you fork a topic branch from public, build it on that branch:\n>\n>                       a---a---a---a  feature-A\n>                      /\n>                     O---o---o---o  public\n>                      \\\n>  ...---x---x---x---X---S---x---x   private\n>\n> and merge it to public:\n>\n>                       a---a---a---a  feature-A\n>                      /             \\\n>                     O---o---o---o---*  public\n>                      \\\n>  ...---x---x---x---X---S---x---x   private\n>\n> I depicted such a topic as \"feature-A\" that consists of four commits 'a'\n> in the pictures above.  Since you made the initial merge S, open source\n> world may have added three commits 'o' to improve your system and you also\n> have a few more commits 'x' that are secret.\n>\n> The private branch can take the result of the work done on the topic\n> branch, either by merging public wholesale:\n>\n>                       a---a---a---a  feature-A\n>                      /             \\\n>                     O---o---o---o---*  public\n>                      \\               \\\n>  ...---x---x---x---X---S---x---x-------*  private\n>\n> in which case you will also get the open source improvements 'o', or by\n> merging that particular topic alone:\n>\n>                       a---a---a---a...    feature-A\n>                      /             \\  .\n>                     O---o---o---o---*  .  public\n>                      \\                  .\n>  ...---x---x---x---X---S---x---x----------*  private\n>\n> in which case your private branch will not (yet) have the three 'o' open\n> source improvements.\n>\n> Note that you may consider some of your features \"differentiating edge\"\n> that you may want to keep private for one year and then release it to the\n> public.  In such a case, you can even choose to merge feature-A to private\n> first:\n>\n>                       a---a---a---a...    feature-A\n>                      /                .\n>                     O---o---o---o      .  public\n>                      \\                  .\n>  ...---x---x---x---X---S---x---x----------*  private\n>\n> and after a year, you can merge it to public to arrive at the previous\n> picture.\n>\n>\n\n\n\n-- \nJérôme Martin\n"},{"id":"167196","messageId":"BANLkTinwuGTbX0qeOZHAhGKgZzPBTTaHCw@mail.gmail.com","threadId":"27267","inReplyTo":"201105052110.p45LAViP010495@no.baka.org","subject":"Re: Private/public branches/repos workflow","fromName":"Jerome Martin","fromEmail":"tramjoe.merin@gmail.com","sentAt":"2011-05-05T22:05:56Z","receivedAt":"2011-05-05T22:05:56Z","isPatch":false,"sender":{"key":"tramjoe.merin@gmail.com","avatar":null},"body":"Thanks for the additional clarification on detached vs orphan.\n\nI want to thank you guys again for being so patient and helpful. It\nhelps a lot, as for some reason, only reading the docs doesn't seem to\nsink in as fast as I would like ;-)\n\nRegarding the usage of an orphan branch, a coworker of mine suggested\nan alternate way, which seems similar to me regarding the result, but\nif you could take a look at it and tell me what you think, that would\nbe very helpful:\n\n1) On the public server, init a blank repo, and commit there an export\nof the public tree as initial import.\n2) On the devel machines, use git-remote to track that repo's master\nas a local 'public' branch. That public branch now has no history\nother than the initial import, and is in the same repo as both my\nprivate branch and my public-branch-with-full-history (not to be used\nfor future work).\n3) From there, use this 'public' branch as if it was created using\n--orphan from my local public-branch-with-full-history.\n\nAre there any essential properties that set apart a 'public' branch\ncreated this way from one creating using your suggested --orphan\nmethod ?\n\nOn Thu, May 5, 2011 at 11:10 PM, Seth Robertson <in-gitvger@baka.org> wrote:\n>\n> In message <BANLkTikFdV=nGW-L+3NVzP58uPiS5ui-9A@mail.gmail.com>, Jerome Martin\n> writes:\n>\n>    One thing I do not understand clearly is why with a detached (I guess this\n>    is synonym to orphan ? At least when creating it ?) branch cannot be then\n>    merged with the branch that was initially copied to create it and just get\n>    the additional commits. Instead, it gets the whole history. Being used to\n>    using merge between my public/private branches, I am afraid that using that\n>    orphan branch might lead to disaster eventually.\n>\n> Junio appears to have answered much of these followup questions so I\n> will focus on a slight misunderstand you exhibit here.\n>\n> An orphan branch is very different from a detached head.  A detached\n> head is not on any branch.  Commits on detached heads cannot typically\n> be referenced by any symbolic name and will eventually go away through\n> garbage collection.  In general you want to avoid detached heads for\n> any read/write activity.\n>\n> An orphan branch, on the other hand, is one which simply doesn't have\n> a parent.  The first commit you make in a new repository is also\n> orphan, though it is not talked about as such.  The point of this\n> orphan branch is that since it does not have a parental link from your\n> private branch, if you publish the orphan it will not bring along any\n> of the private commits.\n>\n> As Junio stated/suggested, as long as you are careful to never merge\n> from private into public, and instead either cherry-pick or do\n> development from public and merge that into private, you should be\n> safe.  However, a good safety test might be to have an intermediate\n> repository be part of your public push process, and have a\n> post-receive (or other process) script run which looks for magic\n> cookies in that intermediate repo showing that private data has leaked\n> before proceeding to push that validated repo to a publicly accessible\n> repo.\n>\n>                                        -Seth Robertson\n>\n\n\n\n-- \nJérôme Martin\n"},{"id":"167209","messageId":"7vk4e44gfo.fsf@alter.siamese.dyndns.org","threadId":"27267","inReplyTo":"BANLkTimggn-E+JsXp78_a2P3eWku3oTSbQ@mail.gmail.com","subject":"Re: Private/public branches/repos workflow","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2011-05-06T04:10:51Z","receivedAt":"2011-05-06T04:10:51Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Jerome Martin <tramjoe.merin@gmail.com> writes:\n\n> Could you tell me how you would see usage of rebasing inside the\n> workflow you describe ? I am thinking about features (mistakenly)\n> implemented on top of the private branch that need later to be release\n> in the public branch. Can this be the shortcut to avoid lengthy\n> cherry-picks ?\n\nMistakes and changes of plans can happen, but it's not a big deal.\n\nIn the git project itself, even the \"master\" branch that corresponds to\nyour \"private\" branch is managed with topic branch workflow, so it is\nentirely possible that a topic that was originally meant only for the next\nrelease turns out to be better backported to the maintenance track.\n\nIf you have a private \"feature-A\" topic with many commits:\n\n                     O   public\n                      \\\n ...---x---x---x---X---S  private\n                        \\\n                         a---b---...---z  feature-A\n\nand later it turns out that it is better to release them also to the\npublic, instead of cherry-picking the commits to the public, you could at\nthat point do something like this:\n\n    $ git checkout -b public-feature-A feature-A\n    $ git rebase --onto public private\n\nwhich will first create a new branch \"public-feature-A\" that points at the\nsame tip of \"feature-A\", and then rebases the commits on that branch that\nwere made since the topic was forked from \"private\" on top of the tip of\nthe \"public\" branch, resulting in:\n\n                       a'--b'--...--z' public-feature-A\n                      /\n                     O   public\n                      \\\n ...---x---x---x---X---S  private\n                        \\\n                         a---b---...---z  feature-A\n\nand then you may choose when to merge that to the \"public\" branch.\nBy the time you do this, perhaps the original \"feature-A\" may have already\nbeen merged to \"private\" after fully tested and audited, like this:\n\n                       a'--b'--...--z' public-feature-A\n                      /\n                     O   public\n                      \\\n ...---x---x---x---X---S---x---x---x-----*  private\n                        \\               / \n                         a---b---...---z  feature-A\n\nand then after you merged \"public-feature-A\" to \"public\":\n\n                       a'--b'--...--z' public-feature-A\n                      /              \\  \n                     O---o---...---o--*   public\n                      \\\n ...---x---x---x---X---S---x---...---x---*  private\n                        \\               / \n                         a---b---...---z  feature-A\n\nmerging \"public\" back to \"private\" hopefully may have too many conflicts\nbetween the feature-A and public-feature-A branches, as they are supposed\nto be patch equivalent, to produce this:\n\n\n                       a'--b'--...--z' public-feature-A\n                      /              \\  \n                     O---o---...---o--*---.   public\n                      \\                     \\\n ...---x---x---x---X---S---x---...---x---*---*   private\n                        \\               / \n                         a---b---...---z  feature-A\n\nAfter this you could even garbage collect the two topic branches ;-).\n"},{"id":"167236","messageId":"BANLkTikC23_hi4TppxdfMjCZDJWNd9ZF7g@mail.gmail.com","threadId":"27267","inReplyTo":"7vk4e44gfo.fsf@alter.siamese.dyndns.org","subject":"Re: Private/public branches/repos workflow","fromName":"Jerome Martin","fromEmail":"tramjoe.merin@gmail.com","sentAt":"2011-05-06T09:27:11Z","receivedAt":"2011-05-06T09:27:11Z","isPatch":false,"sender":{"key":"tramjoe.merin@gmail.com","avatar":null},"body":"Again, thanks for the help :-)\n\nOn Fri, May 6, 2011 at 6:10 AM, Junio C Hamano <gitster@pobox.com> wrote:\n> Jerome Martin <tramjoe.merin@gmail.com> writes:\n>\n>> Could you tell me how you would see usage of rebasing inside the\n>> workflow you describe ? I am thinking about features (mistakenly)\n>> implemented on top of the private branch that need later to be release\n>> in the public branch. Can this be the shortcut to avoid lengthy\n>> cherry-picks ?\n>\n> Mistakes and changes of plans can happen, but it's not a big deal.\n>\n> In the git project itself, even the \"master\" branch that corresponds to\n> your \"private\" branch is managed with topic branch workflow, so it is\n> entirely possible that a topic that was originally meant only for the next\n> release turns out to be better backported to the maintenance track.\n>\n> If you have a private \"feature-A\" topic with many commits:\n>\n>                     O   public\n>                      \\\n>  ...---x---x---x---X---S  private\n>                        \\\n>                         a---b---...---z  feature-A\n>\n> and later it turns out that it is better to release them also to the\n> public, instead of cherry-picking the commits to the public, you could at\n> that point do something like this:\n>\n>    $ git checkout -b public-feature-A feature-A\n>    $ git rebase --onto public private\n>\n> which will first create a new branch \"public-feature-A\" that points at the\n> same tip of \"feature-A\", and then rebases the commits on that branch that\n> were made since the topic was forked from \"private\" on top of the tip of\n> the \"public\" branch, resulting in:\n>\n>                       a'--b'--...--z' public-feature-A\n>                      /\n>                     O   public\n>                      \\\n>  ...---x---x---x---X---S  private\n>                        \\\n>                         a---b---...---z  feature-A\n>\n> and then you may choose when to merge that to the \"public\" branch.\n> By the time you do this, perhaps the original \"feature-A\" may have already\n> been merged to \"private\" after fully tested and audited, like this:\n>\n>                       a'--b'--...--z' public-feature-A\n>                      /\n>                     O   public\n>                      \\\n>  ...---x---x---x---X---S---x---x---x-----*  private\n>                        \\               /\n>                         a---b---...---z  feature-A\n>\n> and then after you merged \"public-feature-A\" to \"public\":\n>\n>                       a'--b'--...--z' public-feature-A\n>                      /              \\\n>                     O---o---...---o--*   public\n>                      \\\n>  ...---x---x---x---X---S---x---...---x---*  private\n>                        \\               /\n>                         a---b---...---z  feature-A\n>\n> merging \"public\" back to \"private\" hopefully may have too many conflicts\n> between the feature-A and public-feature-A branches, as they are supposed\n> to be patch equivalent, to produce this:\n>\n>\n>                       a'--b'--...--z' public-feature-A\n>                      /              \\\n>                     O---o---...---o--*---.   public\n>                      \\                     \\\n>  ...---x---x---x---X---S---x---...---x---*---*   private\n>                        \\               /\n>                         a---b---...---z  feature-A\n>\n> After this you could even garbage collect the two topic branches ;-).\n>\n\n\n\n-- \nJérôme Martin\n"}]}