How to undo a merge
UPDATE January 14, 2020: Learn more about subtractive merges in the Plastic Book or in the Advanced version control pocket guide.Reasons to undo a merge
There’s no software free of bugs which means you’ll deal, sooner or later, with a branch that introduces a bug.
Hopefully your automatic test suite will detect it. Otherwise an unhappy customer will do it for you. In either case you will need to revert a merge to remove the functionality that is causing the issue and then you’ll have make the release stable again.
There’s also another reason to undo a merge that doesn’t mean you’ve a nasty bug: sometimes you simply need to remove a task branch because the team changed their mind and decided to postpone it to a future release.
How to undo a merge (subtract a merge) with Plastic
Plastic SCM provides an easy way to revert a merge operation while keeping the code history. We call it “subtractive merge” and it is way much easier than it sounds.
I’ll explain how it works with an example. Consider the following scenario displayed in the image below: I've just merged the “/main/issue32” and the “/main/issue33” task branches into the “/main/Release_500” integration branch.
We strongly recommend you run your testsuite (at least part of it depending on how fast it is) after each task branch is merged. This way you can check that everything still works once merged together.
Sadly it wasn’t that easy with the “issue32” branch; this branch introduced an issue that only showed up when it was combined with the branch “issue33”.
Now that we know where the issue is coming from, we need to move forward with the release. The whole “main/Release_500 branch” is affected by the issue so we need to take “issue32” out of release being built.
In order to do that we will subtract changeset 178, the one introducing the changes of “issue32” into the “Release_500” branch.
A subtractive merge from the changeset #178 does the job (red merge link), returning the branch to a stable status.
The changeset #180 is now ready to be integrated into the “/main” branch in order to generate a new release.
Merging back from a branch that has been subtracted
Sometimes the release can’t continue once the faulty bugfix has been removed. Sometimes we can proceed with the release and simply merge the “reopened” task later on.
In both cases we’ll need to merge “issue32” again.
The developer continued working on “issue32” and created a new changeset to solve the problem.
Once the “issue32” task branch is ready again to be reintegrated you will need to perform the following actions:
- Cherry-pick (ignoring traceability) the subtracted changeset (purple merge link).
- Merge from the task branch again (green merge link).
You’ll need the cherry-pick operation to bring back all the changes removed by the subtractive merge and then the second merge from the “issue32” branch will work as the antidote of the issue. The cherry-pick has to ignore the traceability due the source and destination changesets are already connected so a regular cherry-pick will find nothing.
Finally the release branch is fully tested and it needs to be merged into “main” to label the new “BL500” release.
Done!!
Steps summary
That will remove the feature or bug from the destination branch. If you also want to later re-integrate the branch you will need to:
- Cherry-pick (ignoring traceability) from the changeset of branch subtracted
- Merge the source task branch again to get the latest changes
Here you have a gif summarizing all the steps together:
Very informative article. However, I wish you would explain why you would want to use subtractive merges over "Delete changeset" and the side effects that can cause. Also, can you explain what "Cherry-pick (ignoring traceability)" means?
ReplyDeleteI'm also curious of why we would not want to just delete the faulty changesets?
ReplyDeleteIn this scenario after the "faulty" changeset you have done several checkins. So you can't simply remove the cset because even if you could do it (which you can't) the change will be included in the next csets.
ReplyDeleteSubtractive is the way to get this done right :-)
Muy bueno Manu!
ReplyDeleteSaludos.-
Why not do subtractive merge of 180, undoing the undo without needing to do a baseless cherry-pick. This would avoid having to redo any conflict resolution done in the first subtractive merge.
ReplyDeleteEither way, your branch history now shows:
Add issue32
Add issue33
Back out buggy issue32
Re-add buggy issue32
Merge fix for issue32
It'd be nicer if those last two commits could be handled as one commit, "Re-add fixed issue32".
Any comment on TBBle's suggestions? Would a subtractive from 180 work equally well? Also, I suppose you _could_ do the last two merges in one checkin...
ReplyDeleteYes, you can Cherrypick from 180 and then merge from 181. It's going to be the same.
DeleteCherry picking from the faulty branch seems not to work like expected in Plastic SCM Version 5.4.16.768.
ReplyDeleteI have a situation, where I had to subtractive merge a changeset interval, because the outcome had a bad performance. (It was not a bug, by the way.)
But there were also some good changesets within the "bad" branch. So I tried to cherry pick only the "good" changeset, the cherry pick tab opened correctly, but it says "0 items to merge".
It seems to me, that Plastic SCM thinks internally, I want to merge the changeset instead of cherry picking it. (As far as I know, the cherry pick operation should not care about any merging history. It should simply take the changes and merge these with the current workspace.)
Could this be a bug?
Are you selecting the "Ignore traceability" option for the cherry pick operation? Otherwise Plastic will see there's a path from the changeset to the destination and will conclude the merge is not needed (0 items to merge).
Delete