DVCS

A Distributed Version Control System is a tool that helps manage changes in a code base by multiple people. Two examples are Git and Mercurial.

Introduction
In the world of Version Control Systems, DVCS's are fairly new. For a long time there have been monolithic Version Control Systems - such as SVN, Visual Sourcesafe, and CVS. One of the very big differences here is that a DVCS allows (actually encourages) multiple repositories, where you really only have one in a monolithic VCS.

In understanding DVCS, a fair amount of re-learning is needed. While we're covering the basics, remember that other Version Control systems you may be familiar with have similar terms which don't match with what we're discussing, and you need to be willing to completely discard those old definitions except where I might specifically refer to them.

A change or changeset is the most fundamental unit in a DVCS.

A branch is a collection of changesets.

A repository is a collection of branches.

Some of these terms may seem to be the same as a regular VCS, but here's where a DVCS really differs:
 * Usually all developers have a copy of their own repository.
 * The same change can exist in more than one branch.
 * If two branches contain the exact same set of changes, DVCS considers those branches to be the same thing - even if those branches are in different repositories.
 * Changes are the atomic unit. In a VCS the atomic unit is the revision.  Think about this as the difference between: "What changes currently make up my code?" (DVCS) vs "What did my code look like last tuesday?" (VCS)

DVCS Ambiguity
To avoid confusion, below are some definitions that I will be using, and the corresponding terminology or commands that are used in each DVCS implementation.

Normal Workflow

 * 1) Before you begin work on a new feature, make sure you have pulled and are in sync with the main branch.
 * 2) While developing the feature:
 * 3) Make multiple commits to your branch while developing the feature.
 * 4) Frequently pull from the main branch (this will make pushing easier later on), keeping your code up to date with the changes in the main branch
 * 5) Only once the code is ready:
 * 6) Pull one last time after you are done the feature
 * 7) Push to the main branch
 * 8) Repeat

Notice you only push once the code is ready.

When is code 'ready'?

 * All your tests pass
 * Nobody is going to see a crash
 * You have completed a unit of work, such as a feature or a bugfix

Real Developers Need to Fix Bugs
Inevitably, there are bugs and other client requests that occur while working on a feature. To deal with this, you have two options:
 * 1) Roll the change into your current feature's work - this can be handled using the 'normal' workflow.
 * 2) Save your changes and fix the bug - this is a little bit more sticky, so I'll explain it below.

Hold everything, I need to squash that bug!
If you can't just roll the fix into your feature work, you are going to need another way to go about things. At a minimum you want to:
 * Fix the bug in the main branch
 * Avoid putting any of your in-progress code into the main branch
 * Make sure the fix is in both your current feature work and the main branch

That's a tall order, but easily doable with the right workflow:
 * 1) Commit your current feature work (this will save your progress)
 * 2) Check out a copy of the main branch, switching away from your feature branch
 * 3) Fix the bug and commit (again, make SURE you are on the copy of the main branch, not your feature branch)
 * 4) If needed, pull from the main branch.
 * 5) Push to the main branch
 * 6) Check out your feature branch and resume work where you left off

This way, the bug is fixed in the main branch, and you are working where you were before. As a bonus, the next time you pull from the main branch while working on your feature (# 2.2 in the normal workflow), your fix will get into your current working branch!