I begun a workflow where I aim to do all new features in a development
branch and the master
branch will only be for production ready code.
After doing the following:
git checkout master
git merge staging
I received a bunch of conflicts looking like this:
CONFLICT (rename/add): Rename app/assets/stylesheets/mobile.css->app/assets/stylesheets/application.css in HEAD. app/...
CONFLICT (modify/delete): app/views/organizers/mobile.html.erb deleted in HEAD and modified in staging. Version stagi...
CONFLICT (modify/delete): app/views/events/mobile.html.erb deleted in HEAD and modified in staging. Version staging of app/v...
When I now have been googling this, all I read is about reviewing each and every file, resolving the conflicts and commit the changes. But I don't see any point in doing all this, as I know the code and it's only an advancement of the same code set.
How can I merge the changes done in staging
into master
in a simple manner without having to review and resolve each and every change?
This can be resolved by creating a new branch that's identical to master, then merge that.
Merge conflicts happen when you merge branches that have competing commits, and Git needs your help to decide which changes to incorporate in the final merge. Git can often resolve differences between branches and merge them automatically.
This is a complex problem because it basically means that git
cannot figure out intuitively how to combine the two branches. It appears that some files were deleted on master
that are then modified in (and therefore used by) staging
while another was renamed in master
yet added to on staging
. The following will mostly be a shot in the dark, and you may still have to manually resolve some (but hopefully fewer) conflicts.
There are a number of different algorithms for merging that git
can choose from, so we'll use the one that is simplest, easy to customize, and usually used by default: the recursive strategy. And we'll force its use with the option -s recursive
.
The first step to helping git
would be to have it spend more time refining the patches, so we'll use the option -Xdiff-algorithm=histogram
. This will take the longest but it will force git-merge
to produce a better diff output (which will hopefully reduce the conflicts).
The next step is to tell git-merge
to spend more time on doing a correct merge. We'll use the use the -Xpatience
option to do this.
Since master
will depend on the renamed/modified file, while staging
will depend on the old file, we can try to trick git
into thinking that the file wasn't really renamed with the option -Xrename-threshold=100%
(so that the files have to be identical to be considered a rename). Note that you may have some redundant files left over and any changes to files that need to be aware of the other file names won't record old names (just the new ones) so you may want to go back and fix those once you've completed the merge. You could also adjust that 100%
to something smaller (the default is 50%
and that's currently causing a problem).
Now to include the files that are needed by staging
we can use the following option to force them to be added: -Xtheirs
. WARNING: this option will silently ignore all merge conflicts and simply use the content of staging
by default. Make sure to run a full test suite to check for any inconsistencies. If you do have problems in the test suite after the merge, undo it with git reset --hard HEAD^
and redo the merge without this option. You will likely have a small number of merge conflicts that you'll have to settle manually, but you will know that the source of the errors is from one of those (finitely many) conflicts, which is huge leap forward from guessing in front of a debugger.
Finally, we put it all together to get
git checkout master
git merge staging -s recursive -Xdiff-algorithm=histogram -Xpatience -Xrename-threshold=100% -Xtheirs
Lastly, I suggest you play around with the options. The extra time spent on the merge may make the last two options useless (and even make it worse).
In the future, I suggest you regularly pull any changes in master
to your topic branches. This will not only present the conflicts earlier (and thus there are fewer of them at a time) but it will also keep you up to date enough that you may even resolve the conflicts before they occur. The other reason that this is good is because git
has a feature called git-rerere
that records the conflicts that you resolve manually and then learns how to resolve those same conflicts automatically for you later. So once you resolve it once, you won't have to resolve the same/similar conflict over again.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With