In our project, we have 5 teams working on a monolithic application in 3-week sprints. Until now, all commits go into master (via Gerrit). Our test pipeline is too lengthy to ensure quality pre-commit, so we have to accept that some commits break things. I'm aware that the root cause here is the pipeline, and a breaking commit should never reach master. We have to accept this, however, until our pipeline redesign is complete, and this will take several months in the least.
We're now discussing the approach of "team branches", where each team would develop and commit on their own branch, and update the master periodically. The heated part of the discussion revolves around merge or rebase. Our current understanding is:
Rebase
- On branch-team1:
git rebase origin/master
- Resolve conflicts
- Push to branch:
git push origin branch-team1 --force-with-lease
- Finally, rebase master:
git rebase branch-team1
With this approach we see commit IDs changing (due to rebase + push --force), and part of our change history is invisible to Gerrit. The former has the effect that the entire team needs to halt work during the rebase, as their un-pushed work might get messed up due to the changing commit history.
On the plus side, this approach yields an easily readable history on master. Each commit is visible, and can be cherry picked or reverted.
Merge
- On master:
git merge origin/branch-team1
(+ resolve conflicts) - On branch-team1:
git rebase origin/master
The main concern expressed here is that the history becomes much harder to read, as the master will mainly contain large "composite merge commits". For debugging/blaming, the associated team branch would have to be checked for the further history. Also, reverting a single commit (originally on a team branch) becomes more tedious.
However, a short proof-of-concept indicates that the history is no different to the Rebase approach, except for the actual merge commit. Similarly, cherry picks / reverts seem just as easily done, with the sole exception being if part of the cherry pick / revert would actually be a change made during conflict resolution and thus part of the merge commit. This, however, seems a tad far-fetched.
A third way?
It seems both approaches have negative aspects (personally I don't see much negative in the merge approach, but others on our project are clearly against it). It's a bit hard to believe that with the power and popularity of GIT, there isn't an established approach available which doesn't require squabbling over.
Does anyone have some practical experience to share here?