# GitHub sub-issues: create, track and automate

> **TL;DR** Open an issue and click Create sub-issue under its description, or use the dropdown beside it to add an existing issue. A parent holds up to 100 sub-issues, nested up to eight levels. In Projects, enable the Parent issue and Sub-issue progress fields, then group or filter with parent-issue:OWNER/REPO#NUMBER. The GraphQL API uses addSubIssue, removeSubIssue and reprioritizeSubIssue.

Sub-issues turn one GitHub issue into a tree. A parent issue lists its children with a progress count, each child links back to its parent, and GitHub Projects can group, filter and chart by that relationship. This guide covers creating them, using them in Projects, the limits, hiding them from views, and the API calls behind them. Everything up to the last section needs only GitHub.

## How do I create a sub-issue?

Start from the parent issue.

1. Open the issue that should become the parent.
2. At the bottom of its description, click **Create sub-issue**.
3. Type the sub-issue's title. Optionally add a description and set the issue type, assignees, labels, projects and milestone.
4. To add several in a row, select **Create more sub-issues**.
5. Click **Create**.

To attach an issue that already exists, click the dropdown next to **Create sub-issue**, choose **Add existing issue**, and pick from the suggestions or search by title or number. Switch the repository in the picker to attach an issue from another repository.

From a child issue you can also go the other way: its **Relationships** menu has **Add parent**.

The GitHub CLI does the same from a terminal:

- Create a new sub-issue: `gh issue create --title "TITLE" --body "ISSUE-DESCRIPTION" --parent PARENT-ISSUE-NUMBER`. The parent can be an issue number or URL.
- Attach existing issues: `gh issue edit PARENT-ISSUE-NUMBER --add-sub-issue SUB-ISSUE-NUMBER`. The flag takes a comma-separated list.
- Detach from the parent's side: `gh issue edit PARENT-ISSUE-NUMBER --remove-sub-issue SUB-ISSUE-NUMBER`.
- Detach from the child's side: `gh issue edit SUB-ISSUE-NUMBER --remove-parent`.

`gh issue view ISSUE-NUMBER` prints the parent and a "Sub-issues" section with each child's state and the completion count.

## What are the limits on sub-issues?

A parent can hold up to 100 sub-issues, and sub-issues can nest up to eight levels deep. An issue has one parent at most. Sub-issues can come from other repositories, so an epic in one repository can own work in several.

Plan the hierarchy with the 100 limit in mind. An epic that needs more than 100 pieces of work is better split into child epics, each with its own sub-issues, which the eight levels allow.

## How do sub-issues show up in GitHub Projects?

Through two fields that are hidden until you turn them on.

1. In a table view, click **+** in the rightmost field header.
2. Under "Hidden fields", click **Parent issue**.
3. Repeat and click **Sub-issue progress**.

**Parent issue** names each item's parent. Group a view by it (**View** → **Group by** → **Parent issue**) to see each epic with its children underneath. **Sub-issue progress** shows how many of an item's sub-issues are complete.

To filter to the children of one issue, type `parent-issue:` and choose the issue from the list, or type it in full as `parent-issue:"octocat/game#4"`, with your own owner, repository and issue number.

A project's built-in workflows include **Auto-add sub-issues to project**. Its rule reads "When an item in the project has sub-issues", then "Add sub-issues to the project", so children follow their parent onto the board as work is broken down. Turn it on from the project's **Workflows** page.

## How do I hide sub-issues in a view?

Filter out the items that have a parent. GitHub's docs do not describe a dedicated setting for this, but they document `no:FIELD` for any field, and Parent issue is a field, so the filter is `no:parent-issue`.

That keeps only top-level items, which suits a roadmap or an epics board. The docs show `no:` with assignee, reviewers and priority, not with Parent issue, so check the result on your project before saving the view. The inverse, `has:parent-issue`, shows only sub-issues.

GitHub's View menu also has a **Show hierarchy** toggle, recorded in a capture of GitHub's interface taken on 5 August 2026. The capture records the toggle and not what it does, and GitHub's filtering and layout docs do not mention it, so try it on a copy of your view first.

## How do I manage sub-issues with the GraphQL API?

Three mutations change the relationship, and three fields on `Issue` read it. The mutations identify issues by node ID, not by number; `addSubIssue` also accepts the child's URL as `subIssueUrl`.

