Home > Software engineering >  How can I merge two protected branches in git when they are not in sync?
How can I merge two protected branches in git when they are not in sync?

Time:01-24

I have a GitLab repository for my application. Following some guidelines (https://nvie.com/posts/a-successful-git-branching-model/) I created a "main" branch that mirrors the production version and a "develop" branch that mirrors the version currently under acceptance test. After finishing the acceptance test, the develop version is rolled out and will be merged into main.

All worked fine until recently we had to ship an emergency change. For this, I created a branch off main, committed the changes and merged them back to main.

Now we have the next scheduled release ready on develop, so I created a merge request from develop to main. This merge request tells me that develop is 2 commits behind main (which isttrue due to the emergency branch). So I create a merge request from main to develop. Now this one is also behind develop (which is true due to the regular functional updates in this release).

In the emergency change we changed a file that should not be changed in the developmen branch (a quickfix, that we solved otherwise in the main release).

Now I cannot merge develop into main because I have to dvance develop to the main head, but I cannot do this because I would have to commit the "main" changes (or their override) into develop which is protected.

Creating a new branch to incorporate the main changes into a merge request to develop did not work.

What is the correct way to move develop to the head of main while not being able to directly commit to develop (or main)?

CodePudding user response:

It sounds like you have a setting which forces an incoming branch to be fully up to date with main before merging into main. This is fine to help prevent the scenario you almost found yourself in, which is when you have a hotfix, and you don't merge those changes back into develop, and then the next time you deploy to production from develop you blow away the changes in the hotfix.

If you are using that setting, you only need it enabled for merges into main. You don't need to have that setting enabled for merges into develop, though there is a workaround for that if you wish to leave it on for develop as well.

Normally, after merging a hotfix into main, you should immediately then merge main into develop.1 Since develop is a protected branch in GitLab, this might simply mean creating a Merge Request from main into develop. In some cases you cannot create a MR directly from main into develop, and instead need to use an in-between temporary branch, for example if:

  1. There are conflicts when merging main into develop.
  2. There are not conflicts, but there is at least one change that you don't wish to be applied to the develop branch.
  3. You have enabled the flag on develop that all incoming merges must be up to date with develop.

Regardless of which of the above reasons for the exception, the solution to creating the in-between branch is the same (these commands assume your remote name is origin):

# get the latest code
git fetch

# create a new temporary branch starting from the latest develop
git switch -c merge-main-into-develop origin/develop --no-track

# Merge in main
git merge origin/main
# resolve conflicts if needed and continue to complete the merge

# push out your branch and set it to track the new branch
git push -u

Now you can create a PR from merge-main-into-develop into develop.

If you happen to be in exception scenario #2 above, where you don't wish to actually bring all of the hotfix changes from main into develop, you have a few options:

  1. If you want some files but not all, you could change the merge command to be git merge origin/main --no-commit. This will pause the merge with the files saved, and you can modify the index however you need to before committing. You might choose this option if you have some version files that were modified on main that you don't wish to update on develop. Consider updating the merge commit message to explain what you are changing and why.
  2. If you don't want any of the changes from the hotfix to be brought into develop, perhaps because you already fixed the same thing in a different and preferred way on develop, you could use the merge strategy "ours, by modifying the merge command to be: git merge origin/main -s ours. This will bring in the commits but without any of the changes. Consider updating the merge commit message to explain why you are doing this.
  3. A similar method to number 2 is to accept the merge as is, but then revert the merge with a commit message explaining why. This has the same effect as #2, but creates one additional commit. The advantage of this method is it's easier to predict what happened simply by glancing at the commit message titles.

Ultimately, the key idea here is you need all of the commit IDs that are on main to be present on develop before merging develop back into main.


1 The Git Flow documentation suggest merging hotfix into main and then also merging hotfix into develop. That will produce the same state but will not contain the new merge commit created on main (which is recommended). By merging main into develop instead you bring that new merge commit over as well and will therefore keep develop up to date with main. Note this also means you'll need to merge main into develop right after merging develop into main, just to bring over that merge commit!

  • Related