I'll keep this one short. If you have a change that has been made to a file (or even to a change package of files) somewhere in the past, and you would like to eliminate that change from the past, you can do so by a judicious use of almost any merge tool.
Most merge tools take, as parameters, a common ancestor file and two files that have been changed (from that ancestor) in parallel, perhaps repeatedly. If you look at the history of a file (and the extension to a change package is straightforward), and we'll keep this history really simple, you will see something like the following:
1.01 .. 1.02 .. 1.03 .. 1.04 .. 1.05 .. 1.06 .. 1.07
Now let's assume that the change that created 1.04 (from 1.03) was not a good change and needs to be yanked out of the file. Your merge tool can do this by considering 1.04 as the common ancestor and 1.03 and 1.07 as parallel changes to 1.04. It may help you to visualize it by pulling 1.03 out of the chain (or even making a copy of it) and considering it as a parallel branch created from 1.04.
The fact that it didn't happen that way doesn't really matter. If you compare 1.03 to 1.04, you will see the original change. If you compare 1.04 to 1.03, you will see the inverse change. The inverse change is going to be merged into 1.07. It is what actually causes the original change to be yanked.
I remember one time when we had integrated a merge tool into CM+ and mixed up the order of the file parameters to the merge tool. It was quite embarassing as each reconcile operation (merge of a parallel checkout with the latest branch version), rather than reconciling the intermediate changes with the parallel checkout, yanked all the changes made by the parallel checkout. A quick edit of the configuration file to swap the order of the files quickly fixed the problem. But I'm sure it made it quite clear to the user that a yank operation is nothing more than a merge operation.
When talking about individual files Neuma generally speaks about merging in four separate use cases:
- Merge - merge the contents of two parallel branches (typically into one of the branches)
- Propagate - merge a specific change into a branch from a parallel branch
- Yank - the opposite of Propagate: remove a change introduced somewhere in the history of the branch
- Reconcile - at checkin time, if the latest branch version doesn't match the checked out version, merge the changes into the checked out version.
There are of course other ways to view merge - a primary case being with respect to your entire workspace. But that's another topic.