Skip to content
Back to skills

Jira Local Merge

ASecurity

Locally merge a Jira task branch into the base branch without a remote or PR. Triggers: jira-task merge, local merge; 로컬 병합, 원격 없이 병합.

  • 9 stars
  • 0 votes
  • 0 copies
  • 0 views
  • Added September 29, 2026
toolspythonbashnodegit

Works with

  • claude code
  • cli

Security analysis

A100/100

Scanned September 29, 2026

npx -y skills add mzd-hseokkim/jira-claude-code-integration --skill jira-local-merge --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Jira Local Merge?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Jira Local Merge
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/mzd-hseokkim-jira-local-merge/badge)](https://www.skillsdirectory.com/skills/mzd-hseokkim-jira-local-merge)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: jira-local-merge
description: "Locally merge a Jira task branch into the base branch without a remote or PR. Triggers: jira-task merge, local merge; 로컬 병합, 원격 없이 병합."
user-invocable: false
argument-hint: "<TASK-ID>"
allowed-tools:
  - Read
  - Write
  - Bash
  - Glob
---

# jira-local-merge: Local Branch Merge

**Language Rule**: 프로젝트 CLAUDE.md의 Conventions 섹션 참고 (한국어 출력, Jira 코멘트 제목은 영어).

remote origin 없이 feature 브랜치를 base 브랜치로 로컬 병합하고,
Jira 상태 전환 및 worktree 정리까지 일괄 처리한다.

## Prerequisites
- feature 브랜치에 커밋이 존재
- Jira 자격증명 설정됨 (`skills/_shared/jira-cli.md`)

## Workflow

### Jira 호출

Jira 호출은 `python3 "<scripts>/jira-cli.py" …` (규약: `skills/_shared/jira-cli.md`). 호출 prompt가 `<scripts>/` 절대 경로를 줬으면 그대로 쓰고, 없으면 `skills/_shared/script-lookup.md`로 `SCRIPT_NAME="jira-cli.py"` 1회 해석. 이슈 조회가 필요하면 `get <TASK-ID>` (압축 JSON의 `summary`/`status`/`issuetype` 사용).

### Step 1: Load Context

`.jira-context.json`을 읽어 태스크 컨텍스트 로드:
- `taskId`, `branch`, `baseBranch`, `worktreePath`, `repoRoot`

인자로 TASK-ID가 전달된 경우 해당 값 우선 사용.

`repoRoot`가 없으면 `git worktree list`의 첫 번째 줄로 폴백:
```bash
# git worktree list 첫 번째 줄이 항상 메인 레포 경로
git worktree list | head -1 | awk '{print $1}'
```
`git worktree list --porcelain | awk 'NR==2{print $2; exit}'`도 동일 결과.
`git rev-parse --show-toplevel`은 워크트리 안에서는 워크트리 경로를 반환하므로 사용하지 않음.

`baseBranch`가 없으면 `repoRoot`에서 감지:
```bash
git -C "<repoRoot>" rev-parse --verify develop 2>/dev/null
git -C "<repoRoot>" rev-parse --verify main 2>/dev/null
git -C "<repoRoot>" rev-parse --verify master 2>/dev/null
```

### Step 2: Pre-flight Checks & Auto-commit

```bash
# 1. feature 브랜치 존재 확인
git branch --list "feature/<TASK-ID>"

# 2. 워크트리 내 미커밋 변경사항 확인
git -C "<worktreePath>" status --porcelain
```

미커밋 변경사항이 있으면 **사용자에게 묻지 않고 스마트 커밋**한다. merge 요청 자체가 "커밋도 끝났길 바란다"는 의도이므로 흐름을 끊지 않는다.

- 쓸데없는 파일(로그·임시·OS 아티팩트)은 스테이징에서 제외. `.gitignore`가 이미 거르는 항목(`.jira-context.json`, `TASK-README.md` 등)은 자연히 빠진다.
- 의미 있는 변경(소스·문서·설정)만 스테이징 후 이슈 summary 기반 메시지로 커밋.

```bash
cd "<worktreePath>"
# junk 제외하고 의미 있는 변경만 스테이징
git add -A -- . \
  ':(exclude,glob)**/*.log' ':(exclude,glob)**/*.tmp' ':(exclude,glob)**/*.swp' \
  ':(exclude)nul' ':(exclude)**/.DS_Store' ':(exclude)**/Thumbs.db'
# 스테이징된 변경이 있을 때만 커밋
if ! git diff --cached --quiet; then
  git commit -m "feat(<TASK-ID>): <issue summary>"
fi
```

스테이징할 의미 있는 변경이 없으면 커밋을 생략하고 다음 단계로 진행한다.

### Step 3: Merge Strategy (고정: --no-ff)

병합 전략은 **항상 `--no-ff`** (merge commit 생성, feature 브랜치 히스토리 보존)로 고정한다. 사용자에게 묻지 않는다 — merge를 요청했다는 것은 전략이 이미 정해져 있다는 의미다.

### Step 4: Perform Merge

**`.jira-context.json`의 `repoRoot`를 사용**한다. `git rev-parse --show-toplevel`은 워크트리 안에서 실행하면 워크트리 경로를 반환하므로 사용하지 않음.

```bash
git -C "<repoRoot>" checkout <baseBranch>
git -C "<repoRoot>" merge --no-ff feature/<TASK-ID> -m "Merge feature/<TASK-ID>: <issue summary>"
```

merge 충돌 발생 시 사용자에게 알리고 중단. 충돌 해결 후 재실행 안내.

### Step 5: Post Completion Report to Jira

병합 결과를 scratchpad md 파일로 쓰고 `python3 "<scripts>/jira-cli.py" comment <TASK-ID> @<파일>`로 게시:

```
## Task Merged Locally: <TASK-ID>

**브랜치**: feature/<TASK-ID> → <baseBranch>
**전략**: --no-ff
**커밋 수**: <count>개
**변경 파일**: <count>개 (+<추가> -<삭제>)

### Changes
<git log --oneline 요약>
```

### Step 6: Transition Issue

`python3 "<scripts>/jira-cli.py" transitions <TASK-ID>`로 전환 목록 조회 후 `python3 "<scripts>/jira-cli.py" transition <TASK-ID> "<id|상태명>"`으로 상태 전환:
- "In Review" 우선 시도 (PR 생성 단계가 남아있으므로 Done이 아님)
- "In Review"가 없으면 가능한 전환 목록을 사용자에게 안내하고 선택 요청
- Done으로 전환하지 않는다 (PR 생성 후 `jira-task done`에서 처리)
- 코멘트는 `comment` 서브커맨드로 별도 (전이에 섞지 않음)

### Step 6.5: Verify Transition (SSOT)

`Read skills/_shared/transition-verify.md` — `transition` 출력의 `status`가 SSOT이며 별도 재조회는 하지 않는다. `<final-jira-status>` 결정 규칙, 실패 정책을 그대로 따르고 결과 status를 Step 8의 `<final-jira-status>` 인자로 전달.

### Step 7: Cleanup Instructions

현재 Claude Code가 워크트리 디렉토리에서 실행 중이므로 워크트리를 직접 삭제할 수 없다.
병합이 완료된 후 사용자에게 아래 안내를 출력한다:

```
⚠️  워크트리 정리가 필요합니다.
    이 세션을 닫고 메인 레포 세션에서 아래를 실행하세요:

    /jira-task clean <TASK-ID>

    ⚠️  `git worktree remove`를 직접 실행하지 마세요 — worktree 안의 junction/symlink
       (예: node_modules → 메인 레포)를 따라 들어가 메인 레포 소스를 지웁니다.
       clean 스킬은 링크를 먼저 끊고 검증한 뒤에만 git을 호출합니다.
    ⚠️  clean은 feature 브랜치도 삭제합니다. PR 워크플로라면 PR 머지 후에 실행하세요.
```

실제 명령 실행은 하지 않는다.

### Step 8: Update Context & Completion Summary

워크트리의 `.jira-context.json`과 `<repoRoot>/.jira-context.json` 양쪽을 공용 스크립트로 갱신한다. 스크립트 경로 결정은 `Read skills/_shared/script-lookup.md` 후 lookup 블록 실행:

```bash
SCRIPT_NAME="jira-context-update.py" OUT_VAR="JIRA_CTX_UPDATE_PY"
# Read skills/_shared/script-lookup.md and execute its lookup block here
python3 "$JIRA_CTX_UPDATE_PY" <TASK-ID> merge "<final-jira-status>" \
    "<worktree>/.jira-context.json" \
    "<repoRoot>/.jira-context.json"
```

- `<final-jira-status>`: **Step 6.5에서 `transition` 출력의 `status`로 확보한 Jira 실제 status명** (예: `"In Review"`, `"검토중"`). transition 시도값을 그대로 쓰지 말 것.

스크립트는 다음을 일괄 처리한다:
- `completedSteps`에 `"merge"` 추가 (중복 방지)
- `status`를 `<final-jira-status>`로 set
- `mergedAt`에 현재 UTC ISO 8601 (Z suffix) 기록 — TZ-naive timestamp는 dashboard reader가 stale로 처리하므로 Z 접미사 필수
- `cachedIssue.status` / `cachedIssue.fetchedAt`도 함께 갱신 (cachedIssue가 있을 때만)
- aggregate vs worktree 형식 자동 감지 (aggregate는 `tasks[]`에서 해당 `taskId` 항목만 갱신)

아래 형식으로 완료 요약 출력:

```
---
✅ **Local Merge Complete** — <TASK-ID>

- 병합: feature/<TASK-ID> → <baseBranch> (--no-ff)
- Jira 상태: In Review
- Worktree 정리: 세션 종료 후 수동 실행 필요 (위 안내 참고)
- feature 브랜치(feature/<TASK-ID>)는 PR 생성을 위해 보존됨
- 완료 리포트 Jira에 게시됨

**Progress**: init → start → approach → impl → test → review → **merge ✓** → pr → done

**Next**: 세션 종료 후 메인 레포에서 `/jira-task pr <TASK-ID>` — PR을 생성합니다
---
```

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.