11

Some background:

Currently on CVS and looking to move to Git. We do planned releases for our complex custom internal platform every month or so.

In current development workflow, we have multiple branches, one for each of our planned release, such as an example:

  • Release 7000, that will probably go out in May
  • Release 7100, that will probably go out in August
  • Release 7200, that will probably go out in September

(we can have half a dozen planned releases being worked on at the same time).

We also have named project branches, for larger projects that don't have a release date at the moment. They eventually get merged into a selected planned release branch, when the date becomes known.

Each release is quite large (many features), as releases require outages, we can't have them too often, we literally can get approval for release downtime once every month or so.

With this come merge conflicts. We have a CVS report that provides a list of manual merges that are to be done, and we split the work between a few developers. Any way to do the same with Git - to split up merge work for merge from one branch to another (resulting in many conflicts) between multiple developers?

EDIT:

This is what I ended up doing (note that we are using Atlassian Stash/BitBucket Server for pull request / code review):

  • Merge daemon: Create a new "manual merges" branch from the target branch
  • Merge daemon: Start merge to get list of conflicts
  • Merge daemon: Notify managers and wait for conflict resolution
  • Manager: Divide conflicts between developers
  • Developers: Each developer creates and checks out "feature" branch from the merge branch, then start to merge source tag to their feature branch - they get the conflicts in their environment. They resolve conflicts only for the files they are responsible for, then do a soft reset to abort the merge, and commit only the files they resolved. Then they merge their feature branch (with review) to the "manual merges" branch.
  • Merge daemon: Once conflicts have been resolved by developers, check out modified files from "manual merges" branch (only the files that changed). At this point all manual conflicts should be resolved. Commit and push.
Pavel Chernikov
  • 2,186
  • 1
  • 20
  • 37
  • 1
    The answer in your edit sounds reasonable, but it does not work for me. git reset --soft origin/ result in "fatal: Cannot do a soft reset in the middle of a merge." Are you using a different command for the reset? – Father Stack Jan 05 '18 at 17:40

4 Answers4

3

Assuming your developers each have their own clone of the repository, there is no way to split up a single merge-and-conflict-resolution effort in the same branch across all these clones. When a developer performs a git merge on her branch and encounter conflicts, the merge remains "in-progress" (hence, no further commits can be made) until all conflicts in that branch is resolved and the merge completed with a merge commit.

That said, you can still assign each developer to resolve conflicts on a different branch in his own cloned repository; just not multiple developers on a single branch.

If you really have to stick with the existing branch set-ups and that you can cleanly partition the conflict resolution works without team members stepping on each toes, you can experiment with having a common repository on a shared machine where everyone can access (say, via ssh). Just do a git merge, and the conflicts identified in the output is your report :-)

In general, avoid letting the branches deviate too far from each other, by merging them often. Having a merge fest, especially near the release date, can be very stressful and error-prone.

A side note on your comment on restricted release cycles due to strict SLA, have you considered different release techniques such as blue/green deployment or clustering strategy (appropriate to your product) that might help to reduce downtime and mitigate risks?

ivan.sim
  • 8,972
  • 8
  • 47
  • 63
1

Here's one approach:

  1. Start the merge
  2. Use git diff --name-only --diff-filter=U to print a list of merge conflicts
  3. Use git reset --hard HEAD to reset to before you began the merge

But, it's better to just not let these things build up rather than have a massive conflict resolution exercise which may introduce more bugs.

You could do this by making 7100 a branch off of 7000 instead of master, and regularly rebase or merge 7000 into 7100.

You could also do this by keeping each feature on separate branches (feature-a, feature-b, etc.) and merge them in one at a time when you're near a release and you know for sure what'll be in it.

Aaron Brager
  • 65,323
  • 19
  • 161
  • 287
  • Unfortunately having smaller releases is not possible due to only being able to get down time approved (most changes pretty much guarantee to require downtime) only every-so-often. Branching 7100 from 7000 is not always possible either, since they might actually start from the same point. Regular rebasing or merging is a good suggestion, thanks for that! – Pavel Chernikov Apr 13 '15 at 04:49
  • Using "git diff --name-only --diff-filter=U": how would splitting up the merge work with the list of conflicts provided to individual developers? Would they cherry-pick commits to be merged? – Pavel Chernikov Apr 13 '15 at 04:50
  • I don't mean have smaller releases, I just mean keep each individual sub-feature on its own branch, until you're getting closer to a big release. – Aaron Brager Apr 13 '15 at 16:45
  • Yes, you would use cherry-pick if you want to get individual commits vs. my suggestion of using small feature branches. (Read [this answer](http://stackoverflow.com/a/881014/1445366) about the caveats.) – Aaron Brager Apr 13 '15 at 16:46
  • Problem with keeping individual sub-features on own branch until getting closer to a big release is automated testing - some of these features are parts of a larger project, plus need to be able to run automated tests to ensure all the little features play well together. – Pavel Chernikov Apr 13 '15 at 23:28
1

Oh gosh our team recently went through this and were initially frustrated with this limitation. Merging from branch "source" into "destination", our (admittedly hackey) solution was:

  1. For each team member, we cloned on our individual machines copies of "destination" as "destinationMerging".
  2. Each of us then, inside the destinationMerging directory, did 'git merge source'
  3. This produced a list of conflicted files. We set up a checklist of the conflicts that all of us could edit. (You could possibly do this in Google Docs.)
  4. We than began merging the conflicts file-by-file. When one of us would start working on a new file, we would check it off the list. Checking off means "it is done or it is being worked on".
  5. When we would finish with a file, we would copy it to the original "destination" repo and commit/push those changes.
  6. When all conflicted files were resolved and pushed, one person then, from "destination", did a pull to get all of the changes and proceeded with the 'git merge source'

Absolutely inelegant, but it got the job done. I understand that "it's better to just not let these things build up" but when they do, they need to be fixed and this was how we were able to do in a distributed manner.

Brian Risk
  • 1,244
  • 13
  • 23
  • 1
    Hey Brian. See my latest EDIT in the question. We've come up with a pretty elegant and mostly automated solution. I'll see about putting it up on github at some point when it's a bit more polished. – Pavel Chernikov Mar 03 '16 at 19:46
0

Maybe Gerrit, loosely speaking a "Git server", could help you: It has the concept of changes. Each change is owned by a user (usually the developer). The developer may push a feature to a future release branch but it will not be applied to the branch directly (e.g. by pushing to the magic branch refs/for/release-7100).

As soon as someone (e.g. the release manager) decides that this feature should really be taken over, the change can be submitted. If the release branch has diverged to much in the meantime, the developer will be notified and needs to resolve the conflicts. After pushing the resolved conflicts, the change can finally be submitted again.

I have not tried out this workflow by myself but I imagine this could work. In any case, I think it's worth a try… ;-)

siegi
  • 5,646
  • 2
  • 30
  • 42
  • We are planning to use Atlassian Stash, as it provides good Jira integration. – Pavel Chernikov Apr 13 '15 at 14:38
  • So maybe Atlassian Stash provides such a feature, too? I don't know this product, but apparently it provides "Pull request". I guess you could use this to develop a similar workflow… – siegi Apr 13 '15 at 16:59