Does your team do all of their development on a single branch? Does everyone push to something called 'develop' or 'trunk', mingling their in-progress work? Or even if you work alone, are you pushing everything to the same place no matter how unfinished?
This is a fairly common way of working, especially in companies with centralised verson control systems. It seems intuitively like the easiest way to develop, if you make one-off monolithic releases. If you want some more flexibility to make releases more often - typical of online services - then it can actually get in your way.
It's a little like having a big bucket, and occasionally someone will throw some code in which may or may not be finished. At some point, someone has to empty the bucket, but what is in the bucket is hard to reason about. Using feature branches, by contrast, is like having an empty bucket waiting while everyone fills up small mugs nearby. The mugs get emptied in when people are sure the contents is ready.
You're also missing out on benefitting from having all code related to a single feature in one place. You can compare the tip of a feature branch with the stable master branch, giving you exactly what changed, and allowing you to analyse and report on it.
What are Feature Branches?
The fundamental idea behind feature branches is that all work is done in isolation on a dedicated branch rather than the main branch. A developer or group of developers tasked with creating a feature or bugfix create a branch from the stable branch, and can iterate without polluting the master branch with potentially unstable, unfinished code.
The side effect of this is that the master branch should always contain stable code; theoretically, any commit on the master branch could be used to create a release.
Feature branches match the natural method of development. Individuals or small groups are responsible for a feature - why not reflect that in your version control and release process?
Why Use Feature Branches?
Less Communication Overhead
This one depends a lot on your deployment process, but unless you have perfect continuous deployment, there will be some concept of a 'release'. There is a line in the sand demarcating what users used to see and what they see now, which means at some point in the development process somebody has to promote code from work-in-process to live.
This requires synchronising developers so that they all work on the same cycle - develop code, pause, start testing, pause, now there's a code freeze in order to make a release. As well as the overhead of herding cats in this way, it also restricts everyone to the same schedule, which isn't useful as features can all take different amounts of time.
Using feature branches, the release process can be decoupled from the development process. The "develop" or "work in progress" branch should be the final resting place of stable code ready to be tested. Developers can merge when they are ready, allowing asynchronous development and reducing the need to corral everyone around releases.
There are more and more Doing-things-to-your-code-as-a-Services these days. You can have your code coverage measured, have checks to see if your dependencies are up to date, host and build your documentation for you or even add CLAs for you.
These tools allow you to get reports about all kinds of ways your new feature will affect your existing code. Each feature or bugfix can be analysed in isolation.
With Landscape, for example, each pull request generates a report of all new bugs, style problems and other errors introduced. This is great for incremental improvement - if your code coverage goes down or static analysis reports more problems than the base branch, then you realise straight away and can act in isolation on a small amount of code. Over time, this keeps the main branch healthy and encourages fixing technical debt the moment it appears.
If someone is a new developer - either in terms of experience, or new to the language or company - then they will probably not be doing things exactly the way the rest of your organisation does. Code reviews can help guide these newer employees, and they're also useful for everyone, as it allows developers to learn from the way they each solve problems.
The neat thing is that further commits go onto the same branch, keeping everything separate until the code review is complete at which point it can be merged, and allowing you to see the results of feedback.
Test and Build Features in Isolation
Most CI tools like CircleCI or Travis will build every branch they see. This gives you an individual success or failure for your particular feature. It also means that if the build breaks, it's definitely from your code. Compare this to the single development branch approach: if many people are committing work-in-progress features to the same branch, it's not immediately obvious whose responsibility it is if the build breaks or tests fail.
I once worked on a Java-based web application which took design patterns very seriously. Specifically, the Big Ball of Mud and God Object anti-patterns. A single object with around 5,000 lines (most of which were getters and setters) was instantiated for every request, with a reference to every possbile service or helper class in case that particular web view needed it. It spread throughout the codebase like a blobfish, an object-oriented Mr. Creosote ready to consume any and all state.
This meant that every feature, bugfix or refactor touched this class and this file. Having everyone develop on the bucket branch meant a diff between the stable tag and the current work in process would reveal several changes but it was not obvious which change belonged to which feature or bugfix.
Now not all projects will be filled with such concentrated misery but it's a reasonable bet that some code is more used than others, and concurrent feature development will inevitably lead to overlap. Keeping development in separate branches allows you to associated particular code changes with particular features.
Pick and Choose Features for Release
Let's take the simplest example - there is only one single branch. All code produced in the organisation, from the most beautiful, artisanal craft to the lowliest tired-on-Friday-evening scribbles, ends up in this single branch. How would you release in this case? Somebody has to take responsibility and say that a certain commit has only code that is stable enough for release.
If you are using feature branches correctly, then your master branch will always be stable. Since only tested, working code should be merged into master, then a release can be created at any point in time from any commit on the master branch. If you're brave you could even have a CI server build and release for you on every merge.
This means that if you have a scheduled release, but a feature is not finished yet, you simply don't merge in the first place and you don't have to delay the release until the feature is stable - you can simply release without it, if you want to.
How Can I Start?
If you're using Git, then the most excellent git-flow extension will help you out. Git Flow is a branching model described by Vincent Driessen which codifies creating feature branches, as well as defining hotfix branches and releases.
Similarly, hg-flow exists for Mercurial users.
Users of GitHub will likely already be familiar with pull requests. If you're not already using them on your own code, even if you're the only developer, then you should!
Of course you don't need extra tools to get started, as it is super simple - just branch from a stable point, build your feature, and merge back when it's done.