There's nothing sexy about source control, but it—and the skills to use it—are essential to software development. Long gone are the days where it's appropriate to simply use a network share that probably gets backed up—or worse, nothing at all—to manage source code.
Source control provides these benefits:
Version Control, Revision Control, Source Code Control, call it whatever you want as long as you use it!
While any Revision Control System (RCS) will provide some benefits, the best option is to use a modern system. Older systems, Visual Source Safe being a (now defunct) example, rely on exclusive file locking to prevent users from editing the same file at once. That worked, but it led to a lot of bottlenecks, particularly when a developer went on vacation and forgot to check in first! Modern systems (Git, SVN, Mercurial, etc.) let any developer edit any file at any time and rely on merging to deal with conflicts. This usually works great when commits are frequent and small, though developers need to be skilled at reviewing and resolving conflicts.
Deciding which system to use depends a lot on the team and the project requirements. Generally any modern system is acceptable, so the easiest option is to pick the one your team is most skilled with.
Once you've got a source control system, you then need to use it effectively. Your team needs to have some policies in place, and these will of course need to vary based on team and project specifics.
Branching and Releasing
The biggest policy to sort out is your branching/release strategy.
The basic strategy I'd start with is to have a trunk for development and branches for features. Feature branches should be specific to one smallish feature. They should be merged back to the trunk when completed—and then deleted. I'd also recommend branches for maintenance support (e.g. create a 1.0_Support branch while you work on Version 2 in the trunk). You can also create branches for staging/production to track exactly what is released and when, though tags can also be used for this in some scenarios.
Branches are cheap, but they aren't free—as it takes some extra work on the part of the developer to use and manage branches. On a single developer project where I controlled the release schedule I'd probably do most development in the trunk and only use branches for big (20–40 hour) features. On other projects I'd generally try to keep the trunk in a stable and deployable state, and use a branch for any feature that is bigger than one commit.
Frequency of Committing
One big difference of opinion among developers is what they feel is the proper commit frequency and size.
My personal preference is small commits. I prefer each commit to be focused on one logical "thing" only. A single feature might entail 3-5 (or more) commits, though 1 commit is common for a small feature. I don't commit on a particular clock schedule, rather I wait until I get to some stable but not necessarily finished point. I probably end up committing every 2-6 hours of effort, though on some work I commit many times an hour.
To my mind that level of committing makes it easy to review the changes and see specific history of what and why changes were made. It does tend to lead to more verbose logs, so some developers would find my level too much. I'd rather err on the side of noisy verbosity though, since it's easy to filter logs and combine multiple commits into a single review.
On the other end of the spectrum, some developers rarely commit. Either it's just not a part of their process and becomes an afterthought, or they avoid committing out of fear of letting someone see their code in an unpolished state. Big commits are hard (sometimes impossible) to review, and if you find yourself writing commit messages with lots of "ands"—or worse being unable to properly summarize a commit—then it's probably too big!
Personally, I use a commit as a chance to conduct my own code review. I review every line of every commit. I would estimate that 95% of my commits don't make it through a review without changes. This is another compelling argument for keeping the scope of commits small.
Comments on commits are a necessity. There is nothing worse than reviewing logs to find out what's going on and finding a commit with no message. You then have to review the code changes and reverse engineer the comment!
Comments can also be too detailed. The goal should be to summarize the code changes—ideally in one line—not to reiterate the code in English!
Frequency of Updating
When working with other developers, the frequency at which you update is very important. If you go too long before getting fresh updates you increase the chance of collisions. When you are working in a branch you are isolated from other developers, so if your branch is open long enough you'll want to merge from the trunk regularly to keep current. This will lessen the merge conflicts when you merge the branch back to the trunk. It will also make sure your feature code works with other developers' changes.
Most source control systems are not very good at storing binary assets, so for most projects I recommend against putting binary build outputs (like DLLs or executables) in source control, instead rebuilding from source as needed.
I also try to avoid committing third party dependencies when possible, instead relying on (and trusting) services like NuGet (for .Net) to maintain specific versions.