GitLab Epics let you group issues from multiple projects into a single, coherent plan.
Imagine you’re building a new feature that spans several distinct services, each managed in its own GitLab project. You’ve got front-end work in webapp, API development in backend-api, and database schema changes in database-schemas. Without Epics, tracking progress across these would be a nightmare of cross-project issue linking and manual aggregation.
Here’s a real-world example. Let’s say we’re developing a new "User Profile" feature.
Project: webapp
- Issue:
Create User Profile UI(ID:webapp#123) - Issue:
Implement Profile Edit Form(ID:webapp#124)
Project: backend-api
- Issue:
Add /users/:id endpoint(ID:backend-api#45) - Issue:
Implement Profile Update logic(ID:backend-api#46)
Project: database-schemas
- Issue:
Add 'bio' column to users table(ID:database-schemas#7)
To tie these together, we create an Epic, let’s call it "User Profile Feature".
We can then add all the relevant issues to this Epic. In GitLab, you’d navigate to the Epic’s page (under the "Plan" section of your group or project) and use the "Related Issues" or "Add Issue" button. You can add issues from any project within your group.
Once issues are linked, GitLab aggregates their status. You can see at a glance how many are To Do, In Progress, or Done.
The true power comes with the Roadmap view. For our "User Profile Feature" Epic, we can assign start and end dates.
- Epic: "User Profile Feature"
- Start Date:
2023-10-26 - End Date:
2023-11-10
- Start Date:
GitLab automatically visualizes this on the Roadmap. If you have multiple Epics, you’ll see them laid out chronologically, with bars representing their duration. This gives you a high-level overview of your team’s planned work, dependencies between Epics (you can link Epics themselves), and potential bottlenecks. You can filter the roadmap by labels, assignees, and other criteria to focus on specific areas.
Here’s a snippet of what a roadmap.json might look like if you were exporting or interacting with the API (though you primarily use the UI):
[
{
"id": "gid://gitlab/Epic/1",
"title": "User Profile Feature",
"startDate": "2023-10-26",
"endDate": "2023-11-10",
"webUrl": "https://gitlab.com/groups/mygroup/-/epics/1",
"issues": [
{"id": "gid://gitlab/Issue/1001"},
{"id": "gid://gitlab/Issue/1002"},
{"id": "gid://gitlab/Issue/2005"},
{"id": "gid://gitlab/Issue/2006"},
{"id": "gid://gitlab/Issue/3007"}
]
},
{
"id": "gid://gitlab/Epic/2",
"title": "Notifications Overhaul",
"startDate": "2023-11-05",
"endDate": "2023-11-20",
"webUrl": "https://gitlab.com/groups/mygroup/-/epics/2",
"issues": [...]
}
]
The system automatically calculates the progress of an Epic based on the weighted completion of its child issues. By default, each issue is weighted equally, so an Epic with 5 issues, where 2 are done, is considered 40% complete. However, you can manually adjust the weight of individual issues within an Epic to reflect their relative effort or importance, allowing for a more accurate progress calculation. This is done by editing the issue and finding the "Weight" field, typically set to values like 1, 2, 3, 5, 8, etc.
The most surprising thing most people don’t realize is that Epics are a group-level construct by default. While you can associate issues from a single project with an Epic, their primary purpose is to aggregate work across projects within a group, providing a unified planning and reporting layer that transcends individual project boundaries.
After mastering Epics and Roadmaps, you’ll likely want to explore Portfolio Management features to manage dependencies and timelines across multiple groups.