The “I don’t care about version control, I just want other programmers to stop pestering me”-guide to version control

Every so often, I come across a pro­gram­mer (usu­ally a stu­dent, or a self-taught hob­by­ist) who doesn’t use ver­sion con­trol (cue shock and horror).

Of course, when­ever some­one dares to admit this, they’re set upon by every­one and heck­led and pestered until they give in and install some VCS. And then they spend a few after­noons moan­ing about how they “could have been cod­ing instead”.

And it occurred to me that there doesn’t seem to be any short, sim­ple, min­i­mal­ist guide to set­ting up and using a VCS sys­tem. There are plenty of excel­lent tuto­ri­als and guides which explain every­thing about every­thing, and are an amaz­ing resource to those will­ing to actu­ally spend time to learn how to use their tool.

But new­com­ers to ver­sion con­trol are gen­er­ally some­one who’s will­ing to give it 2 – 3 min­utes, if it’ll shut every­one else up so they can get back to cod­ing. They’re not inter­ested in know­ing what their code looked like 7 months ago, or what exact changes were com­mit­ted 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 dis­trib­uted vari­ants (DVCS) are newer, shinier, more pow­er­ful and eas­ier to use. So use one of those. The three main ones are Git, Mer­cu­r­ial (Hg) and Bazaar (Bzr), in decreas­ing order of pop­u­lar­ity (and, sub­jec­tive alert, increas­ing order of user-friendliness). In any case, I like Bazaar, so that’s what this guide is going to use.

Install Bazaar

