0

I'd like to always have a no fast-forward effect on the base branch (creates merge commit always). Based on the following Bitbucket settings used by my team it appears sometimes 2 merge commits will need to be created in order for conflict-resolution.

Bitbucket Server Branch Settings

  • Changes without a pull request - prevents pushing changes directly to the specified branch(es); changes are allowed only with a pull request. Branch Permissions

  • Merge Commit (--no-ff) Always create a new merge commit and update the target branch to it, even if the source branch is already up to date with the target branch. Default Merge Strategy

Since the base branch can only be changed via pull-requests, and it always creates a merge commit on PR-merge, therefore it appears pull requests that require manual conflict resolution will have to have 2 commits.

Problematic Scenario example:

Here is the scenario: the base branch gets merged onto the feature branch to manually resolve the conflict, in this case the manually resolved conflicts result in a merge commit. Then after pushing the conflict-merge commit then the PR will be updated and ready to merge, and upon merging to base it would then create yet another merge commit (due to no-ff option). Technically only 1 of those 2 commits were needed. When done directly in git (without pull request and without locked down branch) this could have been achieved using no-ff by merging directly onto the base branch.

Is there something I'm missing here? Is there a way to achieve exactly 1 merge commit using Bitbucket Server pull request restrictions?

progner
  • 3
  • 3

1 Answers1

1

This is the expect result if you have set merge changes into the base branch via PR and with no-ff merge strategy.

Assume the base branch is master branch, and the pull request is for merging feature branch into master branch, and the commit history as below:

…---A---B---C---D     master
             \
              E---F  feature

If you resolve the merge conflict by merging master branch into feature branch with default merge strategy, and after completing the PR, then the commit history will as below (commit G is the first merged commit and commit H is the second merged commit):

…---A---B---C-------D---H     master
             \       \ /
              E---F---G  feature

In order to make the commit history look clearly, you can change the way to resolve merge conflict by git cherry-pick or squash merge strategy.

  • If resolve the merging feature into master branch’s merge conflicts with git cherry-pick:

    git checkout feature
    git cherry-pick D
    # resolve all conflicts
    git add .
    git cherry-pick --continue
    git push origin feature
    

    After completing PR, the commit history will be:

    …---A---B---C---D-------M     master
                 \         /
                  E---F---D'  feature
    
  • If resolve the merging feature into master branch’s merge conflicts with squash merge:

    git checkout feature
    git merge master --squash
    # resolve all merge conflicts
    git add .
    git commit
    git push origin feature
    

    After completing PR, the commit history will be:

    …---A---B---C---D-------M2     master
                 \         /
                  E---F---M1  feature
    
Marina Liu
  • 36,876
  • 5
  • 61
  • 74
  • Thanks for your explanation. I might be doing something wrong, I tried both examples and it still requires conflict-resolution to merge to master. In this command series the last squash commit won't actually commit anything: `git init; echo "A" > "f"; git add f; git commit -m "A"; echo "B" > f; git add f; git commit -m "B"; echo "C" > f; git add f; git commit -m "C"; git checkout -b feature; echo "E" > f; git add f; git commit -m "E"; git checkout master echo "D" > f; git add f; git commit -m "D"; git checkout feature; echo "F" > f; git add f; git commit -m "F"; git merge master --squash` – progner Jul 11 '18 at 21:24
  • Checking the git status after it wouldn't squash-merge into the feature branch "On branch feature nothing to commit, working tree clean". I wonder if because the contents of F stayed the same after conflict-resolution git was smart enough to not merge in something that would have been resolved to be the same again prior to merge. – progner Jul 11 '18 at 21:31
  • I tried again, this time updated to not fully replace conflicted text. This time it created the squash commit with these commands but still had to resolve conflicts again anyway back on master after. `git init; echo "A" > "f"; git add f; git commit -m "A"; echo "B" > f; git add f; git commit -m "B"; echo "C" > f; git add f; git commit -m "C"; git checkout -b feature; echo "E" > f; git add f; git commit -m "E"; git checkout master; echo "E_keep_D" > f; git add f; git commit -m "D"; git checkout feature; echo "EF" > f; git add f; git commit -m "F"; git merge master --squash` – progner Jul 11 '18 at 21:40
  • @progner Yes, the squash merge must has merge conflicts. You can thing on the opposite: when create a PR to merge `feature` branch into `master` branch, there has merge conflicts for the `f` file (the content of `f` file on `master` branch changes with the content "E_keep_D", while the content is "EF" on `feature` branch). The purpose to sqush merge `master` into `feature` branch is change the file `f` on `feature` branch same as the content on `master`, so that the PR can merge with no conflicts. – Marina Liu Jul 12 '18 at 09:04
  • @progner The situation won't nearly to happen after you protecting `master` branch. That means, no changes can be pushed to `master` branch directly afterwards. The same file will mostly changed only from one side (feature branch). – Marina Liu Jul 12 '18 at 09:07
  • Fair enough, but if another feature branch merges first then it is back to the same situation. From my testing it appears anytime conflicts are resolved on a feature branch by bringing in master changes, they will for sure have to be resolved again once merged into master. Since Bitbucket server doesn't handle merging this seems to be impossible to avoid until Bitbucket adds in a conflict-resolution feature. – progner Jul 12 '18 at 19:40
  • @progner For most 3rd-party place to host remote git repo, like bitbucket, github etc, it requires to resolve the merge conflict manually. And it your example, the file f will truly to go to the original version since there has only one file for test. And you can rebase the feature to the latest master branch after another feature branches merged into master branch. The commands as: `git checkout feature`, `git pull origin master --rebase`. – Marina Liu Jul 13 '18 at 02:04
  • @progner Can you resolve the merge conflict by squash merge or cherry-pick successful now? – Marina Liu Jul 16 '18 at 08:58
  • I prefer to not rebase (I like the individual commits + merge commit). I think your initial statement answers my question: `This is expect result if you have set merge changes into the base branch via PR and with no-ff merge strategy`. Ideally only 1 merge commit would happen, but PRs are an automated operation and can't resolve conflicts. Thanks for your help! – progner Jul 19 '18 at 19:54