atlassian-cli is an independent, community open-source project, not affiliated with, endorsed by, or sponsored by Atlassian, and is not Atlassian's official CLI (acli). Product names are used only to identify compatibility.
What a Jira issue key branch looks like
A Jira issue key branch is a Git branch whose name embeds the issue key, for example feature/DEV-482-add-oauth-login. The uppercase key (DEV-482) is the part that matters: when your repository is connected to Jira, Jira scans branch names, commit messages, and pull requests for that pattern and links every match to the issue's development panel. You get end-to-end traceability from a card on the board to the exact lines that closed it, without anyone pasting links by hand.
The convention most teams settle on has three parts:
| Part | Example | Purpose |
|---|---|---|
| Type prefix | feature/ |
Groups and sorts branches (feature, bugfix, hotfix, chore) |
| Issue key | DEV-482 |
The token Jira detects; must stay uppercase |
| Slug | add-oauth-login |
Lowercase summary so humans can read the branch list |
The mechanical work is turning "DEV-482" plus that issue's summary into a valid, consistent branch name every single time. That is exactly what a one-line lookup with atlassian-cli removes. Instead of opening the browser, copying the summary, lowercasing it, and replacing spaces, you pass the key and the tool does the rest.
Where the key belongs, and why
People often ask whether the key has to be in the branch name or the commit message. The short answer: Jira reads it from all three surfaces, and each unlocks a slightly different view.
| Where the key lives | Example | What it enables in Jira |
|---|---|---|
| Branch name | feature/DEV-482-add-oauth-login |
Branch shows in the issue's development panel; source for hooks below |
| Commit message | DEV-482 Add OAuth login flow |
Commit is listed on the issue; enables Smart Commit actions |
| Pull request | DEV-482: Add OAuth login |
PR and its review state appear on the issue |
Putting the key in the branch name is the highest-leverage choice, because it is the one place you can derive everything else from. Once the branch carries the key, a Git hook can copy it onto every commit for you, so you never type DEV-482 again after the first checkout. That is the pattern the rest of this post builds.
Generate a branch name from an issue key
Start with a shell function that takes an issue key, looks up the summary, slugifies it, and creates the branch. Drop this in your ~/.zshrc or ~/.bashrc:
# jira-branch DEV-482 -> feature/DEV-482-add-oauth-login
# jira-branch DEV-482 bugfix -> bugfix/DEV-482-add-oauth-login
jira-branch() {
local key="$1"
local type="${2:-feature}"
# Pull the summary straight from Jira
local summary
summary=$(atlassian-cli jira issue get "$key" --format json | jq -r '.fields.summary')
# Lowercase, replace non-alphanumerics with hyphens, trim, cap length
local slug
slug=$(printf '%s' "$summary" \
| tr '[:upper:]' '[:lower:]' \
| sed -E 's/[^a-z0-9]+/-/g; s/^-+|-+$//g' \
| cut -c1-40 | sed -E 's/-+$//')
git checkout -b "${type}/${key}-${slug}"
}
Now creating a correctly named branch is a single command. The issue key format is always consistent, the slug always matches the real summary, and typos in branch names disappear:
# Issue DEV-482 summary: "Add OAuth login flow"
$ jira-branch DEV-482
Switched to a new branch 'feature/DEV-482-add-oauth-login-flow'
Because the lookup uses the standard --format json output documented in the command reference, you can shape the branch however your team prefers, truncating the slug, swapping the separator, or prefixing with a username. The one rule that must survive is keeping the key uppercase so Jira detects it.
Create the branch and move the card in one step
The moment you branch is usually the moment the work becomes "In Progress". Fold the transition into the same function so Git and the board never drift apart:
jira-start() {
jira-branch "$1" "${2:-feature}"
# Advance the issue on the board (transition name must exist in the workflow)
atlassian-cli jira issue transition "$1" --transition "In Progress"
}
One command (jira-start DEV-482) now creates the branch and updates Jira. If the transition name differs in your workflow, list the valid targets first with atlassian-cli jira issue get DEV-482 and adjust the string.
Auto-tag every commit with a Git hook
Getting commits to appear on the Jira issue means each commit message must contain the key. Typing it manually every time is exactly the kind of chore people forget under pressure. A prepare-commit-msg hook reads the key out of the branch name and prepends it for you.
Create .git/hooks/prepare-commit-msg in the repository and make it executable:
#!/usr/bin/env bash
# .git/hooks/prepare-commit-msg
# Prepend the Jira issue key from the branch name to every commit message.
set -euo pipefail
msg_file="$1"
branch=$(git rev-parse --abbrev-ref HEAD)
# Match keys like DEV-482, ABC-1, PLATFORM-99
key=$(printf '%s' "$branch" | grep -oE '[A-Z][A-Z0-9]+-[0-9]+' | head -1 || true)
# Only add it if we found a key and it is not already in the message
if [ -n "$key" ] && ! grep -q "$key" "$msg_file"; then
printf '%s %s' "$key" "$(cat "$msg_file")" > "$msg_file.tmp"
mv "$msg_file.tmp" "$msg_file"
fi
From now on, committing on feature/DEV-482-add-oauth-login produces messages like DEV-482 Fix token refresh race without you touching the key. Every commit lands on the issue, and Smart Commit actions (for example a trailing #time 2h or #comment) work because the key is present.
Team-wide rollout: .git/hooks is local to each clone and not committed. To share the hook, keep it in a tracked folder such as .githooks/ and point every clone at it once with git config core.hooksPath .githooks. New teammates get the behavior after a single config command.
If a branch has no key (say you are on main or a spike branch), the hook matches nothing and leaves the message untouched, so it is safe to enable everywhere.
Look up the issue from any branch
The relationship works both ways. Once branches carry keys, you can jump from wherever you are in Git back to the issue without hunting for the ticket. Extract the key from the current branch and hand it to jira issue get:
# Show the issue behind the branch you are standing on
jira-here() {
local key
key=$(git rev-parse --abbrev-ref HEAD | grep -oE '[A-Z][A-Z0-9]+-[0-9]+' | head -1)
[ -z "$key" ] && { echo "No Jira key in branch name"; return 1; }
atlassian-cli jira issue get "$key"
}
Run jira-here and you get the summary, status, and assignee for the current branch's issue in the terminal. This is handy in code review or when you return to a branch after a week and cannot remember what it was for.
The same extraction powers a lightweight guard. A pre-push hook can confirm the key still resolves to a real issue before you push, catching typo'd keys and branches for deleted tickets:
#!/usr/bin/env bash
# .git/hooks/pre-push -- warn if the branch key is not a real Jira issue
branch=$(git rev-parse --abbrev-ref HEAD)
key=$(printf '%s' "$branch" | grep -oE '[A-Z][A-Z0-9]+-[0-9]+' | head -1 || true)
if [ -n "$key" ]; then
if ! atlassian-cli jira issue get "$key" --format json >/dev/null 2>&1; then
echo "Warning: $key did not resolve to a Jira issue"
fi
fi
exit 0
The check is advisory (it exits 0 so it never blocks a push), but it surfaces mistakes early. If you want to script richer checks against Jira, the raw JSON output is the same shape used throughout the Jira API from the command line guide, so the two workflows compose cleanly.
Try atlassian-cli
One free, MIT-licensed Rust binary for Jira, Confluence, Bitbucket, and JSM. No runtime, no subscription.
Install atlassian-cliHow atlassian-cli differs from acli
atlassian-cli is an independent, community open-source project. It is not Atlassian's official CLI (acli) and is not affiliated with, endorsed by, or sponsored by Atlassian. Use the official acli if you want first-party vendor support; use atlassian-cli if you want a single free Rust binary that spans Jira, Confluence, Bitbucket, and Jira Service Management with consistent --format json output that slots straight into shell functions and Git hooks like the ones above.
For this workflow the practical draw is the uniform JSON across products: the same --format json that feeds jq -r '.fields.summary' here also drives pull request and review automation. If you continue the branch into a PR, the Bitbucket PR review automation guide picks up where this one leaves off, using the same key to tie the review back to the issue.
FAQ
How do I put the Jira issue key in my Git branch name automatically?
Write a small shell function that reads the issue key, fetches the summary with atlassian-cli jira issue get KEY --format json, slugifies the summary text, and runs git checkout -b type/KEY-slug. You pass the key once (jira-branch DEV-482) and the branch name is generated for you, so the issue key format is always consistent.
Does the Jira issue key have to be in the branch name or the commit message?
Jira detects the key in the branch name, the commit message, and the pull request, and each links the work back to the issue's development panel. Putting the key in the branch name is the most convenient because a prepare-commit-msg hook can then copy it into every commit automatically, so you only type it once.
How do I make Git commits show up in the Jira issue's development panel?
The commit message must contain the issue key, for example DEV-482, and the repository must be connected to Jira (Bitbucket, GitHub, or GitLab integration). A prepare-commit-msg hook that extracts the key from the branch name and prepends it to the message guarantees every commit carries the key, so it appears in the linked issue.
Can I create a branch and move the Jira issue to In Progress in one command?
Yes. Extend the branch helper so that after git checkout -b it runs atlassian-cli jira issue transition KEY --transition "In Progress". One command creates the correctly named branch and advances the issue on the board, keeping Git and Jira in sync without opening the browser.
What format should a Jira branch name follow?
A common pattern is type/KEY-short-slug, for example feature/DEV-482-add-oauth-login. The type prefix (feature, bugfix, hotfix) sorts branches, the uppercase issue key lets Jira detect it, and the lowercase slug from the issue summary keeps the branch human-readable. Keep the slug short and use only lowercase letters, digits, and hyphens.