From ProgSoc Wiki
So, you've been cuttin' code for quite a while now, eh? Your programs are getting a mite more complex than your garden-variety shell script, with features and functionality to be found left, right and centre. You may very well be the sole programmer working on a program, but there's a pretty good chance that you're not the only developer. In all likelihood, you're probably part of a development team working on a particular program, making changes and -- quite often -- breaking the program. You may or may not all be in the same room at the same time. The program is updated quite frequently to meet its users' needs and demands. It's also possible that you might be deploying more than one version, customised to meet specific needs and markets.
In this chapter, we'll be having a look at version control principles in general and also the many and varied version control systems out there for UNIX and UNIX-like systems, each with their own underlying philosophies for maintaining and tracking revisions to files and multi-user collaboration. The five systems we shall be focusing on are: Subversion (svn), Bazaar (bzr), Git (git), Mercurial (hg) and the Concurrent Versions System (cvs), all of which are installed on the ProgSoc network for your use, are freely available and can also be used on Windows and Mac OS X computers.
Even though by far the most common use for version control systems is source code management, you will find that, once you've grown accustomed to using version control systems, you'll start using them to manage other forms of complex textual and non-textual data that gets updated frequently, such as documentation, capstone projects, master's and doctoral theses -- all which may or may not contain code -- just to name a few. Even the creation of TFM -- this very publication that you're reading right now -- was managed using svn .
"But I'm planning on a career in system administration. I do not need to not not know about no stinking version control!", you might naively retort, for a version control system is a vital and important part of a well-maintained computer network. Indeed, ProgSoc uses version control to keep track of its configuration files on its computers. Every time a change, no matter how large or significant, is made to a computer's configuration, the changes are committed to a bzr repository, so that if a serious mistake is made in the configuration, or we simply just need to restore a computer back to a previous state, we can quite easily revert the changes (more on those italicised words later on).
So a lot of what I'm about to say will stand in good stead, even if you're not planning on doing much coding in your current academic and/or future careers.
Types of version control systems
Regardless of which version control system you end up using, you will find that most, if not all of them have many fundamental features in common.
Repository This is the heart and soul of all proper version control systems. It's basically a database that keeps all the files in a project you're working on in order, sweeping a whole heap of file-and-project management tasks under the metaphorical rug. You associate (or "track") your project directory with your repository, where the actual, direct manipulation of your complex content is made, and files and data are transferred from repository to tracked directory and vice versa. The repository may be hosted on your computer or on a remote machine. In any given project, you might have just one physical database (typical of centralised systems) or you might have many databases distributed over a number of computers (typical of distributed systems), linked together as one repository. You interact with the repository by issuing commands to it in one of two ways:
1. By typing them from the command line, using your favourite shell or command prompt, or;
2. By browsing a tracked folder via a graphical user interface and pointing, clicking and issuing commands. A popular "front-end" program for Windows systems is the freely available Tortoise suite of Windows Explorer extensions that exist for all five version control systems featured in this chapter ("Favourite-search-engine" them) -- once installed, you just right-click in a tracked folder and away you go.
My personal preference is 1. due to its flexibility and universiality, but if you prefer 2. since you're just getting to grips with version control (and you can find a suitable package for your operating system), go for it.
Revision This is what repositories store. Rather than just storing files straightforwardly in the repository, you commit the contents of your tracked directory to it. The repository takes a snapshot of the directory, noting the time and date of the commit, as well as who committed the files and what files have been modified since the last commit, amongst other things, thereby creating a revision, and then stores just the difference between the current (or HEAD) revision and a previous revision (thereby saving disk space). You can commit revisions ad infinitum, and you can also fetch and reconstitute either HEAD or earlier revisions made either by you or someone else, something that is quite hard to do with a regular filesystem.
Branching You don't have to follow a strictly linear development pattern! You are free to branch out and create multiple development paths and grow yourself a nice big "tree" of revisions. You are also free to switch between branches as needed. You are also free to abandon branches. Maybe you want to try out a new idea, or maybe you need to support multiple versions of a program (e.g. a "stable" version of a program,which your customers/adoring fans use but gets the odd bug-fix, and a "developmental" version which is where you add your cool new features and which might form part of a future stable version). Whatever your needs, branching can do it for you.
Merging Sometimes you need to merge branches and/or files together (e.g. if you wish to incorporate the aforementioned bug fixes from the stable branch into the development branch). Depending on which version control system you are using and just how much filesets in each branch to be merged have diverged in content, merging can be either a trivial task or The Task From Hell that saps your productivity and slows down the release cycle. You have been warned, but please don't be put off by this.
User There might be one. There might be many. Some might have permission to change the contents of the repository, others might only be able to fetch files. Your version control system can (and must be able to) handle this.
Historically speaking, all version control programs were of the centralised (or client-server) variety. This is because back in the days of extensive mainframe computer and terminal use (1970s and 1980s), all users of a mainframe (the server) would log in via their terminals (the client -- little more than a monitor and keyboard) to use it, so naturally, version control software on those kinds of computers would need to follow this paradigm by default.
Centralised version control systems such as cvs and later, svn, evolved from these earlier systems and continue their tradition. Such systems are perfectly fine for personal use, if your repository is stored locally on your computer but nowhere else, and you have no intention of sharing your repository with other people on other machines.
This strict client-server model does have a few obvious drawbacks, particularly if the repository is stored on a remote machine. When you fetch a revision from the repository, you get only the files from that revision, not the complete development history. What if the link to the server is down? Then neither you nor your associates can fetch from the repository nor update it, thereby potentially slowing development. What if the hard-disk on the server fails and you haven't got a complete backup of the repository? There has to be a better way. And there is...
The Distributed Approach
With the rise of the Internet to greater public prominence from the 1990s onwards, the world became more interconnected and "a little bit smaller", hard drives increased in capacity, connections and processors became faster... and, in the software development fraternity, distributed version control systems became more popular, taking full advantage of this heightened level of interconnectedness.
Distributed version control systems such as git, Mercurial and Bazaar dispense with the notion of there being just a single, centralised repository and instead replace it with a single repository... spread over multiple computers and each project member has their own local copy of the development history -- essentially, each machine forms at least one branch of the repository. Updating each other's histories or checking out another member's branch is a simple push or pull away. If a link goes down or a server fails (or your machine fails), all is not lost. You can just connect to another machine and there's a pretty good chance most of the development history is still intact. Best of all, distributed version control systems allow for a greater degree of flexibility with regards to who can commit to which server. If you wish to continue with a "client-server" arrangement, where users all pull/push to a central server (in addition to committing locally), you can do it. If you wish to create a "hierarchical" arrangement, where certain developers are tasked with developing a sub-module of a large and complex system, who then commit their work to a "sub-project manager", who in turn vets the changes and pushes them on to someone further up the chain, ultimately leading to the head developer, you can do that too. The possibilities are endless!
Now, you might be asking "If distributed version control systems are technologically superior to centralised systems, why even bother with centralised systems any more?" Well, for the simple reason that they are still being used extensively to this day. It's a cold, hard fact of life that many companies and development houses feel as if they are married to the programming tools they have chosen years ago and are not willing to change to something better... and if you are not working for one of these companies right now, you will one day, so you will just have to deal with it when the time comes. Perhaps with constant and gradual persistence, you might eventually get your colleagues to see the light and convert to the true distributed religion, but for now, you'll just have to stick with using SCCS or Visual SourceSafe (or some other archaic version control system), and learn how to use them well (and struggle with their associated pitfalls and shortcomings). 
We should briefly mention wikis, if only to point out the similarities between them and the version control systems we have been discussing. Generally attributed to Ward Cunningham as its inventor, the wiki (which means "fast" in Hawai'ian, by the way) has become so prevalent on the World Wide Web that it's almost easy to forget there was a time where the hoi polloi couldn't just dive right in and amend content right there on the page. Undoubtedly the most popular wiki software package in use today is MediaWiki (http://www.mediawiki.org), originally created for a certain little online encyclopaedia that shall remain anonymous, but, of course, there are others such as DokuWiki (http://dokuwiki.org) and TWiki (http://twiki.org), just to name a few.
In any given wiki, you've got many pages of content to look at and edit. You just click on the Edit link (or equivalent) on a page, make your changes, save them and the changes appear right there and then. But just because you've made a change, it doesn't mean the previous changes are gone forever. Far from it. Click on that page's History link (or equivalent) and you will see a list of previous revisions to the page (showing the date and time of modification and who changed it amongst other things) and by clicking on one of the links, you will be able to read, and even restore, those revisions in their complete form. Or you could click on a Diff(erence) link (or equivalent) to see just the changes between revisions. Yes, wikis have version control, built into the system. And yes, a good wiki even has some kind of merging facility built-in, on the off-chance a page is being edited simultaneously by two or more people. And the best thing about it is you don't have to use special software (other than your web browser) to do all of this.
There are also other kinds of web-based content management systems (CMS) -- a wiki is a kind of CMS, and so are the version control systems that form the lion's share of discussion in this chapter -- that provide for a greater degree of flexibility in content manipulation (particularly in visual layout and functionality), but are slightly more complicated to use. But CMS' are well beyond the scope of this chapter. Perhaps in another TFM.
Having a (tar)ball: a "simple" version control system
Let me just say that it is entirely possible to do version control without using a dedicated software package. Why you would want to after reading this chapter is another story entirely. But it is possible, so let me illustrate for you how you might go about it.
So let's just say you've belted out a bonza program that does all of these cool things. Now you want to improve it by adding a few nifty features. But you want retain a copy of the original source code before proceeding. It might come in useful one day. No problem! Just copy the entire source tree to another folder. Call it whatever you want. Then you make the changes, compile the program, then ship. Accolades aplenty from your adoring fans/customers/whatever. Demands for new features and bug reports start coming in from all corners. No problem! You can implement them. Just back up the source tree once again, then add the feature/bug fix. Repeat several times for each new feature. Your program grows in functionality... and size. A not insignificant amount of disk space is being taken up by each of these revised versions of the program. No problem! Just create a bzip2ed tarball archive of each revision, which you can decompress when required. If you're really cluey (and you are) and you really want to save space, you'll do a diff of each folder, and then tarball up just the differences between each successive revision, then if you want to recreate a given revision, you'll simply decompress each archive and apply the patch in sequence. Note, of course, that applying patches in this fashion is a time consuming exercise (perhaps you could write a script that automates the process), so my guess is you'll stick with just tarballing whole trees. That's OK. Disk space is cheap and plentiful these days, anyways. The program continues to grow in complexity. You have well over a hundred revisions now. The names of the tarballs with their 255 character limit don't leave you with enough space to give a lengthy description of the changes made. After all, it is helpful to know at a glance what exactly was changed in your program, revision by revision. No problem! You can update a "little" text file, or a spreadsheet where, in one column you have the tarball name and next to it, you have a relatively detailed (not of essay length) description. Note that you will now have to update this file every time, just to keep track. Book-keeping can be tedious and you're a programmer, not an accountant! Small matter, you reason. The program has gotten so big that you've nought the time, energy or resources to update them yourself. No problem! You'll invite a few of your mates to work on it. You set up your machine as a server, give your mates FTP access (hopefully the SSH-enabled variant -- sftp or even scp -- for extra security) to it, then tell 'em "Let's get to work, guys!". And so the collaborative effort begins in earnest. Development chugs alongs smoothly for a while... then you hit a snag. A conflict. You've gone and updated a particular module, got it just the way you want it, then about ninety-nine nanoseconds later, one of your clever mates goes and overwrites your work with his effort. An "edit war" of sorts ensues over e-mail/messaging. It ain't pretty. It's resolved eventually, but much enmity remains. The demands are increasing. Your market is expanding. You have to make different versions for each of the two-hundred-and-whatever sovereign nations of the world, in each of their languages (including Igbo, Yoruba and Piraha, the whistling language of the Amazon), taking into account the complicated laws of each nation. So you branch out, make more folders and tarballs. You buy more disk space (cheap, remember? Besides, you're rolling in cash now. Nothing money can't fix, right?). You and your mates (the ones who haven't thrown in the towel yet) are now simultaneously doing the dance between the development branches, synchronising code in each branch. Turns out you do need to (temporarily) decompress old tarballs, just to restore some old feature you blithely removed 42 revisions ago. More features, more bugs, more demands, more revisions, more branches. What's sleep? What are the names of your significant other and/or kids? What's your name? All long forgotten, as the single-minded battle between man and machine rages on. Then, one day, your machine falls victim to a catastrophic failure. All your revisions, all your work, your whole business more-or-less, gone in one fell swoop. It's not as if you and your mates have been backing up each and every revision. I mean, why would you need to? The answer, of course, is obvious in the cold light of day as you scramble to piece together what's left of the wreckage, hoping to get back on track... but by this stage, I wouldn't count on it. Your ex-mates have long since left you and are no longer interested in helping you.
An awesome programmer, you might be, but suck at version control, you do.
As you can see, it gets very messy and very complicated, very quickly, and, in the worst case scenario, very catastrophic. Yeah, I would prefer using a software package that manages all of this automatically for me, too.
Going with the (work)flow: using version control software
This is just an overview of how you would go about using cvs, svn, git, hg and bzr on a day-to-day basis. Read the next section to find out how to learn more about the specifics of each tool.
Important note: While there are tools that exist that allow you to convert repositories and their histories (with varying degrees of success) from one version control system format to another, you generally can not use one software package to access a repository designed to be accessed by another. In other words, use the svn suite of tools to manipulate svn repositories, the git suite for git repositories, and so on.
Creating and accessing repositories
The very first thing you need to do before you can start working with your version control package is to get access to a repository. This repository might already exist or you might have to create it.
To create a new repository on the machine that you are logged into with cvs, git, Mercurial and Bazaar, you use the init command. For svn, you use svnadmin create. For all five systems, you end up with an initialised repository that contains no files nor any revision history, and is associated with the directory from whence the repository was created. Once you've created the repository, you can configure it to decide who (else) can access the repository, their level of access (can they read and/or write the repository?) and how the repository will be shared (no sharing? NFS? HTTP? SSH? etc.), amongst other things.
To start manipulating files stored in an existing repository -- be it stored locally or remotely -- you need to copy the files from the repository to your machine and (automatically) associate a working directory with it. This is where a major divergence between the centralised (cvs, svn) and distributed (git, hg, bzr) systems takes place.
As mentioned earlier, when you first get files from cvs and svn repositories using the checkout command, by default, you will receive a set of files based on the latest revision (you can checkout an earlier revision if you wish).
With git and hg's clone command, you end up getting your own working copy of an entire repository (complete with every revision), not just a fileset. This is your own repository which you may configure and manipulate as you please. bzr uses branch to get a copy of another repository (actually, just a branch -- bzr, for better or worse, tends to blur the distinction between `repository' and `branch'. Be aware of this.)
You primarily manipulate repositories by editing files in your working directory linked to the repository, then submit your changes to the repository. These files need to be "tracked" by the repository for it to recognise any changes submitted to it. It is perfectly possible to have non-tracked files in your working directory. These files will not be submitted, or worse, be lost if you switch branches (especially with git) unless you use the add command (all five systems) to make the files tracked. If you don't wish to track a file any longer, use the remove command in cvs, hg and bzr, rm in git and delete in svn. Bear in mind, however, that the files you have de-tracked can still be found in previous revisions in the repository (a real lifesaver!)
Before you submit your changes, you might want to see which files have been changed and which files are not tracked in your working directory. This is done with the status command (all five systems).
You might also want to assign a descriptive name, or tag, to your revision before submitting, using the tag command. This makes identifying the purpose of your revision at a glance a lot easier than just relying on sequential revision numbers. Don't go overkill with tagging revisions, though. Just assign tags to important or landmark revisions e.g. if you feel a particular revision of a program is suitable for release to the public, you might tag it as "ReleaseCandidate1" or "Version1.0" or whatever nomenclature you or your team have chosen.
To submit, or commit, changes made to tracked files in your working directory to your repository, use the commit command (all five systems). It is useful to include a "commit message" along with the commit, describing the changes made to the files, so that when you read through the revision logs later on, you'll know what you've done. You will have the opportunity to enter the message at the time of the commit, either directly from the command line or via a text editor which will automatically open for you.
The distributed systems have an additional set of commands -- pull and push. pull allows you to update your local repository by fetching revisions stored in other (remote) repositories, while push allows you to send revisions you've committed to your local repository onto other repositories.
To bring in the latest changes from your repository to your working directory, use the update command for cvs, svn and hg. git and bzr don't have an update command, as the working directory is automatically updated every time a commit or a pull is made, or an active branch is changed.
Get into the habit of doing an update before you commence an editing/programming/etc. session (provided that you have not edited anything in your working directory after a commit) and especially if you haven't committed anything to the repository in a while -- you don't want to inadvertently write older versions of files when you do a commit, overwriting later revisions, and annoy your friends, now, do you?
To see how exactly a file has changed between two revisions, use the diff (difference) command (all five systems).
To get a complete or partial listing of all the revisions in the repository, use the log command (all five systems). Alternatively, you can use a graphical interface browser tool (such as gitk for git) to not only give you a scrollable listing, but also a graphical representation of all the revisions -- including branches and merges -- in a nice "railroad" diagram format.
Sometimes you need or want to break away from the main development track. You do this by creating a branch, or a new line of revisions, which involves making a separate copy of a previous revision and working from that point onwards. You can commit changes to this branch as you please, without affecting the main branch or any other branches.
To create a branch with git, hg and bzr, you use branch, tag with cvs and copy with svn.
To switch between branches, that is, make your working directory point to a different branch, use switch with svn and bzr, update -C with hg, update -r with cvs and checkout (why confuse poor cvs and svn users!?) with git. It's a good idea to save your work in your working directory and commit your changes in your current development branch before switching branches, as the contents of your working directory might get replaced with a fileset from the new branch. Alternatively, use separate working directories for different branches.
And sometimes, you need to bring development branches back together again. Or sometimes, there's a conflict between two versions of a file (or many files). In both instances, you need to know how to merge, possibly one of the most dreaded, headache-inducing and time-consuming tasks in the software development field, depending on your level of experience and the tools you use.
In most modern version control systems, some kind of auto-merging capability is provided for, saving the user from merging all but the most complicated files and branches.svn, git, hg and bzr all have a merge command, however cvs, being old and horrible, does not have such a command and all merging has to be done by hand or with an alternate file merging tool (such as patch).
There are many auto-merging algorithms used by different version control systems, most of which follow one of two basic strategies. Version control systems such as svn use the two-way merge, where a new merged file is created by comparing just the differences between a revision on one branch and a revision on another, and attempting to reconcile the differences. Sometimes it works, sometimes it doesn't. More modern systems such as git, hg and bzr use the three-way merge, where, in addition to comparing the differences between the two branches as per the two-way method, it also compares the parent revision, that is, the revision from where the two branches ultimately originated from. This method usually ends up being more successful at producing accurate merges that don't break your code.
Regardless of whether your version control system has auto-merging capabilities, there are times when conflicts between files have to be resolved manually, for example, if there are two differing lines of text in two versions of the same file that appear on the exact same line. Your version control system might spit out a file that looks like this:
This is a sad little poem about sad little things... . [redacted, non-conflicting part] . <<<<<<< .r42 April is the cruellest month ======= April is the coolest month >>>>>>> .r69 . . .
You can't use this file for its intended purpose just yet, as it is in a state of conflict. You must therefore resolve it. The system has clearly identified the various part(s) of the file that it was incapable of merging (note the revision numbers in the above example) and has kindly provided us with both versions in-file. It's up to you to choose which version you wish to retain or perhaps you wish to replace the conflicted part(s) outright with something different.
Once you've successfully merged your files, don't forget to commit your changes to the repository!
I wanna know more!
Owing to a lack of space in TFM and insufficient level of motivation possessed by your author to write a separate thousand-page treatise on the subject, this chapter is, by necessity, just a brief overview of the concepts, practices and tools associated with version control, so you will need to look elsewhere to learn more. Here are some places you can look:
man / info Help is just a command-line command away! Type man or info, then the name of the version control program you're using, to get a terse description of the system and each and every function supported by your program.
tool help command If you haven't got the time to wade through man pages and just need to know what a specific command does and how to use it, type
tool help command
(e.g. to learn how to send changes to an svn repository and a listing of all the various ways you can do a commit, type svn help commit.) Just as terse as man pages, though, and not as user-friendly and conversational as a book (such as TFM ;), which leads us to...
Bookstores There are plenty of bookstores around Sydney that sell computer-related books, especially in the CBD. Kinokuniya on George Street and Abbey's on York Street have a particularly impressive range of computer books, so you're bound to find something on your favourite version control system there.
Tutorials and videos Joel Spolsky (of Joel on Software fame) has put together a pretty awesome (even more awesome than this chapter) and easy to follow tutorial on Mercurial, which can be found at http://hginit.com. Follow the tutorial to the end and you will find a more detailed discussion on Mercurial (http://hgbook.red-bean.com/), hosted by Red Bean Software, who also have similarly detailed books on both cvs (http://cvsbook.red-bean.com/) and svn (http://svnbook.red-bean.com/). And if you're still not convinced that "distributed" is the way to go, take a look at this enlightening Tech Talk on git, presented by the man himself, Linus "God" Torvalds -- just type "linus torvalds on git" into your favourite search engine to find it.
Amazon, eBay, et. al. If you can't find what you're looking for in the aforementioned bookstores (and you really want it in hardcopy), there are always online bookstores. Standard caveat emptor regarding online purchases applies.
And finally, heed well the following maxim: Google is your friend.
Version Control Cheat Sheet
And because "mine cup runneth over" with generosity, I have compiled for you a list of commands needed to carry out the most common version control tasks in each of the systems discussed in this chapter. Photocopy it or tear it out of the book and fasten it to a wall or wall-like surface within view of your computer, so you can have it as a handy reference while you work.
To use the table, simply find the task you need to carry out from the first column, then look at the cell corresponding to the version control program you wish use, then at the command line, type:
(along with other command-line parameters as needed) to carry out the task.
|Create new (local) repository||init||create||init||init||init|
|Copy current revision from repository||checkout||checkout||n.a.||n.a.||n.a.|
|Copy whole repository||n.a.||n.a.||clone||clone||branch|
|Update working fileset||update||update||n.a.||update||n.a.|
|Add file for tracking||add||add||add||add||add|
|Remove file for tracking||remove||delete||rm||remove||remove|
|Report on modification status of working fileset||status||status||status||status||status|
|Compare changes between revisions of files||diff||diff||diff||diff||diff|
|Display revision log||log||log||log||log||log|
|Commit to (local) repository||commit||commit||commit||commit||commit|
|Pull from remote repository||n.a.||n.a.||pull||pull||pull|
|Push to remote repository||n.a.||n.a.||push||push||push|
|Assign to revision a "friendly" name (tag)||tag||n.a.||tag||tag||tag|
|Switch current working branch||update -r||switch||checkout||update -C||switch|
 bzr tends to blur the distinction between `repository' and `branch'.
 Invoke using svnadmin not svn.
