Every so often, I come across a programmer (usually a student, or a self-taught hobbyist) who doesn’t use version control (cue shock and horror).
Of course, whenever someone dares to admit this, they’re set upon by everyone and heckled and pestered until they give in and install some VCS. And then they spend a few afternoons moaning about how they “could have been coding instead”.
And it occurred to me that there doesn’t seem to be any short, simple, minimalist guide to setting up and using a VCS system. There are plenty of excellent tutorials and guides which explain everything about everything, and are an amazing resource to those willing to actually spend time to learn how to use their tool.
But newcomers to version control are generally someone who’s willing to give it 2 – 3 minutes, if it’ll shut everyone else up so they can get back to coding. They’re not interested in knowing what their code looked like 7 months ago, or what exact changes were committed on the 28th of June 2010 at 9:37 pm. And they don’t really see why they’d want to branch and merge their code.
The 5-minute guide to Bazaar1
You can use any VCS you like. But the distributed variants (DVCS) are newer, shinier, more powerful and easier to use. So use one of those. The three main ones are Git, Mercurial (Hg) and Bazaar (Bzr), in decreasing order of popularity (and, subjective alert, increasing order of user-friendliness). In any case, I like Bazaar, so that’s what this guide is going to use.
Pick yer poison. Bazaar is available for pretty much any OS. Pick the relevant one, download it and install it. (For Windows, you probably want the standalone installer, not the Python ones — unless you have Python installed, in which case you can pick the Python-based one if you like.
Fire up the command line
On Windows, that’s good old cmd.exe. On OS X or Linux, you’ve got terminals and a half-dozen different shells.2
cd to wherever your code is:
c:\somewhere> cd \dev\myproject c:\dev\myproject>
Initialize a repository. A repository is a small file-based database storing current and past versions of your code.3
c:\dev\myproject> bzr init Created a standalone tree (format: 2a)
There we go. Bazaar now assumes that the current directory is what it’s supposed to track. It just created a subfolder with the name
.bzr, into which it’s going to store all the versioning data associated with your project. If you ever want to just rip everything Bazaar out of your project, just delete that folder.
Now, it’s time to tell Bazaar which files to track:
Putting files under version control
We’ve probably already got some code, spread over one or more files. There’s almost certainly also some temporary files, intermediate files creating during a build, and your final executable, and whatever else, which we do not want to version control. Your VCS system should track the files needed to build your project. No more, no less.
So we need to divide our code up into these two groups. Files that should be version-controlled, and files that should be left out.
A good start is to ask Bazaar what it sees. If your project is a Visual C++ 2010 project, it might look something like this:
c:\dev\myproject> bzr status unknown: Debug/ myproject.sdf myproject.sln myproject.vcxproj myproject.vcxproj.filters myproject.vcxproj.user ipch/ main.cpp
These are the files and directories which Bazaar found, and which, as it says, are unknown. We haven’t yet told Bazaar anything about them.
Well, running through the list, we can see:
Debug, where the output of a debug build are stored. It contains a half-dozen different file types, from our
myproject.exeto a bunch of build logs, and intermediate build files, manifests and other stuff. It’s all generated during build, so we don’t want any of it.
- The Intellisense database,
myproject.sdf, and an associated
ipchdirectory storing some other Intellisense cruft which is also generated automatically.
- The Solution file, which we do want Bazaar to keep track of
- The project file, including the project filters it uses, both of which should be version-controlled, and the
.userfile containing user-specific configuration. If you’re just one developer, you can let Bazaar track this as well, but with more than one developer, each will probably want his own
.userfile, so I’ll assume you want to keep it out.
main.cpp— our actual source code. This should definitely be version-controlled.
Well, we could selectively add the files we wanted, but that would leave us with
bzr status being all cluttered up showing files we don’t care about. Instead, we should tell Bazaar to ignore the files we don’t want. Then we can add everything else.
c:\dev\myproject> bzr ignore Debug/ c:\dev\myproject> bzr status added: .bzrignore unknown: myproject.sdf myproject.sln myproject.vcxproj myproject.vcxproj.filters myproject.vcxproj.user ipch/ main.cpp
ok, so a very short detour first, We told Bazaar to ignore the
Debug directory. (The trailing
/ tells Bazaar that it should only ignore directories with the name
Debug. The command
bzr ignore Debug would have ignored both files and directories named
bzr status now shows us something a bit more interesting.
Debug/ has vanished from the eyes of Bazaar. The directory still exists, but we told Bazaar to ignore it, so it does. It is no longer “unknown”. On the other hand, we now have a
.bzrignore file, and it is not unknown, it’s “added”. This means that it is registered as something that should be added to Bazaars repository, but it hasn’t actually been done yet. As you might have guessed, this is where it stores the information that
Debug/ should be ignored. Feel free to look inside the
.bzrignore file, or edit it by hand. There’s no magic in it.
Now, let’s move on and ignore the remaining files:
c:\dev\myproject> bzr ignore Debug/ c:\dev\myproject> bzr ignore /*.sdf c:\dev\myproject> bzr ignore *.user c:\dev\myproject> bzr ignore ipch/ c:\dev\myproject> bzr status added: .bzrignore unknown: myproject.sln myproject.vcxproj myproject.vcxproj.filters main.cpp
Pretty straightforward, eh? Note that we can use
* as wildcards, allowing us to ignore entire groups of files. We can also use a leading
/ to indicate that this rule only applies if the pattern matches starting from the root. In other words, we want to ignore
.sdf files found in the root, but not in subdirectories, whereas with
.user files, we just want a blanket ban. Wherever they’re found, Bazaar should ignore them.
Now our status is down to showing just the files we actually want to add. So let’s just add everything.
c:\dev\myproject> bzr add adding myproject.sln adding myproject.vcxproj adding myproject.vcxproj.filters adding main.cpp
Here, it’s time for another little word of caution:
We just told bazaar to add everything it can see. It will do so recursively. In my little example, that makes no big difference because I only had one subdirectory, and I already told Bazaar to ignore it. If you have subdirectories that are not ignored, then this command will make Bazaar add everything the files inside them as well, even if they weren’t listed on the
bzr status output, which doesn’t look inside unknown directories. So it is possible that the
add command just added a bunch of other intermediate files, which you didn’t actually want to put under version control. If so, you can use
bzr rm <filename> to selectively remove files from version control again. Alternatively, you can just delete the intermediate files, and when Bazaar tries to add them in a minute, it’ll realize they don’t exist, and figure out that you probably didn’t want to add those after all. Or, of course, you could have played it safe and added only the directory itself (
bzr add mydir), after which
bzr status would have shown the contents of the directory as well, allowing you to easily see what should be ignored and what should be added.
At this point, either read over the output from
bzr add above, or run a
bzr status and check the
Make sure that the files you want to add are on the list, and that none of your generated/temporary files are. If your ignore patterns hide too many files from Bazaar, go ahead and edit the
Assuming the list of added files now matches what we actually want to add, go ahead and tell Bazaar to commit these changes:
c:\dev\myproject> bzr commit
Or, as I prefer,
c:\dev\myproject> bzr commit -m "initial commit: added files"
When you commit, Bazaar expects a small text message describing the changes that were just committed. With
-m you can specify this message directly. If you don’t, Bazaar will open a text editor so you can type the message there, save the file and close the editor.
In both cases, you’ll get this output:
Committing to: C:/dev/myproject/ added .bzrignore added myproject.sln added myproject.vcxproj added myproject.vcxproj.filters added main.cpp Committed revision 1.
Now, Bazaar has stored a copy of all the files it knows about (files you just added, and files added previously) inside its
.bzr subdirectory. If you ever want to go back and check what your code looked like in revision 1, you just have to ask Bazaar (but I won’t tell you how, because this is supposed to be a short minimalist guide).
Just for good measure, check the status again:
c:\dev\myproject> bzr status
Nothing. Bazaar sees nothing interesting. There are some ignored files, but we’re ignoring those. And there are some other files, which Bazaar already knows about, and they’re unchanged compared to the version Bazaar knows. So it has nothing to say, and is polite enough to say nothing.
This is what we like to see, because it means Bazaar is completely up to date on our code.
Now, go ahead and write some code. Change something in one of your files (in my case, that’ll be
main.cpp since that’s the only actual code file I have), and run
bzr status again:
c:\dev\myproject> bzr status modified: main.cp
Aha! Bazaar has detected that our file has been modified, and these changes have not been recorded by Bazaar. Well, perhaps that’s because the code doesn’t compile, in which case that’s fine. We only want Bazaar to store the changes that are actually worth storing. The ones that mark an improvement to the code, or the ones we might want to be able to recover later on.
But perhaps these changes are actually something we’d like to keep, in which case we commit them:
c:\dev\myproject> bzr commit -m "Fixed a ton of bugs in main.cpp" Committing to: C:/dev/myproject/ modified main.cpp Committed revision 2.
And once again,
bzr status is empty because everything is exactly as Bazaar expects it to be. Our code looks exactly like what Bazaar was given in our last commit.
And that is basically it. You’re now using version control. When you add new files to your project, just remember to
bzr add them. When you’ve made some interesting changes, run
bzr commit to tell Bazaar to store a snapshot of your code as it looks now. Regularly run
bzr status in between to check that Bazaar’s view of the world correlates with your own. If it shows any unknown files, get them added or ignored. And if it shows other changes, it provides a list of what changes would be committed if you ran
bzr commit now. (And also, a list of which changes would be lost if you accidentally overwrote the modified file).
If you want to look up how a command is used, simply type
bzr help <command>.
Of course you can do all sorts of interesting things with your repository now4, but you wanted the quick version. As long as you add new files, and regularly commit your changes, other programmers will shut up and leave you alone. When you actually need the more interesting features of your version control system, you can always look them up.
But for now, you can go back to coding, and no longer have to hide when people ask “so do you use version control?”.
See? That wasn’t so bad, was it?
I chose Bazaar because it’s my preferred VCS tool, and thus, easier for me to run through in record time. No big arguments here about why X is better than Y. There are dozens such sites already, proving conclusively that Git is better than Hg, Hg is better than Bzr and Bzr is better than Git. And of course, there are other sites showing just as clearly that the opposite is true. It just doesn’t matter. All three are good enough, and are used on several major software projects. I like Bzr because it’s convenient and easy to use. I’ve never used Hg, but that looks nearly as convenient and easy to use. Git is less convenient and less easy to use, but makes up for it by being ridiculously widely used. ↩
Yes, there are graphical front-ends available as well. Bazaar comes with Bazaar Explorer, for example. Use them if you like. I use the command line interface because, to be honest, I find it to be the simplest and fastest solution. As you’ll see, the commands are all very simple, so just leave a command prompt (or terminal, for you Unixy folks) open in the background while you code. ↩
Technically, in Bazaar it’d be more correct to say you are initializing a (named) branch. That’s what
bzr help initsays about the command too. The difference doesn’t really matter for now. Other VCS systems call this a repository. In brief, a repository stores the version history for one or more branches. In most VCS systems, you need a repository, because that’s where your branches are stored. Bazaar allows you to create a common repository which any number of branches can use to store data, eliminating a lot of duplication and speeding up certain operations. But a branch can also just store all its history itself. That’s the lazy option, and what we’re doing here. Look up “shared repositories” if you’re curious about how to use repositories in Bazaar. ↩
in particular, once you’re willing to spend another minute or two fiddling with version control, you should investigate
bzr push, which pushes a copy of your branch to another location — a different directory on your computer, or a remote server. This is obviously handy for sharing code, but it’s also a very convenient way to take backups. ↩