Pick yer poi­son. Bazaar is avail­able for pretty much any OS. Pick the rel­e­vant one, down­load it and install it. (For Win­dows, you prob­a­bly want the stand­alone 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 com­mand line

On Win­dows, that’s good old cmd.exe. On OS X or Linux, you’ve got ter­mi­nals and a half-dozen dif­fer­ent shells.2

Now, cd to wher­ever your code is:

c:\somewhere> cd \dev\myproject

Ini­tial­ize a repos­i­tory. A repos­i­tory is a small file-based data­base stor­ing cur­rent and past ver­sions of your code.3

c:\dev\myproject> bzr init
Created a standalone tree (format: 2a)

There we go. Bazaar now assumes that the cur­rent direc­tory is what it’s sup­posed to track. It just cre­ated a sub­folder with the name .bzr, into which it’s going to store all the ver­sion­ing data asso­ci­ated with your project. If you ever want to just rip every­thing Bazaar out of your project, just delete that folder.

Now, it’s time to tell Bazaar which files to track:

Putting files under ver­sion control

We’ve prob­a­bly already got some code, spread over one or more files. There’s almost cer­tainly also some tem­po­rary files, inter­me­di­ate files cre­at­ing dur­ing a build, and your final exe­cutable, and what­ever else, which we do not want to ver­sion con­trol. Your VCS sys­tem 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 some­thing like this:

c:\dev\myproject> bzr status

These are the files and direc­to­ries which Bazaar found, and which, as it says, are unknown. We haven’t yet told Bazaar any­thing about them.

Well, run­ning through the list, we can see:

  • Debug, where the out­put of a debug build are stored. It con­tains a half-dozen dif­fer­ent file types, from our myproject.exe to a bunch of build logs, and inter­me­di­ate build files, man­i­fests and other stuff. It’s all gen­er­ated dur­ing build, so we don’t want any of it.
  • The Intel­lisense data­base, myproject.sdf, and an asso­ci­ated ipch direc­tory stor­ing some other Intel­lisense cruft which is also gen­er­ated automatically.
  • The Solu­tion file, which we do want Bazaar to keep track of
  • The project file, includ­ing the project fil­ters it uses, both of which should be version-controlled, and the .user file con­tain­ing user-specific con­fig­u­ra­tion. If you’re just one devel­oper, you can let Bazaar track this as well, but with more than one devel­oper, each will prob­a­bly want his own .user file, so I’ll assume you want to keep it out.
  • main.cpp — our actual source code. This should def­i­nitely be version-controlled.

Well, we could selec­tively add the files we wanted, but that would leave us with bzr status being all clut­tered up show­ing files we don’t care about. Instead, we should tell Bazaar to ignore the files we don’t want. Then we can add every­thing else.

c:\dev\myproject> bzr ignore Debug/
c:\dev\myproject> bzr status

ok, so a very short detour first, We told Bazaar to ignore the Debug direc­tory. (The trail­ing / tells Bazaar that it should only ignore direc­to­ries with the name Debug. The com­mand bzr ignore Debug would have ignored both files and direc­to­ries named Debug.

Note that bzr status now shows us some­thing a bit more inter­est­ing. Debug/ has van­ished from the eyes of Bazaar. The direc­tory 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 reg­is­tered as some­thing that should be added to Bazaars repos­i­tory, but it hasn’t actu­ally been done yet. As you might have guessed, this is where it stores the infor­ma­tion 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 remain­ing 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

Pretty straight­for­ward, eh? Note that we can use * as wild­cards, allow­ing us to ignore entire groups of files. We can also use a lead­ing / to indi­cate that this rule only applies if the pat­tern matches start­ing from the root. In other words, we want to ignore .sdf files found in the root, but not in sub­di­rec­to­ries, whereas with .user files, we just want a blan­ket ban. Wher­ever they’re found, Bazaar should ignore them.

Now our sta­tus is down to show­ing just the files we actu­ally 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 lit­tle word of cau­tion:
We just told bazaar to add every­thing it can see. It will do so recur­sively. In my lit­tle exam­ple, that makes no big dif­fer­ence because I only had one sub­di­rec­tory, and I already told Bazaar to ignore it. If you have sub­di­rec­to­ries that are not ignored, then this com­mand will make Bazaar add every­thing the files inside them as well, even if they weren’t listed on the bzr status out­put, which doesn’t look inside unknown direc­to­ries. So it is pos­si­ble that the add com­mand just added a bunch of other inter­me­di­ate files, which you didn’t actu­ally want to put under ver­sion con­trol. If so, you can use bzr rm <filename> to selec­tively remove files from ver­sion con­trol again. Alter­na­tively, you can just delete the inter­me­di­ate files, and when Bazaar tries to add them in a minute, it’ll real­ize they don’t exist, and fig­ure out that you prob­a­bly didn’t want to add those after all. Or, of course, you could have played it safe and added only the direc­tory itself (bzr add mydir), after which bzr status would have shown the con­tents of the direc­tory as well, allow­ing you to eas­ily see what should be ignored and what should be added.

At this point, either read over the out­put from bzr add above, or run a bzr status and check the added: sec­tion. 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 pat­terns hide too many files from Bazaar, go ahead and edit the .bzrignore file.

Com­mit­ting changes

Assum­ing the list of added files now matches what we actu­ally want to add, go ahead and tell Bazaar to com­mit these changes:

c:\dev\myproject> bzr commit

Or, as I prefer,

c:\dev\myproject> bzr commit -m "initial commit: added files"

When you com­mit, Bazaar expects a small text mes­sage describ­ing the changes that were just com­mit­ted. With -m you can spec­ify this mes­sage directly. If you don’t, Bazaar will open a text edi­tor so you can type the mes­sage 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 pre­vi­ously) inside its .bzr sub­di­rec­tory. If you ever want to go back and check what your code looked like in revi­sion 1, you just have to ask Bazaar (but I won’t tell you how, because this is sup­posed to be a short min­i­mal­ist guide).

Just for good mea­sure, check the sta­tus again:

c:\dev\myproject> bzr status

Noth­ing. Bazaar sees noth­ing inter­est­ing. There are some ignored files, but we’re ignor­ing those. And there are some other files, which Bazaar already knows about, and they’re unchanged com­pared to the ver­sion Bazaar knows. So it has noth­ing to say, and is polite enough to say nothing.

This is what we like to see, because it means Bazaar is com­pletely up to date on our code.

Now, go ahead and write some code. Change some­thing 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

Aha! Bazaar has detected that our file has been mod­i­fied, and these changes have not been recorded by Bazaar. Well, per­haps that’s because the code doesn’t com­pile, in which case that’s fine. We only want Bazaar to store the changes that are actu­ally worth stor­ing. The ones that mark an improve­ment to the code, or the ones we might want to be able to recover later on.

But per­haps these changes are actu­ally some­thing we’d like to keep, in which case we com­mit 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 every­thing is exactly as Bazaar expects it to be. Our code looks exactly like what Bazaar was given in our last commit.

And that is basi­cally it. You’re now using ver­sion con­trol. When you add new files to your project, just remem­ber to bzr add them. When you’ve made some inter­est­ing changes, run bzr commit to tell Bazaar to store a snap­shot of your code as it looks now. Reg­u­larly run bzr status in between to check that Bazaar’s view of the world cor­re­lates with your own. If it shows any unknown files, get them added or ignored. And if it shows other changes, it pro­vides a list of what changes would be com­mit­ted if you ran bzr commit now. (And also, a list of which changes would be lost if you acci­den­tally over­wrote the mod­i­fied file).

If you want to look up how a com­mand is used, sim­ply type bzr help <command>.

Of course you can do all sorts of inter­est­ing things with your repos­i­tory now4, but you wanted the quick ver­sion. As long as you add new files, and reg­u­larly com­mit your changes, other pro­gram­mers will shut up and leave you alone. When you actu­ally need the more inter­est­ing fea­tures of your ver­sion con­trol sys­tem, you can always look them up.

But for now, you can go back to cod­ing, and no longer have to hide when peo­ple ask “so do you use ver­sion control?”.

See? That wasn’t so bad, was it?

  1. I chose Bazaar because it’s my pre­ferred VCS tool, and thus, eas­ier for me to run through in record time. No big argu­ments here about why X is bet­ter than Y. There are dozens such sites already, prov­ing con­clu­sively that Git is bet­ter than Hg, Hg is bet­ter than Bzr and Bzr is bet­ter than Git. And of course, there are other sites show­ing just as clearly that the oppo­site is true. It just doesn’t mat­ter. All three are good enough, and are used on sev­eral major soft­ware projects. I like Bzr because it’s con­ve­nient and easy to use. I’ve never used Hg, but that looks nearly as con­ve­nient and easy to use. Git is less con­ve­nient and less easy to use, but makes up for it by being ridicu­lously widely used. 

  2. Yes, there are graph­i­cal front-ends avail­able as well. Bazaar comes with Bazaar Explorer, for exam­ple. Use them if you like. I use the com­mand line inter­face because, to be hon­est, I find it to be the sim­plest and fastest solu­tion. As you’ll see, the com­mands are all very sim­ple, so just leave a com­mand prompt (or ter­mi­nal, for you Unixy folks) open in the back­ground while you code. 

  3. Tech­ni­cally, in Bazaar it’d be more cor­rect to say you are ini­tial­iz­ing a (named) branch. That’s what bzr help init says about the com­mand too. The dif­fer­ence doesn’t really mat­ter for now. Other VCS sys­tems call this a repos­i­tory. In brief, a repos­i­tory stores the ver­sion his­tory for one or more branches. In most VCS sys­tems, you need a repos­i­tory, because that’s where your branches are stored. Bazaar allows you to cre­ate a com­mon repos­i­tory which any num­ber of branches can use to store data, elim­i­nat­ing a lot of dupli­ca­tion and speed­ing up cer­tain oper­a­tions. But a branch can also just store all its his­tory itself. That’s the lazy option, and what we’re doing here. Look up “shared repos­i­to­ries” if you’re curi­ous about how to use repos­i­to­ries in Bazaar. 

  4. in par­tic­u­lar, once you’re will­ing to spend another minute or two fid­dling with ver­sion con­trol, you should inves­ti­gate bzr push, which pushes a copy of your branch to another loca­tion — a dif­fer­ent direc­tory on your com­puter, or a remote server. This is obvi­ously handy for shar­ing code, but it’s also a very con­ve­nient way to take back­ups. 

Share and Enjoy: These icons link to social book­mark­ing sites where read­ers can share and dis­cover new web pages.
  • Digg
  • StumbleUpon
  • Reddit
  • Technorati

Tags: , , ,

2 Responses to The “I don’t care about version control, I just want other programmers to stop pestering me”-guide to version control

  1. Good arti­cle, but took me slightly longer than 5 mins — per­haps I’m a slow reader? ;)

    Inter­est­ing to see that Bazar is that sim­i­lar to Git. In the basic com­mands you show here you could almost just replace “bzr” with “git” and it would work. So I don’t see they lack of usabil­ity with Git for that case.

    I will admit, how­ever, that it took me some time to fully under­stand branch­ing, track­ing, fetch­ing, merg­ing and rebas­ing in Git, so I sup­pose Bazar has much sim­pler con­cepts for that? Then again, is that good enough for a entire dev team?

    Also Git can still do mys­te­ri­ous things when e.g. ref­er­ences to sub­mod­ules are branched and merged, but I sup­pose Bazar has the per­fect solu­tion for that too? :)

  2. Jesper says:

    Well, keep in mind that I basi­cally only showed add, ignore and commit. Those look basi­cally the same in every­thing from CVS to Git.

    The usabil­ity 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 hav­ing to edit the .bzrignore file by hand. Sim­ple lit­tle con­ve­nience thing, but… nice to have. Or set­ting up your name/email: bzr whoami "name <email>", orgit con­fig name; git con­fig email‘

    Or com­pare the out­put from bzr status above to what you get in Git by default. I count 9 lines just to tell me that I have a sin­gle untracked file.

    Another exam­ple is in han­dling con­flicts, where bzr does a lot more to help you out, keep­ing track of which files are still con­flicted and which ones aren’t.

    Com­mands like revert and checkout exist in basi­cally every VCS, but in Git they mean some­thing com­pletely dif­fer­ent. Why? A lot of git com­mands are just hor­ri­bly named, so they either con­flicts with what users of any other VCS would expect, or just using inconsistent/ambiguous names. Why do com­mands take a --cached argu­ment when you want them to work on the index? Would it really kill you to rename it to --index then?

    The Git help docs are gen­er­ally really bloated, walls of text writ­ten for peo­ple who already know exactly how Git works internally.

    And then there’s my per­sonal pet peeve. The index/staging area in Git really seems like such a back­wards idea. I get that it’s nice to be able to com­mit part of your repos­i­tory, but the sane solu­tion would be to tem­porar­ily stash away the changes you don’t want to com­mit, so your work­ing tree reflects what you intend to com­mit, and so you can test your code before com­mit­ting. The index does the oppo­site: it lets you stash the code you want to com­mit, so that you can test every­thing else, and com­mit code you haven’t been able to test. (both Git and Bzr have such com­mands, stash and shelve respectively)

    Ulti­mately, every DVCS works much the same way. There’s no big huge con­cep­tual dif­fer­ence between how you cre­ate 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 dif­fer­ence in how they’re pre­sented to the user.

    As for sub­mod­ules, I’m actu­ally not sure what sup­port bzr has for that. But git sub­mod­ules are another won­der­ful exam­ple. They’re just so need­lessly com­plex to set up and use.

    Any­way, I didn’t write this post to imply that bzr was a supe­rior choice. All the three major DVCS sys­tems (and prob­a­bly a lot of small upcom­ing ones as well) are per­fectly viable choices, with all the nec­es­sary fea­tures. I just write this using the one I like the best.

Leave a Reply

Name and Email Address are required fields. Your email will not be published or shared with third parties.