22

I'm currently working on a project with a team that's using a git workflow. It's fairly simple: master should be in a deployable state and branches are used to create features and hotfixes. Whenever we have a feature or bugfix completed and tested then we move that over to master as soon as we can. The idea is that branches should be as small as possible to make it easier to merge them back into master. We have a policy that any code pushed to master branch should be in a deployable state and pass the tests.

We have got a situation where one of the developers has done a lot of work (a few months worth) on a single branch and this branch hasn't been merged back into the master yet. There's now a few separate features and a bunch of commits on this branch. Essentially, this branch really should have been merged back in a few times already but so far hasn't been. Most of the code is in a good state with unit tests that could be merged back into master but the most recent changes should certainly not be as they are not completed and aren't tested.

What is the best way to deal with such a situation where one branch is really far away from the others? What ways can we avoid branches getting a very large number of commits away from master in the future?

2
  • Is this in a business or open source project? I think the answers on how to handle it would be different. If business, then it points to some process issues. If it's open source work then you'd want to handle it differently.
    – Daenyth
    Aug 18, 2016 at 12:55
  • @Daenyth This particular situation was a in business context. I'm interested in what you think the best approach would be in an open source project.
    – shuttle87
    Aug 19, 2016 at 0:52

5 Answers 5

15

Let the developer who went for a couple of months without merging fix it. Maybe they can get one big chunk of code to merge, maybe they can get a bunch of little chunks to merge one at a time. In any case, they should be doing the legwork to fix the problem, since they caused it.

What is the best way to deal with such a situation where one branch is really far away from the others?

In general, don't worry about it: it's the other developer's problem. If two branches are really too far apart to merge, then they aren't really part of the same project anymore and you have a defacto fork. If it's an open source project, that may not even be a problem.

If this developer is really brilliant, and their code is better/smarter/more important than the rest of the team combined, then it's worth making it your problem instead of theirs. Otherwise, it isn't.

To answer the literal question: the best way to deal with this kind of situation is to not get in that kind of situation.

What ways can we avoid branches getting a very large number of commits away from master in the future?

Make sure everyone notices that the developer who went for months without merging is having to fix the problem they caused. Make sure everyone knows that it's easier to commit to master frequently than infrequently, since fewer changes means fewer opportunities for conflicts.

Make sure that people know that they can pull from master to stay up-to-date with other people's changes.

"If you merge every day, suddenly you never get to the point where you have huge conflicts that are hard to resolve." --Linus Torvalds

That quote is from a talk he gave at Google, here's the transcript, and here's the video.

1
  • 2
    The problem may have been caused by things outside of the developer's control. For example, a manager might say "I want this big feature developed, but I don't want it to contaminate production code until X date" (real-world managers do that kind of thing all the time). In fact, you'd have to wonder what the manager was thinking if they're still paying a developer whose code isn't reaching production. In any case, I'd advise against playing the blame game because that just makes your organisation an unpleasant place to work. Jan 28, 2021 at 1:05
5

If you have a commit that you know this and all previous commits is well tested and should be merged, then simply branch-out from this last good commit and merge the new branch with master.

If you have some commits that you would like to merge, but they are interspersed with other commits that are not production-ready, then I see 2 possibilities:

  1. Create new branch, and cherry pick good commits, merge with master.
  2. Try to rebase unwanted commits to the top (maybe on new branch just to be safe).

As for prevention methods, try to define some funny team rules like "One that does not merge with master within a week will order pizza for a month".

1
  • I love that funny team rule <3 Jan 5, 2022 at 16:57
2

Fixing the issue of the large pull request is one thing, and there are some good answers regarding that. But as for dealing with branches that get far out of date, you might want to revisit your processes for dealing with team work.

If you're working within an Agile or SCRUM framework, the team should really be asking why the feature wasn't completed and merged as part of the iteration/sprint. If it was "too big" to fit within an iteration, it should have been broken down into smaller chunks.

It also raises a question of code ownership -- within your team, do individual developers own their own work separately, or does the full team work together to ensure that items done?

Of course, the above assumes that your team is within some kind of company structure. If this is an open-source project with volunteer contributors, that's another story. Generally such projects have looser control over workflows, but the onus for generating acceptable pull requests falls more often on the individual contributors.

In many ways this becomes a process question. Maybe your needed process includes checking periodically (weekly? monthly?) for long-running, unmerged branches. Some tools make this simple to check visually; e.g. on github visit the "branches" link and it shows how far ahead/behind each branch is.

1
  • The large pull request may manifest due to there being low PR velocity which means that it would not be possible to meet deadlines by performing sequential work, merge, work, merge patterns. One possibility would be to branch on from unmerged branches, but this becomes unwieldy very quickly and you end up with duplicated work all over the place. So in essence you need to have high PR throughput otherwise the whole system can get out of kilter quite rapidly, leading to these kinds of issues.
    – Den-Jason
    Jan 12, 2021 at 1:29
2

Here is a simple solution.

Track the features that this person has implemented and go to each commit on that branch which was updated per feature. Take this commit and merge it with the master repo.

Let me break this down in the form of an example.

> Let: Branch A be the branch from the master
>      Branch A+ = Branch A + new feature 1
>      Branch A++ = Branch A + new feature 2
>      and so on and so forth
> 
> What you need to do is to go back to: Branch A+
> 
> Take Branch A+ and merge it with Master.
> 
> Now go to Branch A++ and merge it with (Master + Branch A+).
> 
> Repeat until you've reached the final Branch A+...+ that is stable.

This method may sound counter-intuitive at first, but if you merge each separate new feature on its own with the master, it becomes easy to cycle between the master branch "per added feature"

What ways can we avoid branches getting a very large number of commits away from master in the future?

I think my solution above indicates what future method you should be adopting. Go with a per feature or per task method for each branch.

I would suggest using an approach of:

pre-master and master

master: Final/production level. Is modified not often. Is considered always stable

pre-master: the area where a new feature is added to existing code. Is tested thoroughly to work with existing code-base, and is the place where other branches can fork for new feature implementation.

You should also try bundling features and aiming for version-targeting.

Version-targeting: Specify an arbitrary number that will act as the placeholder for the master branch. "In V1.0.0, we will want to achieve X, Y, Z features. V1.0.0 will also have all these functionalities available: ..."

By maintaining a version against master, it can also be a way of keeping "master" stable and production-ready at all times.

1

First, see if there truly are separate commits that can be merged or cherry-picked, like suggest by @Maciej Chalpuk. If this is the case, then the situation really isn't that bad, and I wouldn't worry too much about it in the future.

However, if the real situation is that multiple features have been developed concurrently in a single branch, within the same commits, then it becomes a much larger pain to deal with. Luckily, the prevention method is built in: require the developer to separate out the changes for each feature into separate branches and pull requests before merging them in. You'll both get your atomic merges, as well as dissuade this developer from doing it in the future.

The actual process of separating out the features is entirely manual. Create new branches off of master, and copy in whatever changes from the mega branch that are related to it. Compile, test the feature, push and issue a pull request. The less intermingled the code changes are, the easier it will be to do. If he was hacking a single method for all of them, well, have fun. He won't do it again.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.