| Mutation               | Input                                                                   | What it does                                       |
| ---------------------- | ----------------------------------------------------------------------- | -------------------------------------------------- |
| `addSubIssue`          | `issueId`, plus `subIssueId` or `subIssueUrl`, optional `replaceParent` | Makes the issue a sub-issue of `issueId`           |
| `removeSubIssue`       | `issueId`, `subIssueId`                                                 | Unlinks the child; the issue itself is not deleted |
| `reprioritizeSubIssue` | `issueId`, `subIssueId`, and `afterId` or `beforeId`                    | Moves one child within the parent's ordered list   |

The first operation below adds a child, and the second reads an issue's tree through `parent`, `subIssues` and `subIssuesSummary`:

```graphql
mutation AddSubIssue($input: AddSubIssueInput!) {
  addSubIssue(input: $input) {
    issue {
      id
    }
    subIssue {
      id
    }
  }
}

query IssueTree($owner: String!, $name: String!, $number: Int!) {
  repository(owner: $owner, name: $name) {
    issue(number: $number) {
      parent {
        number
        title
      }
      subIssuesSummary {
        total
        completed
        percentCompleted
      }
      subIssues(first: 100) {
        nodes {
          number
          title
          state
        }
      }
    }
  }
}
```

Send the mutation with `{"input": {"issueId": "PARENT_NODE_ID", "subIssueId": "CHILD_NODE_ID"}}`. If the child already has a parent, the call is refused unless the input also carries `"replaceParent": true`, which moves the child to the new parent. In the query, `first: 100` matches the per-parent limit, so one page returns every child.

## How does Gitsu handle sub-issues?

Gitsu reads and writes sub-issues through the same mutations, and shows the tree in an item's detail view.

In the **Sub-issues** section of an issue:

- **Create sub-issue** makes a new child. Type a title, and choose **Add details** to write a description.
- **Link issue** attaches an existing issue. The picker lists the board's own issues first, can switch to another repository, and accepts a pasted issue URL or a `#number`.
- Each child can be unlinked or dragged to a new position, which sends `removeSubIssue` or `reprioritizeSubIssue`.
- A child with its own sub-issues expands in place, so you can walk the tree without leaving the page.
- The header shows a count such as "3/5 completed".

Every change shows at once and is sent to GitHub in the background. If GitHub refuses it, Gitsu puts the list back and says what failed.

From the child's side, the detail view shows **Sub-issue of** with the parent and its progress, and **Add parent** searches issues or accepts a pasted issue URL. If the issue already has a parent, Gitsu asks before moving it and names the parent that will lose it. Only after you confirm does it send `replaceParent: true`, so an ordinary link never takes a child from another epic without asking.

In lists and filters:

- Rows show sub-issue progress, such as "2 of 5 sub-issues done".
- The filter menu has **Has parent issue** and **Has sub-issue** toggles.
- The filter box accepts `parent-issue:octocat/game#4`, and `no:parent-issue` hides sub-issues from any view.

Where Gitsu stops today: it draws no hierarchy on a timeline, because it has no timeline view, and it has no project workflow settings, so **Auto-add sub-issues to project** is switched on from GitHub. The [roadmap view guide](/guides/github-projects-roadmap-view) covers the timeline gap. The [filter syntax guide](/guides/github-projects-filter-syntax) lists the other qualifiers that combine with `parent-issue:`, and the [getting-started guide](/docs/getting-started) connects your first project.

## Frequently asked questions

### How many sub-issues can a GitHub issue have?

Up to 100 sub-issues per parent issue, and up to eight levels of nesting.

### Can a sub-issue be in a different repository from its parent?

Yes. When adding an existing issue as a sub-issue, you can switch the repository in the picker and choose an issue from another repository.

### Can an issue have two parents?

No. An issue has at most one parent. The API's addSubIssue refuses an issue that already has a parent unless you pass replaceParent: true, which moves it.

### How do I show sub-issue progress in GitHub Projects?

In a table view, click + in the last field header and, under Hidden fields, click Sub-issue progress. The field shows how many of an item's sub-issues are complete.

### How do I hide sub-issues in a GitHub Projects view?

GitHub's docs do not describe a dedicated setting. The documented no:FIELD filter applied to the Parent issue field, no:parent-issue, keeps only items without a parent; test it on your project before saving the view.