- ↑ The author is not Canadian.
- ↑ As Deane Hutton would say...
- ↑ As Commandant Lassard would say...
- ↑ Linux, FreeBSD, etc.
- ↑ First look up "mercurial" in a dictionary, then look up Hg on a periodic table. You get it? Clever name and abbreviation, no?
- ↑ Much like the chapter on LaTeX, a secondary aim of this chapter is to teach you enough about version control to help you contribute to TFM... unless, of course, we switch over to using a wiki (wimps) for the next edition, rendering this footnote moot.}
- ↑ With an inordinate and confusing number of negatives.
- ↑ Plus once you're familiar with an application, typing is quicker and more efficient -- Vi is living proof of this.
- ↑ Or with, for those with a defiant streak who are under the delusion that they are in complete control of their destiny. "I am NOT a number -- I am a free man!", shouted Number Six to his captors. Number Two just laughed, evilly and uproariously.
- ↑ Another question you might have, recalling what I had said earlier about the version control system used for TFM, is why svn was chosen, and the answer: it was a simple toss of a coin. We could've just as easily used git, hg, or bzr. Honest. For relatively "simple" projects such as TFM that don't get modified all too frequently by too many people, svn really isn't that bad. For more complex and serious projects, eschewing such devices of chance as coins, dice and magic eight balls to choose a version control system is well advised.}
- ↑ Anyone who claims Jimbo Wales to be the inventor should be shot.
- ↑ No more free rides.
- ↑ Code snippet sites notwithstanding.
- ↑ I don't know what it could be, I'm devoid of an imagination. Besides, in this made-up-on-the-spot, completely contrived case study, you're the wunderkind programmer, not me.
- ↑ Now I know I've created a horror story in order to persuade you to use a "proper" version control system, but believe it or not, it is possible to successfully run a project (more-or-less) this way. It just requires a helluvalot of discipline and co-ordination by all concerned. For example, the development "team" (actually a disjointed melee of developers worldwide) of the kernel, or core, of the Linux operating system used a tarball-and-patch system for about ten years before they finally decided to switch to a "proper" system (BitKeeper, then git, which was created specifically to manage kernel development as the owners of BitKeeper would no longer permit use of their software by the kernel development team and there wasn't -- in the opinion of Linus Torvalds, creator of Linux -- a suitable alternative at the time.)
- ↑ WARNING: git uses the checkout command to switch between branches, not to get files from a repository. DO NOT get the commands confused! And yes, I wholeheartedly believe this keyword was chosen on purpose to annoy and confuse svn and cvs users.
- ↑ Hence my choice of picture on the title page of this chapter ;)
- ↑ If you're the kind of person that bought a hardcopy of TFM.
- ↑ At the time of publication, online shopping became all the more popular in Australia, owing to the favourable exchange rate of the local currency. Yes, posterity, the Australian dollar was actually worth slightly more than the US dollar. Heady days indeed.
- ↑ Or print it, if you are reading a web-based version of this chapter.
- ↑ If you are the owner of this book.