Skip to main content

github-merge-502-already-merged

`gh pr merge` 가 502/504 를 내도 머지는 이미 됐을 수 있다 — GitHub 는 머지를 수행한 뒤 PR 레코드 갱신에서 죽는다. 그러면 스쿼시 커밋은 main 에 있는데 PR 은 `state=open, merged=false` 로 남고, 브랜치도 안 지워진다. 재시도하기 전에 `git log origin/main` 을 먼저 봐라. 트리거: gh pr merge 502/Bad Gateway, "머지 실패"인데 CI 는 green, mergeStateStatus 가 갑자기 BEHIND, PR 이 열려 있는데 커밋이 main 에 있음.

Source facts

Repository
blas1n/claude-skills
Last source activity
August 12, 2026 at 03:45
Detected SKILL.md language
Korean
Stars
2
Forks
0

Install options

The review-first prompt is selected by default. You can switch to a direct command or download a local copy.

Review the source files

Read SKILL.md and any companion files shown by SkillsMP before deciding whether to install.

Showing SKILL.md

SKILL.md
Source instructions · Read-only preview
name
github-merge-502-already-merged
description
`gh pr merge` 가 502/504 를 내도 머지는 이미 됐을 수 있다 — GitHub 는 머지를 수행한 뒤 PR 레코드 갱신에서 죽는다. 그러면 스쿼시 커밋은 main 에 있는데 PR 은 `state=open, merged=false` 로 남고, 브랜치도 안 지워진다. 재시도하기 전에 `git log origin/main` 을 먼저 봐라. 트리거: gh pr merge 502/Bad Gateway, "머지 실패"인데 CI 는 green, mergeStateStatus 가 갑자기 BEHIND, PR 이 열려 있는데 커밋이 main 에 있음.
# `gh pr merge` 의 502 는 "머지 안 됐다"가 아니다 ## Problem ``` $ gh pr merge 736 --squash --delete-branch non-200 OK status code: 502 Bad Gateway ... <center>nginx</center> ``` 반사적으로 재시도하거나 "머지 실패"로 보고하게 된다. **둘 다 틀릴 수 있다.** - **증상**: 머지 명령이 502. 이어서 `gh pr view` 를 보면 `state: OPEN`, `mergedAt: null`, `mergeStateStatus: BEHIND` — 전부 "안 됐다"로 읽힌다. 리모트 브랜치도 그대로 있다. - **실제**: `git fetch && git log origin/main` 을 보면 **스쿼시 커밋이 이미 올라가 있다.** - **근본 원인**: 머지는 두 단계다 — ①ref 를 전진시킨다 ②PR 레코드를 merged 로 표시하고 브랜치를 지운다. 502 는 ① 이후 ② 에서 났고, GitHub 은 그것을 **되감지 않는다.** 스쿼시 머지는 커밋 SHA 가 브랜치 tip 과 달라서 GitHub 의 자동 감지도 안 걸린다. - **왜 위험한가**: 재시도하면 이미 반영된 변경을 다시 머지하려 들고(빈 머지 또는 충돌), "머지 실패"로 보고하면 **이미 배포 파이프라인이 물어간 변경**을 없는 것으로 취급하게 된다. ## Solution 502/504 를 받으면 **재시도 금지, 먼저 사실을 확인**한다: ```bash git fetch -q origin git log --oneline -3 origin/main # 내 PR 번호의 스쿼시 커밋이 있는가? # 있다면 — 내용까지 동일성 확인 (부분 반영이 아님을 증명) git diff --stat origin/main <my-branch> # 비어 있어야 한다 # 동일하면 머지는 끝난 것이다. PR 레코드만 손으로 정리한다 gh pr close <N> --comment "머지 API 502; 스쿼시 커밋은 main 에 반영됨(<sha>). 레코드만 수동 정리." git push origin --delete <my-branch> ``` ⚠️ `gh pr close --delete-branch` 는 다른 워크트리가 그 브랜치를 쓰고 있으면 `fatal: 'main' is already used by worktree at ...` 로 로컬 삭제에서 죽는다. 리모트 삭제는 `git push origin --delete` 로 따로 한다. 배포 확인도 잊지 마라 — 머지가 됐으므로 **autodeploy 폴러는 이미 물어간다**: ```bash curl -s https://<api>/api/health # git_sha 가 새 커밋인지 ``` ## Key Insights - **API 에러는 "요청이 실패했다"이지 "아무 일도 안 일어났다"가 아니다.** 쓰기 API 는 부분적으로 성공할 수 있고, 502 는 게이트웨이 계층이라 백엔드가 어디까지 갔는지 말해주지 않는다. - **원본(ref)이 메타데이터(PR 레코드)보다 진실이다.** GitHub UI/`gh pr view` 는 PR 레코드를 보여주는데, 실제로 배포를 결정하는 것은 `origin/main` 의 ref 다. - `mergeStateStatus: BEHIND` 같은 부수 신호가 오해를 강화한다 — 그건 이미 전진한 main 기준으로 다시 계산된 값이다. - 다음에 먼저 확인할 것: **`git log origin/main`.** PR 상태 API 를 다시 부르지 마라. ## Red Flags - 머지 명령이 5xx/timeout 인데 CI 는 전부 green 이었다 - PR 은 열려 있는데 `git log origin/main` 에 그 PR 번호의 커밋이 있다 - 머지 직후 `mergeStateStatus` 가 `BEHIND` 로 바뀌었다 - 재시도하려는 충동 — 그 전에 ref 를 봐라 ## 같은 착시, 다른 원인 — `--delete-branch` 의 로컬 정리 단계 (2026-08-12, PR #742) ``` $ gh pr merge 742 --squash --delete-branch failed to run git: fatal: 'main' is already used by worktree at '/…/bsvibe-app/main' ``` 머지 실패로 읽힌다. **머지는 됐다** (`gh pr view 742 → state=MERGED`). `--delete-branch` 는 원격 머지가 끝난 **뒤** 로컬 정리를 한다 — 로컬 브랜치를 지우려면 먼저 다른 브랜치로 옮겨야 하므로 `git checkout main` 을 시도한다. bare + worktree 레이아웃(`.bare` / `main` / `wt/*`)에서는 `main` 이 이미 다른 worktree 에 체크아웃돼 있어 그 checkout 이 거부되고, gh 가 그 exit code 를 그대로 뱉는다. 즉 **머지 명령의 비-0 종료가 머지 실패를 뜻하지 않는다** — 502 든 로컬 git 이든 같다. 확인 순서는 동일하다: 재시도 전에 `gh pr view <N> --json state,mergeCommit` 과 `git log origin/main` 을 먼저 본다. 정리는 손으로: ```bash git -C <main-worktree> fetch -q origin && git merge --ff-only origin/main git worktree remove wt/<name> && git branch -D <name> ```
View on GitHub