2

I did a lot of searches on this, I apologise if this is a dupe, I couldn't find any answers that directly addressed my issue.

We have a client who will mull over a feature for a while and while doing this will quickly approve another feature.

This means that we make feature branches from master and merge them in to deploy to a QA environment, this is all well and good, but when feature2 is approved before feature1 we need to then merge feature2 into our releases branch without any trace of feature1.

This sounds ok, but this has been going on for a while and there is a constantly different commit history between master and releases.

What we've tried;

  1. Branch feature2 from master and merge feature2 branch into releases - this results in too much unwanted commit history coming with it.
  2. Merge master into releases. See problem 1. Too much history.
  3. Create the feature branch from releases, not master. Good in theory, but far too many conflicts on a regular basis to make it a good option.
  4. Cherry picking. Ergh. This is the only thing we've been able to do and its contributed to our diverged branches.

Does anybody have a suggested workflow for this?

I thought we could branch from master at the point of the releases branch but then I think we'd have the same problems as 2 above.

EDIT

See link two below (What kind of Git workflow suits our case?) - Possibly a 'temporary' branch could work for deployment to the dev environment?

Some similar discussions ;
What git branching models actually work?
What kind of Git workflow suits our case?

Community
  • 1
  • 1
Christian
  • 3,917
  • 2
  • 23
  • 40
  • So currently, your branches are coming off master, having independent features developed on them, and then being cherry-picked into master for QA, and then master is merged into release for release. You are having issues because of merge conflicts between feature branches and master and between master and release, and also because you have too much history in master from the dev branches. Is all that correct? – andyg0808 Jun 05 '13 at 00:29
  • @andyg0808 So, we may gave 5 feature branches, all branched from master. All will have been merged into master for our QA. But, only 2 might get the nod to go to production. So, we have 2 branches that need merging into releases but they might have history relating to the other 3 branches. Hopefully that makes sense? – Christian Jun 05 '13 at 01:03
  • Yes, that mostly makes sense. One thing: why is there history in the branches that go to release from the other branches? I'm imagining that you are merging the features into master to test, but not doing any dev on the merged versions. Are they getting it from when they're branched from master with some unreleased features in testing? – andyg0808 Jun 05 '13 at 01:22
  • Hi @andyg0808 - Yes, when we merge the feature into master it may remain there for an indetermined period. So, an unreleased feature may be present when we branch from master - giving us the unwanted history. – Christian Jun 05 '13 at 03:15
  • Could you explain a bit more about the conflicts that you're having with option 3 in your question (creating feature branches from release)? That's sounding like the most promising direction to me at the moment... – andyg0808 Jun 05 '13 at 04:33
  • If we branch from releases, we get the opposite problem. That is, merging into master for QA breaks horribly. – Christian Jun 06 '13 at 00:04
  • So basically, the feature branches often involve overlapping edits to create each feature, and those edits result in conflicts when you try to merge them, right? Now, what happens when feature1 eventually gets approved (after feature2)? Why aren't there tons of conflicts in the cherry-picking done to move feature1 into release? – andyg0808 Jun 06 '13 at 01:33

1 Answers1

1

Try git merge --squash branchname (docs).

It makes an entire branch into a single commit, thus eliminating the history problem. This lets you follow a pattern where you have a master and release branch that are enduring, and transient feature branches that know nothing about each other. The master is where features are forked from and merged to, the release branch is where master is merged when a release is contemplated, and the feature branches are where the bulk of the development takes place. When a feature is approved, it is merged into master with git merge --squash, which results in master having one commit for the entire feature. Then the feature branch can be deleted if desired. Furthermore, if the feature is not deleted, it appears that it will continue to merge happily back and forth with master, so you could even keep the branch and work on that feature in isolation, periodically using git merge --squash to merge it into master, and git merge to merge master into it (keeping it up-to-date).

If more of the history matters, then you might look at git rebase -i, where you would merge a feature branch into master, then clean up the resulting history with git rebase -i. Doing it in that order means that the feature branches are still the same as everywhere else, while the master branch has some additional commits, representing the development on the feature branch. Ask if that sounds interesting, and I'll try to explain further.

For releases, you could then use either git merge --squash to merge into the release branch, which will keep it even cleaner, or you could pull the (now limited) history of master into release with git merge

Here's what git log might show as the resulting commit graph:

* d779567       master Done
* 298c1c7       master Closer
* 736d826       master Building
| * 4657b01     fdab66dc33 Done!
| * 3af011a     fdab66dc33 Closer...
| * 6372833     fdab66dc33 Closer...
| * d345a43     fdab66dc33 Building...
| * 0b64509     fdab66dc33 Building...
| * 9da143c     fdab66dc33 Building...
| * c99dbce     fdab66dc33 Building...
| * 501a25c     fdab66dc33 Building...
| * 4f999ee     fdab66dc33 Building new feature
|/  
* e891881       master Work on master
| *   3571493   release Releasing version 2!
| |\  
| |/  
|/|   
* | 68f75f0     master Feature 1 done
* | 5dbe17c     master Feature 2 done
| * bbcc8e8     release Bugfix on current release
|/  
* d5732fd       release Work directly on master
* 1098d81       release Initial commit

Working from the bottom: some initial work was done; a release was made, then we realized that we needed to fix a bug in it; we got approval for two features in reverse order from their starting, another release was cut. Then some work happened directly on master. Now things get a little more confusing. The branch on the right (fdab66dc33 is actually the branch name) is a feature branch which has had a lot of commits made to it. The branch on the left is the master branch, and the three commits at the top are the result of merging the feature branch into it and then using git rebase -i to squish some of the feature branch's commits together.

andyg0808
  • 1,367
  • 8
  • 18
  • Ok, but this doesn't seem to help with a very different releases and master branches. We use --squash a lot, I don't see how that helps with a history problem though. If master is very different to releases, then when merging the feature into either of those branches, we will have a lot of differences. Perhaps I am missing something? – Christian Jun 04 '13 at 04:07