Hello, and welcome to the fourth episode of the Software Carpentry lecture on version control. In this episode, we will show you how to use version control to recover old versions of your files.
We'll start with the simplest case. Suppose that Wolfman's working copy of the monsters
project is in sync with the head, which is Revision 12.
He decides to edit the file moons.txt
.
Unfortunately, he forgot that there was a full moon.
So his changes don't make a lot of sense.
The next day, when he's back in human form, he wants to undo his changes. Without version control, his choices would be grim. He could ask his colleagues to send him their copies of the files, or try to edit them back into their original state by hand (which for some reason hardly ever seems to work).
But he's using Subversion, and hasn't committed his work to the repository, so all he has to do is revert his local changes. Subversion's revert
command simply throws away local changes to files and puts things back the way they were before those changes were made.
Let's go through that sequence of steps using SmartSVN.
Wolfman runs SmartSVN…
…selects the file moons.txt
, and then double-clicks on it to open it in the editor.
When it comes up, he selects the text he wants to replace, and puts in a couple of lines of bad poetry instead.
He saves his changes, then loses control of his shape and goes off to howl at the moon.
The next morning, when he comes in, he uses "show changes" to take a look at what happened the previous night.
He realizes that he doesn't want to keep his changes, so he selects "revert"…
…and when SmartSVN asks him to confirm, he clicks "revert" again, and SmartSVN puts his file back the way it was.
Let's open it again to double-check—and there's the original contents.
Now let's look at what happens when someone wants to undo changes that have been committed. Suppose that Dracula decides that the numbers in moons.txt
would look better commas.
He edits the file…
…then commits his changes to create Revision 13.
A little while later, the Mummy sees the change…
…and orders Dracula to put things back the way they were. What should Dracula do?
We can draw the sequence of events leading up to Revision 13 like this.
Dracula wants to erase Revision 13 from the repository, but he can't actually do that. Once a change is in the repository, it's there forever.
What you have to do is copy the old revision forward…
…and merge it with the current revision. This is exactly like merging changes made by two different people, which we saw in the previous episode. The only difference is that the "other person" is actually ourself in the past.
Here's what Dracula actually does.
He runs SmartSVN, double-clicks moons.txt
, goes in, make his change, saves it…
…and then back in SmartSVN, he uses "commit" to push his changes into the repository.
He has now created Revision 13 of the repository.
This is the point at which Mummy realizes the changes have to be reverted.
Dracula goes back into SmartSVN, and under the "modify" menu, selects "merge".
In the dialog that comes up, he specifies a range of revisions. He wants to merge Revision 12 through to HEAD, and he wants to do a reverse merge, because he's going backward in time.
After he clicks, he can bring up a display to see what has changed in his local file.
He accepts the changes, and then commits to create Revision 14 in the repository.
This guarantees that the changes he made to create Revision 13 are still there if he can ever convince Mummy that numbers should in fact have commas.
Merging can be used to recover older revisions of files, not just the most recent. It can also be used to recover many files or directories at a time. But the most frequent use is to manage parallel streams of development in large projects. This is outside the scope of this lecture, but the basic idea is simple.
Suppose that Universal Monsters has just released a new program for designing secret lairs. Dracula and Wolfman are supposed to start adding a few features that had to be left out of the first release because time ran short.
At the same time, Frankenstein and the Mummy are doing technical support: their job is to fix any bugs that users find. All sorts of things could go wrong if both teams tried to work on the same code at the same time. For example, if Frankenstein fixed a bug and sent a new copy of the program to a user in Greenland, it would be all too easy for him to accidentally include the half-completed shark tank control feature that Wolfman was working on.
The usual way to handle this situation is to create a branch in the repository for each major sub-project. While Wolfman and Dracula work on the main line…
…Frankenstein and the Mummy create a branch—a copy of the files and directories in the repository—and do their work there. Branches in version control repositories are often described as "parallel universes". Each branch starts off as a clone of the software at some moment in time—typically each time the software is released, or whenever work starts on a major new feature.
Changes made to a branch only affect that branch, just as changes made to the files in one directory don't affect files in other directories. However, the branch and the main line are both stored in the same repository, so their revision numbers are always in step.
If someone decides that a bug fix in the maintenance branch should also be made to the main line, all they have to do is merge the files in question from one to the other. This is exactly like merging an old version of a file with the current one, but instead of going backward in time, the change is brought sideways from one branch to another.
Branching helps projects scale up by letting sub-teams work independently, but too many branches can cause as many problems as they solve. If you'd like to know more about branching and merging, see Karl Fogel's excellent book Producing Open Source Software, or Laura Wingerd and Christopher Seiwald's "High-level Best Practices in Software Configuration Management". Keep in mind, though, that branching and merging is a fairly advanced topic, and not something you should need until you have many developers or several active versions of your program.