6

I'm attempting to work out the best way in which to select a subset of commits from one branch to another with minimal affect on history (such as duplication of commits) for my particular workflow. Here's a description of my workflow, plus the scenario I'm attempting to use it in.

Workflow

master: Represents what's currently on the production servers.

develop: The code on the production servers, plus the latest changes that have been code-reviewed. Barring any problems, develop will be merged to master when the next release to production is performed.

feature-x: Branches for new features, taken from the head of develop. Pull-request made to develop, merged when it passes code-review.

Scenario

feature-1: is developed, passes code-review and is merged to develop.

feature-2: is developed, passes code-review and is merged to develop.

feature-3: is developed, passes code-review and is merged to develop.

Client decides feature-2 should be released without feature-1 and feature-3. feature-2 is a stand-alone change, i.e. it does not depend on anything introduced in feature-1.

I now need to get feature-2 in to master, without feature-1 or feature-3.

Suggested approaches

If I attempt to do a separate pull-request of feature-2 into master, then this will also release feature-1, as feature-1's commits are present in the feature-2 branch.

If I attempt to git cherry-pick the commits from feature-2 into master, the commits will be duplicated when develop is next merged to master (i.e. when the next release occurs). Testing this with a trivial example merged cleanly, but git log displays duplicate commits for anything included in the feature-2 branch.

Are there any alternatives? I can live with a slightly untidy history in this instance if there's no way around it, but the ideal solution would avoid duplicate commits. I'd also like to avoid rebasing master or develop, due to the fact that there will potentially be other feature-x branches active when this happens.

Any help appreciated.

ChrisC
  • 2,385
  • 1
  • 14
  • 25
  • 1
    Have you considered release branches? – Sascha Wolf Jan 26 '15 at 14:08
  • I'm not sure what you mean: We're essentially using master as our release branch, with the intention that develop essentially insulates master from receiving the latest changes. I'm not really looking to change the workflow at this point: I'm open to changing that in future, but more pressing is the need to deal with this scenario using the existing workflow right now. – ChrisC Jan 26 '15 at 14:10
  • You wouldn't need to change your workflow deeply. Personally I would create a release branch from the last release of development and then merge the necessary feature branches into this release branch. Based on this you can revert all changes of feature-1 in the release branch. In the end this release branch would be merged into master rather than directly merging development. – Sascha Wolf Jan 26 '15 at 14:25
  • In reverting the changes in the release branch to get rid of feature 1, wouldn't this pollute the history even more? Master would be left with the feature-1 commits, plus commits for the revert of feature-1, then commits for feature-1 again when develop was next merged to master. This could be resolved, but only by rebasing develop/master, which I'd like to avoid. – ChrisC Jan 26 '15 at 14:47
  • Personally I wouldn't consider this "polluting" master. If each commit on master represents a release and each of this commits is well documented (speaks: has an informative commit message) there is little to no need to take a look at the merged branches (`git log --first-parent`). Directly cherry-picking onto master, even if you squash those commits, would imo result in an unclean history, since you wouldn't have a reference on the "merged" branch. – Sascha Wolf Jan 26 '15 at 14:55
  • As I see it, you have the choice: Either you cherry-pick the feature-2 commits specifically (maybe use a release branch for that too) or you use the approach (or something similar) I suggested. There may be another way but I can't see it. – Sascha Wolf Jan 26 '15 at 14:55
  • Many thanks for your help. When I mentioned in the original question about having tested with a trivial example, I actually did so using a release branch (i.e. a copy of master, with commits cherry-picked from develop, which was then merged to master), so I think we're on the same page with regards to release branches. I'm also struggling to see another way, without having revert commits added to master - It might just be a case of choosing the lesser of two evils (revert commits vs duplicates). – ChrisC Jan 26 '15 at 15:03
  • Maybe you are already familiar with the workflow but I can suggest [gitflow](http://nvie.com/posts/a-successful-git-branching-model/) as a very well thought out workflow. It's similar to your approach but has some subtle differences. Since you said you would consider modifying your workflow in the future. – Sascha Wolf Jan 26 '15 at 15:06

1 Answers1

0

Using the first approach you suggested, slightly modified: simply create feature branches from the last point develop was merged on master.

On the following scenario, LM commit represents the last merge from develop into master and LC the last commit of develop.

----o---------o-----------o------------o--------> master
   /         /            /           /
--o--o---o--o---o---o----o-----o-----LM---o---o---LC------> develop

Instead of creating a new feature branch from the last commit:

----o---------o-----------o------------o--------> master
   /         /            /           /
--o--o---o--o---o---o----o-----o-----LM---o---o---LC------> develop
                                                   \
                                                    ---------> feature_branch

create the feature branch from last merge:

----o---------o-----------o------------o--------> master
   /         /            /           /
--o--o---o--o---o---o----o-----o-----LM---o---o---LC------> develop
                                      \
                                       ------------------------> feature_branch

This way you can create pull requests from feature branches without other "new" features.

Jean Waghetti
  • 4,571
  • 1
  • 16
  • 28
  • Thanks for your response. Unfortunately, this isn't feasible for two reasons. Firstly, it doesn't cope with the case when the development of a feature requires code that's in the latest develop. For example, feature-3 in my example might rely on code added by feature-2. Secondly, this is a change to the workflow: It does not help me resolve the existing scenario that I am in. – ChrisC Jan 26 '15 at 14:44
  • I see your point and I understood it from the begin. I doubt there's a way to solve the existent problem without rewriting repository history, without problems with future merges if cherry-pick is used or "discarding" the commits made and creating new ones with a workflow that fits better the needs of your development/release cycle. The workflow I suggested was the solution to future problems, without changing the branching scheme you have, only modifying where they are created and how to merge to avoid conflicts. – Jean Waghetti Jan 26 '15 at 15:37