The Monotone VCS provides the concept of mini-branches. A mini-branch is a lightweight branch created inside a formal branch whenever a commit causes "conflicts" with the actual contents of the repository. For example, if your working copy is not up to date and you commit something, you will create a new head within the branch (that is, a mini-branch), that you will later need to (possibly manually) merge with the other head to remove the divergence.

Mini-branches can be used to easily apply externally-provided patches to your software project. Consider the following "collapsed" revision subgraph:

      tag: foo-2.1        tag: foo-3.0
| |
A -> B -> C -> D -> E -> F -> G -> H -> I -> J

As you can see, some development happened in revisions A, B and C, at which point the program was considered stable and the 2.1 release was made. Some time later, and after lots of changes, revision G was tagged as 3.0 and that release was made.

One of this project's users notices a bug in the 2.1 version, tracks it down and fixes it. For whatever reason, he cannot update to 3.0 to see if his changes work with the latest version, so he decides to submit his fix as a patch against 2.1 to the mainstream developers.

So, how do they handle the patch? It will doubtfully apply cleanly to their current code-base, which is far past 3.0. Of course, they can inspect it, adjust it and apply it directly to revision J, but all this process won't be tracked anywhere. Users and developers could later be confused when looking at the original patch and the patch that was really applied — "why were those changes done?".

Here is where mini-branches come to help. The developers ask Monotone to check out a clean copy of C (the same that the user had), ensuring that the patch will apply cleanly. At that point, they apply the fix and commit it to the tree, thus "storing" the original patch file in it. As a result, the revision tree could look like:

      tag: foo-2.1        tag: foo-3.0
| |
A -> B -> C -> D -> E -> F -> G -> H -> I -> J
K

As you can see, the repository now has two heads (J and K) in the same branch (which can be inspected using monotone heads). J is a lot farther than K in terms of development, but that doesn't matter to the VCS system. Note that, at this point, the revision K carries the code in 2.1 plus the changes submitted by the user verbatim; they still haven't been modified to apply to J, and J is not affected at all by that commit.

Once this is done, and after inspecting why the patch does not apply, the developer decides to merge the heads (monotone merge), thus creating a new revision L that holds all J's code plus the fix added in K:

      tag: foo-2.1        tag: foo-3.0
| |
A -> B -> C -> D -> E -> F -> G -> H -> I -> J -> L
/
/
K -----------------------------'

Voila! There is now a single head, L, which holds all your code plus the fix sent by the user. Furthermore, the repository has kept track of all the patching process, storing the original and the modified versions of the changes.

Note that this has assumed that revisions are marked as tags rather than as formal branches. Of course, a similar process could be followed if each version was on its own branch (as done with any other VCS).

Subscribe via RSS · Go to posts index

   Delivered by FeedBurner

Comments from the original Blogger-hosted post: