Helper scripts for migrating issues between Jira and Linear. These tools use the Atlassian CLI (acli), Jira REST API, and Linear GraphQL API to manipulate issues during migration processes.
- Atlassian CLI (acli) must be installed and configured
- Run
acli jira auth loginto set up authentication
- Run
curlfor HTTP requestsjqfor JSON parsing- For scripts using Jira REST API, set these environment variables:
JIRA_HOST(e.g.,your-domain.atlassian.net)JIRA_USER_EMAILJIRA_API_TOKEN(get it from https://id.atlassian.com/manage-profile/security/api-tokens)
- For scripts using Linear API, set this environment variable:
LINEAR_API_KEY(get it from https://linear.app/settings/api)
Follow these steps to migrate issues from Jira to Linear and back:
Phase 1a: Prepare Jira for Migration
graph LR
Start([Start: Jira with Epics]) --> Step1[1. Label Bugs]
Step1 --> Step2[2. Add IssueTypeEpic labels]
Step2 --> Step3[3. Add parent labels]
Step3 --> Step4[4. Convert Epics to Tasks]
Step4 --> BrokenJira([Jira: Tasks<br/>⚠️ Broken hierarchy])
style Start fill:#e1f5ff,stroke:#0288d1
style BrokenJira fill:#ffe6e6,stroke:#d32f2f
Phase 1b: Import to Linear
graph LR
Step5[5. Linear Import] --> LinearDone([Linear: Tasks<br/>⚠️ Broken hierarchy])
style LinearDone fill:#ffe6e6,stroke:#d32f2f
style Step5 fill:#f5f5f5,stroke:#757575
Phase 2: Fix Linear Hierarchy
graph LR
Start2([Linear: Broken hierarchy]) --> Step6[6. Link parent/child]
Step6 --> End([Linear<br/>✓ Ready to use])
style Start2 fill:#ffe6e6,stroke:#d32f2f
style End fill:#e8f5e9,stroke:#388e3c
Phase 3: Restore Jira Hierarchy (Optional)
graph LR
Start3([Broken Jira]) --> Step7[7. Convert Tasks to Epics]
Step7 --> Step8[8. Re-link Epics & children]
Step8 --> End2([Jira with Epics<br/>✓ Restored])
style Start3 fill:#ffe6e6,stroke:#d32f2f
style End2 fill:#e8f5e9,stroke:#388e3c
-
Label Bug issues (optional but recommended):
./prepare-jira/label-bugs.sh <PROJECT-KEY> [--dry-run]
Adds "Bug" labels to Bug issue types to preserve type information.
-
Manually mark Epics you want to migrate: Add the label
IssueTypeEpicto all Epic issues you want to include in the migration.Example:
acli jira workitem edit --jql "project = <PROJECT-KEY> AND issuetype = Epic" --labels "IssueTypeEpic"
-
Add parent relationship labels:
./prepare-jira/add-parent-labels.sh <PROJECT-KEY> [--dry-run]
Adds
parentIs<EPIC-KEY>labels to child issues to preserve Epic relationships. -
Convert Epics to Tasks:
./prepare-jira/convert-epic-to-task.sh <PROJECT-KEY> [--dry-run]
Converts Epic issues to Task type (Linear doesn't support Epics).
-
Run Linear import: Use Linear's Jira import feature to migrate the issues.
- Link parent and child issues in Linear:
Links child issues to parent issues in Linear using the
./fix-linear/link-parent-and-child.sh <TEAM-KEY> [--dry-run]
parentIslabels.
-
Convert Tasks back to Epics:
./fix-jira/convert-task-to-epic.sh <PROJECT-KEY> [--dry-run]
Converts issues labeled with
IssueTypeEpicback to Epic type. -
Re-link Epics and children:
./fix-jira/link-children-to-epic.sh <PROJECT-KEY> [--dry-run]
Links child issues back to their parent Epics using the
parentIslabels.
Scripts for preparing Jira issues before migrating to Linear:
Purpose: Adds "Bug" labels to all Bug issue types that don't already have bug labels Motivation: Preserves issue type information through labels when migrating to Linear, where the original issue type metadata might not be preserved.
Usage:
./prepare-jira/label-bugs.sh <PROJECT-KEY> [--dry-run]Purpose: Adds parent relationship labels to child issues of Epics
Motivation: Linear doesn't have the same Epic/Story hierarchy as Jira. This script adds parentIs<EPIC-KEY> labels to all child issues, preserving the parent-child relationships for reference after migration.
Usage:
./prepare-jira/add-parent-labels.sh <PROJECT-KEY> [--dry-run]Purpose: Converts all Epic issues to Task issue type Motivation: Linear doesn't have Epic issue types. Converting Epics to Tasks before migration ensures they migrate as regular issues instead of being dropped or causing errors.
Usage:
./prepare-jira/convert-epic-to-task.sh <PROJECT-KEY> [--dry-run]Scripts for fixing Linear hierarchy after import:
Purpose: Links child issues to parent issues in Linear using the GraphQL API
Motivation: After importing issues into Linear, this script restores the parent-child relationships using the parentIs labels that were added in Jira. It creates sub-issue relationships in Linear.
Usage:
./fix-linear/link-parent-and-child.sh <TEAM-KEY> [--dry-run]Note: This script requires the LINEAR_API_KEY environment variable for Linear API authentication.
Scripts for restoring Jira hierarchy after Linear migration:
Purpose: Converts issues labeled with "IssueTypeEpic" back to Epic issue type Motivation: Recreates Epic hierarchy after migrating issues back from Linear. Issues that were originally Epics and were marked with "IssueTypeEpic" labels get converted back to proper Epic issue types.
Usage:
./fix-jira/convert-task-to-epic.sh <PROJECT-KEY> [--dry-run]Purpose: Links child issues back to their parent Epics using parentIs labels
Motivation: Restores the Epic/child relationships that were preserved via labels during the Linear migration. Uses Jira REST API to set parent links.
Usage:
./fix-jira/link-children-to-epic.sh <PROJECT-KEY> [--dry-run]Note: This script requires environment variables for Jira REST API authentication:
JIRA_HOST- Your Jira domain (e.g.,your-domain.atlassian.net)JIRA_USER_EMAIL- Your Jira user emailJIRA_API_TOKEN- Your Jira API token
<PROJECT-KEY>: Jira project key (e.g., "PAT", "PROJ")<TEAM-KEY>: Linear team key (e.g., "ENG", "PROD")--dry-run: Preview changes without executing them
All scripts use JQL (Jira Query Language) or GraphQL queries to select which issues to process. If the default selection doesn't match your needs, you can modify the queries directly in the script files:
- Jira scripts: Look for the
--jqlparameter in functions likeget_epics_in_project()orget_bug_issues() - Linear scripts: Look for the GraphQL
queryormutationdefinitions in functions likeget_parent_issues()orget_child_issues_by_label()
Common customizations:
- Change status filters (e.g., include/exclude "Done" issues)
- Add additional label filters
- Filter by assignee, reporter, or other fields
- Adjust date ranges
This project is licensed under the MIT License - see the LICENSE file for details.