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.
Thus…
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.
Install Bazaar
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
Now, 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 ourmyproject.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 associatedipchdirectory 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 Debug.
Note that 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 added: section.
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 .bzrignore file.
Committing changes
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. ↩
Tags: bazaar, beginners, tutorial, version-control





Good article, but took me slightly longer than 5 mins — perhaps I’m a slow reader? ;)
Interesting to see that Bazar is that similar to Git. In the basic commands you show here you could almost just replace “bzr” with “git” and it would work. So I don’t see they lack of usability with Git for that case.
I will admit, however, that it took me some time to fully understand branching, tracking, fetching, merging and rebasing in Git, so I suppose Bazar has much simpler concepts for that? Then again, is that good enough for a entire dev team?
Also Git can still do mysterious things when e.g. references to submodules are branched and merged, but I suppose Bazar has the perfect solution for that too? :)
Well, keep in mind that I basically only showed
add,ignoreandcommit. Those look basically the same in everything from CVS to Git.The usability thing is based in a lot of things, and some of it is really just a “gut feeling”.
But there are a few “niceties”, like when I ignored files, I could just type
bzr ignore <file>, instead of having to edit the.bzrignorefile by hand. Simple little convenience thing, but… nice to have. Or setting up your name/email:bzr whoami "name <email>", orgit config user.name name; git config user.email email‘Or compare the output from
bzr statusabove to what you get in Git by default. I count 9 lines just to tell me that I have a single untracked file.Another example is in handling conflicts, where bzr does a lot more to help you out, keeping track of which files are still conflicted and which ones aren’t.
Commands like
revertandcheckoutexist in basically every VCS, but in Git they mean something completely different. Why? A lot of git commands are just horribly named, so they either conflicts with what users of any other VCS would expect, or just using inconsistent/ambiguous names. Why do commands take a--cachedargument when you want them to work on the index? Would it really kill you to rename it to--indexthen?The Git help docs are generally really bloated, walls of text written for people who already know exactly how Git works internally.
And then there’s my personal pet peeve. The index/staging area in Git really seems like such a backwards idea. I get that it’s nice to be able to commit part of your repository, but the sane solution would be to temporarily stash away the changes you don’t want to commit, so your working tree reflects what you intend to commit, and so you can test your code before committing. The index does the opposite: it lets you stash the code you want to commit, so that you can test everything else, and commit code you haven’t been able to test. (both Git and Bzr have such commands,
stashandshelverespectively)Ultimately, every DVCS works much the same way. There’s no big huge conceptual difference between how you create a branch in Git vs Bzr (and yeah, if Bazaar is good enough for Ubuntu, Bugzilla or MySql, I think it’s “good enough for an entire dev team” ;)), but there’s a world of difference in how they’re presented to the user.
As for submodules, I’m actually not sure what support bzr has for that. But git submodules are another wonderful example. They’re just so needlessly complex to set up and use.
Anyway, I didn’t write this post to imply that bzr was a superior choice. All the three major DVCS systems (and probably a lot of small upcoming ones as well) are perfectly viable choices, with all the necessary features. I just write this using the one I like the best.