This article is an excerpt from our new book. For the full guide to building a collaborative software team, pick up your free copy!
In this article, we’ll show you how to create a lightweight and powerful GitHub workflow using Epics and Milestones. By applying some basic agile principles, you can combine Epics, issues (as user stories), markdown checklists (as sub-tasks), and GitHub Milestones to ship better software with less overhead. Read on to learn how we do it!
The difference between Epics and Milestones
One of our most common questions is how Milestones and Epics interact. Sometimes they're even confused for one another. Milestones and Epics aren't interchangeable; in fact, they work best when used together.
In an agile framework, a sprint is typically 2-4 weeks of work with a goal of shipping workable code by the end. These iterative changes are a cornerstone of agile development. In GitHub, Milestones take the place of sprints.
Milestones are used to track the progress of issues and pull requests. They contain issues related by time, and not necessarily related by subject. The scope of work is fixed once a sprint begins.
Epics contain issues related in subject, and the scope is flexible. Whereas Epics can span multiple repositories, GitHub Milestones do not.
In order to use Epics and Milestones effectively, we need to step back and look at what they're made up of: GitHub issues.
Going back to the heart of the issue
In GitHub, issues take the place of user stories – high-level feature descriptions that help define benefit from a customer’s perspective. Remember, once a sprint (Milestone) begins, their scope should remain fixed.
Let's touch on what that means in practice.
The issue as user story
The common structure for a user story addresses the “who, what, and why” of a feature:
“As a <user type>, I want to <task> so that <goal>.”
“As a <customer>, I want to <create an account> so that <I can make purchases>.”
We suggest sticking that user story right in the issue's title. You can set up issue templates to keep things consistent.
The point is to make the issue well-defined for everyone involved: it identifies the audience (or user), the action (or task), and the outcome (or goal) as simply as possible. There’s no need to obsess over this structure; other alternatives have been proposed. As long as the what and why of a story are easy to spot, you’re good.
To learn more about why a user story format is useful, we spoke with product management expert Alexander Cowan – faculty at the University of Virginia Darden and Managing Director at Synapse Partners.
“It's important to remember that user stories are there to drive team discussions about what is a valuable outcome for the user,” he says. “They're not just another format for a specification; specifications are about output and that's why spec-driven products miss the mark so often with the user.”
To illustrate this concept, he suggests a simplified example of a website that sells something. In this example, a related story might be:
As a [buyer persona], I want to [see my final items and charges] so I can [make sure I have what I wanted, and agree with the applicable charges.]
Alex elaborates, “That's a good starting point for a team to design solutions for that part of the buying experience. A specification-driven approach would probably say something like 'The page must show item descriptions, quantities, costs as well as tax and shipping.' It seems fine too, doesn't it?”
“A developer given that specification will probably build something that does all those things. But is it easy for the user to understand? Does it play well with the rest of the experience? Those are the kind of questions where specifications don't perform as well. You usually end up with something that's not wrong, per se, but just is not very good. And that's not good enough anymore in today's hyper-competitive marketplace.”
Defining agile in GitHub
To review, this is how we map agile concepts to GitHub/ZenHub:
Epic > User Story > Sub-Task
Epic > GitHub issue > Markdown Checklist
Note: Without ZenHub, your GitHub issues lack hierarchy; they’re simply a list. There’s no clear indicator of which issues are related and where the dependencies lie. ZenHub’s Epics add this crucial layer of hierarchy.
Working with epics in GitHub
In agile, a user story is the smallest unit of work, and an Epic is essentially a "big" user story. If “as a customer, I want to be able to create an account” is a user story, the entire account management feature may be an Epic.
In ZenHub and GitHub, Epics are a theme of work that contain issues (stories) needed to complete that larger goal. They keep product backlogs coherent and organized while providing greater control end-to-end over the release process.
As you can see, we have three three hierarchical layers: epic, issue, and sub-task (which may be linked to its own issue if necessary.)
Issue, or Epic?
When deciding whether an issue should become an Epic (or vice versa), consider the time and complexity.
Issues should be completed in the smallest amount of time possible. If an issue will take weeks or months to finish, it should probably be an Epic. Likewise, if an issue becomes too complex – if there are several tasks required to complete it – it’s likely better off as an Epic. Splitting these tasks into easily-completed chunks of work helps reduce technical debt and ensures you can ship impactful changes more frequently.
A sample workflow using Epics and Milestones
Here’s an example of how Milestones and Epics interact. Let’s say we’re redoing ZenHub’s website as part of a rebranding effort.
An Epic might be called “Website redesign”. Inside that Epic, I create one issue for each page in that website:
As I add issues to my Epic, I'll also create markdown checklists of tasks needed to complete that page.
At the beginning of a sprint, my team will create a Milestone (ie "Sprint 3"). Having already estimated complexity on the issues in our backlog, we’ll decide as a team which issues should be included in our Milestone. We use Burndown Charts, which give us a pretty good idea of how many story points we can tackle in a given sprint.
We clearly can’t complete the entire website in two weeks, but finishing the homepage seems reasonable.
We’ll add the Homepage issue to our Milestone, and perhaps a couple unrelated technical fixes. Together, these issues form a chunk of work that, based on our team’s projected velocity, we believe we can finish, test, and ship over the next two weeks.
Milestones and Epics aren't swappable concepts, but they are complementary.
The benefits of pairing Epics and Milestones
Once you understand the differences between Epics and Milestones, you’re ready to use both of them effectively.
Epics are intended to give you a broad understanding of larger initiatives. When paired with Milestones, you’re able to work towards these bigger goals in manageable iterations. This means you deliver more business value (e.g. workable code) more frequently.
If you use Epics without Milestones, you might get bogged down in details as you pursue big chunks of poorly defined work.
If you use Milestones without Epics, it's hard to effectively plan or pursue bigger goals. It's also more difficult to visualize how big chunks of work are progressing alongside all your other tasks. The lack of direction could lead to unclear priorities.
However, pairing Milestones with Epics gives you a granular way to plan and achieve your product backlog. It clarifies both the big picture and the minute details that make it up, providing everything necessary to ship better projects faster.
Pssst! If you haven't already, download ZenHub free to get task boards, epics, and more – directly added to GitHub.
If you liked this post, sign up to receive more like it.