GitHub Issue Tree: Implementing Jira-like Hierarchies
A comprehensive guide to creating Epic → Story → Task hierarchies in GitHub Issues using native task lists and the "Tracked by" feature.
Overview
GitHub Issue Tree: Implementing Jira-like Hierarchies
A comprehensive guide to creating Epic → Story → Task hierarchies in GitHub Issues using native task lists and the "Tracked by" feature.
Table of Contents
- Overview
- Why This Workaround
- Core Concepts
- Label Setup
- Issue Templates
- Creating the Hierarchy
- How "Tracked by" Works
- Naming Conventions
- Real-World Example
- Querying and Filtering
- Best Practices
- Limitations vs Jira
- Advanced Workflows
Overview
GitHub Issues doesn't natively support hierarchical issue types like Jira's Epic → Story → Task structure. However, by combining task lists with cross-references, we can create a surprisingly effective hierarchy that:
- Provides visual progress tracking with progress bars
- Shows automatic "Tracked by" relationships
- Maintains bidirectional linking between parent and child issues
- Works seamlessly with GitHub Projects and automation
- Requires no third-party tools or plugins
What we'll build:
Epic #100: User Authentication System
├── Progress: ████████░░ 80% (4 of 5 stories completed)
├── Story #101: Login Flow ✓
│ ├── Task #104: API endpoint ✓
│ ├── Task #105: UI component ✓
│ └── Task #106: Tests ✓
├── Story #102: Registration ✓
│ ├── Task #107: Validation logic ✓
│ └── Task #108: Email verification ✓
├── Story #103: Password Reset (In Progress)
│ ├── Task #109: Reset token generation ✓
│ └── Task #110: Email template (Open)
└── Story #111: OAuth Integration (Open)
Why This Workaround
The Problem
GitHub Issues is flat by design. While this simplicity works for many projects, teams migrating from Jira or managing complex features need:
- Hierarchical organization - Group related work into logical units
- Progress visibility - See completion status at a glance
- Scope management - Break large features into manageable pieces
- Sprint planning - Organize work into achievable increments
The Solution
GitHub's task list feature (introduced in 2022) provides:
- Checkboxes that link to issues -
- [ ] #123 - Automatic progress bars - Visual completion tracking
- Bidirectional linking - "Tracked by" appears on child issues
- Markdown-based - No special syntax or tools needed
When to Use This
Use hierarchical issues when:
- Developing complex features spanning multiple PRs
- Coordinating work across multiple team members
- Planning sprints or releases
- Migrating from Jira to GitHub
- Managing dependencies between issues
Don't overcomplicate small projects - flat issues work fine for simple bug fixes or single-person repositories.
Core Concepts
Three-Tier Hierarchy
| Level | Purpose | Typical Scope | Assignee |
|---|---|---|---|
| Epic | Large initiative spanning multiple sprints | 2-6 weeks, 3-10 stories | Product/Team Lead |
| Story | User-facing feature or capability | 3-5 days, 2-5 tasks | Feature Owner |
| Task | Technical implementation unit | 4-8 hours, 1 PR | Developer |
Task List Syntax
GitHub recognizes these patterns:
- [ ] #123 - Unchecked, links to issue #123
- [x] #124 - Checked, marks issue as complete
- [ ] Description without issue number - Simple checkbox
- [ ] #125 Story: Login implementation - Descriptive text
Important: GitHub automatically:
- Creates clickable links from issue numbers
- Shows progress bars when task lists contain issue references
- Adds "Tracked by #parent" to child issues
- Updates progress when child issues are closed
Visual Hierarchy
Epic (type:epic)
│
├─ Story (type:story, epic:100)
│ │
│ ├─ Task (type:task, story:101)
│ ├─ Task (type:task, story:101)
│ └─ Task (type:task, story:101)
│
└─ Story (type:story, epic:100)
│
└─ Task (type:task, story:102)
Label Setup
Labels help filter and organize hierarchical issues. Set up these labels once per repository.
Required Labels
Create labels using gh CLI:
# Issue type labels
gh label create "type:epic" \\
--description "Large initiative spanning multiple stories" \\
--color "7057ff"
gh label create "type:story" \\
--description "User-facing feature or capability" \\
--color "0e8a16"
gh label create "type:task" \\
--description "Technical implementation unit" \\
--color "1d76db"
# Status labels
gh label create "status:planning" \\
--description "Still being defined" \\
--color "fbca04"
gh label create "status:ready" \\
--description "Ready for development" \\
--color "0e8a16"
gh label create "status:in-progress" \\
--description "Currently being worked on" \\
--color "1d76db"
gh label create "status:blocked" \\
--description "Cannot proceed due to dependency" \\
--color "d93f0b"
gh label create "status:review" \\
--description "Awaiting review or testing" \\
--color "fbca04"
# Priority labels
gh label create "priority:high" \\
--description "High priority work" \\
--color "d93f0b"
gh label create "priority:medium" \\
--description "Medium priority work" \\
--color "fbca04"
gh label create "priority:low" \\
--description "Low priority work" \\
--color "0e8a16"
Optional Enhancement Labels
# Epic-specific relationship labels
gh label create "epic:auth" \\
--description "Part of User Authentication epic" \\
--color "7057ff"
gh label create "epic:payments" \\
--description "Part of Payment Processing epic" \\
--color "7057ff"
# Estimation labels (Fibonacci sequence)
gh label create "estimate:1" --color "c2e0c6"
gh label create "estimate:2" --color "c2e0c6"
gh label create "estimate:3" --color "c2e0c6"
gh label create "estimate:5" --color "c2e0c6"
gh label create "estimate:8" --color "c2e0c6"
gh label create "estimate:13" --color "c2e0c6"
Bulk Label Creation
Save this as labels.json:
[
{"name": "type:epic", "color": "7057ff", "description": "Large initiative spanning multiple stories"},
{"name": "type:story", "color": "0e8a16", "description": "User-facing feature or capability"},
{"name": "type:task", "color": "1d76db", "description": "Technical implementation unit"},
{"name": "status:planning", "color": "fbca04", "description": "Still being defined"},
{"name": "status:ready", "color": "0e8a16", "description": "Ready for development"},
{"name": "status:in-progress", "color": "1d76db", "description": "Currently being worked on"},
{"name": "status:blocked", "color": "d93f0b", "description": "Cannot proceed due to dependency"},
{"name": "priority:high", "color": "d93f0b", "description": "High priority work"},
{"name": "priority:medium", "color": "fbca04", "description": "Medium priority work"},
{"name": "priority:low", "color": "0e8a16", "description": "Low priority work"}
]
Then create all labels:
cat labels.json | jq -r '.[] | "gh label create \\"\\(.name)\\" --description \\"\\(.description)\\" --color \\"\\(.color)\\""' | bash
Issue Templates
Create reusable templates for consistent issue creation.
Epic Template
Save as .github/ISSUE_TEMPLATE/epic.md:
---
name: Epic
about: Large initiative spanning multiple stories
title: '[EPIC] '
labels: 'type:epic, status:planning'
assignees: ''
---
## Epic Overview
**Goal:** [Describe the high-level business objective]
**Value Proposition:** [Why are we building this? What problem does it solve?]
**Success Metrics:**
- [Metric 1: e.g., 50% reduction in login time]
- [Metric 2: e.g., 90% user satisfaction]
- [Metric 3: e.g., Zero security incidents]
## User Stories
### In Scope
- [ ] #<story-number> [Story title]
- [ ] #<story-number> [Story title]
- [ ] #<story-number> [Story title]
### Out of Scope (Future Consideration)
- [ ] [Feature or capability deferred to later]
- [ ] [Feature or capability deferred to later]
## Dependencies
- **Blocks:** #<issue> - [What this epic blocks]
- **Blocked by:** #<issue> - [What blocks this epic]
- **Related to:** #<issue> - [Related epics or initiatives]
## Technical Considerations
- [Key architectural decision or constraint]
- [Technology choices or requirements]
- [Performance/security/scalability concerns]
## Timeline
- **Target Start:** YYYY-MM-DD
- **Target Completion:** YYYY-MM-DD
- **Actual Start:** [Fill when started]
- **Actual Completion:** [Fill when completed]
## Acceptance Criteria
- [ ] All stories completed and merged
- [ ] Documentation updated
- [ ] Tests passing (unit, integration, e2e)
- [ ] Security review completed
- [ ] Performance benchmarks met
- [ ] Deployed to production
## Notes
[Additional context, links to designs, stakeholder discussions, etc.]
Story Template
Save as .github/ISSUE_TEMPLATE/story.md:
---
name: Story
about: User-facing feature or capability
title: '[STORY] '
labels: 'type:story, status:planning'
assignees: ''
---
## User Story
**As a** [user type]
**I want** [goal or desire]
**So that** [benefit or value]
## Description
[Detailed description of what needs to be built]
## Epic
**Tracked by Epic:** #<epic-number>
## Tasks
### Backend
- [ ] #<task-number> [API endpoint implementation]
- [ ] #<task-number> [Database schema/migration]
- [ ] #<task-number> [Business logic/validation]
### Frontend
- [ ] #<task-number> [UI component implementation]
- [ ] #<task-number> [State management]
- [ ] #<task-number> [Form validation/error handling]
### Testing & Documentation
- [ ] #<task-number> [Unit tests]
- [ ] #<task-number> [Integration tests]
- [ ] #<task-number> [E2E tests]
- [ ] #<task-number> [Documentation updates]
## Acceptance Criteria
- [ ] [Specific, testable criterion 1]
- [ ] [Specific, testable criterion 2]
- [ ] [Specific, testable criterion 3]
- [ ] [Specific, testable criterion 4]
## Design
**Mockups/Wireframes:** [Link to Figma, screenshots, or design files]
**API Contract:**
```json
// Example request/response
Dependencies
- Depends on: #<issue> - [Must be completed first]
- Blocks: #<issue> - [This blocks other work]
Estimation
Story Points: [1, 2, 3, 5, 8, 13] Estimated Hours: [Development time estimate]
Notes
[Additional context, technical decisions, edge cases, etc.]
### Task Template
Save as `.github/ISSUE_TEMPLATE/task.md`:
```markdown
---
name: Task
about: Technical implementation unit
title: '[TASK] '
labels: 'type:task, status:ready'
assignees: ''
---
## Task Description
[Clear, concise description of the technical work]
## Story
**Tracked by Story:** #<story-number>
## Implementation Details
**Files to modify:**
- `path/to/file1.ts`
- `path/to/file2.ts`
**Approach:**
1. [Step-by-step implementation approach]
2. [Step 2]
3. [Step 3]
**Code example/pseudocode:**
```typescript
// Example of expected implementation
Acceptance Criteria
- Code implements specification
- Unit tests added/updated
- No breaking changes to existing functionality
- Code reviewed and approved
- Documentation updated (if needed)
Testing Checklist
- Unit tests pass locally
- Integration tests pass locally
- Manual testing completed
- Edge cases handled
Pull Request Checklist
- PR created and linked to this issue
- CI/CD pipeline passing
- Code review approved
- Merged to main branch
Estimated Time
Hours: [e.g., 4-6 hours]
Notes
[Technical notes, gotchas, or considerations]
---
## Creating the Hierarchy
Step-by-step workflow for building issue hierarchies.
### Step 1: Create the Epic (Top-Down Approach)
```bash
# Create epic with template
gh issue create \\
--title "[EPIC] User Authentication System" \\
--label "type:epic,status:planning,priority:high" \\
--body "$(cat .github/ISSUE_TEMPLATE/epic.md)"
# Note the issue number (e.g., #100)
Alternative: Use GitHub UI
- Navigate to Issues → New Issue
- Select "Epic" template
- Fill in the template
- Submit
Step 2: Create Story Issues
Create stories that belong to the epic:
# Story 1
gh issue create \\
--title "[STORY] Login Flow Implementation" \\
--label "type:story,status:planning,epic:auth" \\
--body "Tracked by Epic: #100
As a user
I want to log in with email and password
So that I can access my account securely
## Tasks
"
# Story 2
gh issue create \\
--title "[STORY] User Registration" \\
--label "type:story,status:planning,epic:auth" \\
--body "Tracked by Epic: #100"
# Story 3
gh issue create \\
--title "[STORY] Password Reset Flow" \\
--label "type:story,status:planning,epic:auth" \\
--body "Tracked by Epic: #100"
Step 3: Link Stories to Epic
Update epic #100 to include story task list:
gh issue edit 100 --body "$(cat <<'EOF'
## Epic Overview
Implement comprehensive user authentication system.
## Stories
- [ ] #101 Login Flow Implementation
- [ ] #102 User Registration
- [ ] #103 Password Reset Flow
## Timeline
Target: Q1 2025
EOF
)"
Result: Epic #100 now shows a progress bar tracking 0/3 stories.
Step 4: Create Task Issues
For each story, create granular tasks:
# Tasks for Story #101 (Login Flow)
gh issue create \\
--title "[TASK] Implement JWT authentication endpoint" \\
--label "type:task,status:ready,story:101" \\
--assignee "@me" \\
--body "Tracked by Story: #101
Implement POST /api/auth/login endpoint with JWT token generation."
gh issue create \\
--title "[TASK] Create login form component" \\
--label "type:task,status:ready,story:101" \\
--assignee "@me"
gh issue create \\
--title "[TASK] Add login flow tests" \\
--label "type:task,status:ready,story:101" \\
--assignee "@me"
Step 5: Link Tasks to Story
Update story #101 with task list:
gh issue edit 101 --body "$(cat <<'EOF'
**Tracked by Epic:** #100
As a user I want to log in with email and password.
## Tasks
### Backend
- [ ] #104 Implement JWT authentication endpoint
### Frontend
- [ ] #105 Create login form component
### Testing
- [ ] #106 Add login flow tests
EOF
)"
Step 6: Work the Tasks
As work progresses:
-
Assign and start task:
gh issue edit 104 --add-label "status:in-progress" -
Create PR and link:
gh pr create \\ --title "Implement JWT authentication endpoint" \\ --body "Closes #104" -
Merge PR: Task #104 automatically closes
-
Check task in story:
# Manually check the task in story #101 # Or let GitHub auto-check when #104 closes