GitHub Stacked PRs
(github.github.com/gh-stack)- 대규모 코드 변경을 작고 검토 가능한 PR 단위로 분할해 순차적으로 관리할 수 있게 하는 GitHub의 새로운 기능
- 각 PR은 독립적으로 리뷰되며, 전체 스택은 한 번의 클릭으로 병합할 수 있음
- GitHub UI와
gh stackCLI를 통해 스택 생성, 탐색, 리베이스, 병합을 지원하고, 스택 맵으로 계층 구조를 시각화함 - AI 코딩 에이전트 통합을 통해 대규모 diff를 자동으로 스택 단위로 나누거나 스택 기반 개발을 수행할 수 있음
- 대형 PR의 복잡성과 충돌 위험을 줄이고, 리뷰 효율성과 팀 개발 속도를 높이는 데 목적이 있음
주요 기능
-
스택형 PR 관리
- 여러 PR을 순서 있는 스택(stack) 형태로 구성해, 각 PR이 바로 아래 PR의 브랜치를 기반으로 함
- 최종적으로 메인 브랜치에 도달하는 체인 구조를 형성
- GitHub는 스택 전체를 인식해 스택 맵(stack map) 을 UI에 표시, 리뷰어가 각 계층을 쉽게 탐색 가능
- 브랜치 보호 규칙은 최종 대상 브랜치에 적용되며, CI 테스트는 스택 내 모든 PR에 대해 실행됨
-
간소화된 스택 관리
- GitHub UI에서 스택 내 PR 간 이동, 각 계층의 상태 확인, 전체 스택에 대한 연쇄 리베이스(cascading rebase) 실행 가능
- 한 번의 클릭으로 스택 전체를 병합하거나 일부만 병합 가능
- 병합 후 남은 PR들은 자동으로 리베이스되어, 가장 아래의 미병합 PR이 기본 브랜치를 대상으로 조정됨
-
강력한 CLI 지원
gh stackCLI를 통해 스택 생성, 리베이스, 브랜치 푸시, PR 생성, 계층 간 이동을 터미널에서 수행 가능- CLI 명령 예시
gh extension install github/gh-stack: 확장 설치gh stack alias: 단축 명령어 설정gs init <branch>: 첫 브랜치 생성gs add <branch>: 새 계층 추가gs push: 모든 브랜치 푸시gs submit: 스택 전체 PR 생성
-
AI Agent 통합
npx skills add github/gh-stack명령으로 AI 코딩 에이전트가 스택 작업을 수행하도록 학습 가능- 대규모 diff를 자동으로 스택 단위로 분리하거나, 처음부터 스택 기반 개발 진행 가능
스택형 PR의 필요성
- 대형 PR은 검토 난이도 증가, 병합 지연, 충돌 위험을 초래
- 리뷰어가 문맥을 잃고 피드백 품질이 저하되며, 팀 전체 속도가 느려짐
- Stacked PRs는 이를 해결하기 위해 작고 집중된 PR 체인으로 분할
- 각 PR은 독립적으로 검토 가능하며, 전체 변경은 순차적으로 누적됨
시작하기
- 빠르게 사용하려면 Quick Start 가이드 또는 Overview 문서 참고
댓글과 토론
Stacked PRs is currently in private preview. This feature will not work unless enabled for your repository.
Hacker News 의견들
-
내가 필요한 건 "stacked PR"가 아니라 단일 커밋 관리용 UI임
- 일부 커밋만 독립적으로 머지하거나, 특정 커밋을 리뷰 완료로 표시하고 싶음
- 커밋 단위로 interactive rebase/squash/edit를 하고 싶은데 GitHub UI에서는 불가능함
- 커밋 메시지나 특정 커밋에 코멘트를 달 수 있는 기능, 그리고 diff of diff로 강제 푸시 간의 변화를 시각화하는 기능이 필요함
Git은 이미 커밋 개념을 가지고 있는데, 왜 그 위에 또 “stacked PR”이라는 추상화를 얹는지 모르겠음 - Phabricator가 만든 stacked diff 워크플로우를 GitHub에 가져온 개념임
아직 머지되지 않은 작업 위에서 새 작업을 진행하기 쉽게 하고, 리뷰어가 큰 변경을 작은 단위로 독립 리뷰할 수 있게 함
대규모 monorepo나 기업 환경에서 특히 유용했음 - 하지만 나는 git 히스토리를 계속 재작성하는 게 위험하다고 느낌
squash, rebase, force push를 반복하는 건 발등에 총을 겨누는 일 같음
git merge --no-ff,git log --first-parent,git bisect --first-parent로도 충분히 같은 효과를 얻을 수 있음 - Meta에서 썼던 SuperSmartLog(SSL) 이 가장 훌륭한 구현이었음
interactive smartlog 문서에 공개되어 있고 VSCode 확장도 있음
의외로 널리 쓰이지 못한 게 아쉬움 - 내가 선호하는 워크플로우는 PR/MR을 “원자적 변경” 으로 보는 것임
커밋은 그 PR을 완성하기 위한 진화 과정으로 사용함- PR이 너무 크면 커밋으로 나눔
- PR의 발전 과정을 커밋에 기록함 (“foo를 bar로 바꿈” 같은 이유 포함)
- 네가 말한 건 사실상 Gerrit임
-
Phabricator와 Mercurial을 쓰다가 GitHub로 돌아오니 석기시대로 돌아간 기분임
stacked diff 흐름을 다시 구현해주는 jujutsu나 이번 기능이 반가움
monorepo뿐 아니라 장기 기능 개발에서도 리뷰를 작고 빠르게 할 수 있게 해줌- Git이 DVCS 전쟁에서 이긴 게 정말 다행임
Mercurial은 늘 “git보다 빠르다”고 했지만 실제로는 느리거나 깨졌었음
Git은 못생겼지만 빠르고 신뢰성 있음 - 나는 여전히 GitHub 리뷰가 싫어서 Gerrit을 씀
큰 변경(예: vendor 종속성 업데이트)을 리뷰할 때 GitHub의 파일 리뷰 경험이 별로임 - Phabricator의 리뷰 UI가 너무 그리움
- Git이 DVCS 전쟁에서 이긴 게 정말 다행임
-
드디어 나왔음!
GitHub의 “PR=브랜치” 모델은 이해가 안 됐음
Phabricator/Gerrit식 stacked commit이 내 사고방식에 더 맞음
이제 CLI를 설치해야겠음- GH CLI 의존성이 아쉽지만, GA 시점에는 UI 지원이 생기길 바람
- 내 머릿속 모델로는 브랜치와 stacked PR의 차이를 잘 모르겠음
브랜치는 단지 커밋에 깃발을 꽂는 것일 뿐이고, 여러 지점을 남기는 건 이전 부분을 독립적으로 머지할 수 있을 때만 의미가 있음
-
현재 Squash & Merge UX 문제를 해결했는지 궁금함
나는 수동으로 main <- PR A <- PR B <- PR C 식으로 쌓는데,
PR A가 먼저 머지되면 PR B는 충돌 지옥이 됨
GitHub UI가 자동으로 타깃 브랜치를 main으로 바꾸면서 이상한 충돌이 생김
그냥 “그냥 잘 작동하는” 도구가 필요함- 충돌은 PR A가 squash 머지되었기 때문일 가능성이 높음
gh stack sync가rebase --onto로 해결해주길 바람 - 실제로는 CLI와 서버에서
git rebase --onto로 처리함
예: PR1(main<-A,B), PR2(main<-A,B,C,D), PR3(main<-A,B,C,D,E,F)
PR1,2가 squash 머지되면 main은 S1(A+B), S2(C+D)
이후git rebase --onto S2 D branch3로 충돌 없이 정리됨 - 내 워크플로우에서는 A가 머지되면 B도 이미 머지된 상태여야 함
git rebase --update-refs --onto origin/main A C로 해결 가능함
GH CLI가 이 과정을 자동화해줌 - 이 문제는 git의 논리적 한계이지 버그는 아님
- 나도 이게 짜증나고 직관적이지 않음에 동의함
하지만 해결책은 결국 수동 rebase로 커밋 정리하는 것뿐임
- 충돌은 PR A가 squash 머지되었기 때문일 가능성이 높음
-
혼자 개발할 땐 stacked PR이 거의 필요 없지만, 작은 단위로 나누는 습관은 여전히 중요함
AI 도구(예: Claude Code)가 한 번에 큰 diff를 만들기 때문에,
에이전트가 스스로 작업을 논리적 단위로 나누는 기능이 생기면 흥미로울 것 같음- 이미 PR은 여러 커밋으로 구성될 수 있으니, 에이전트가 그걸 잘 탐색하지 못한다면 stacked PR도 마찬가지일 것임
- 나는 Claude와 jj를 함께 써서, 작업 스택을 trunk 위에 리뷰 친화적으로 재구성하게 함
- 작은 브랜치를 서로 의존하게 만들면, 이전 브랜치가 업데이트될 때 동기화 지옥이 생김
- 관련된 에이전트 통합 가이드는 웹페이지에서 확인 가능함
-
git-spice도 확인해볼 만함
GitLab 등과 호환되고, 나는 기존 git 명령 대신 전부 git-spice를 씀 -
GitHub가 드디어 UI에 stack 기능을 넣은 게 멋짐
GitLab의glab stack과 유사함
다만 머지 과정이 약간 어색할 듯함 — 스택 아래쪽을 머지하면 나머지가 rebase되어 CI가 다시 돌게 됨
세 개의 패치 중 아래 두 개만 머지하고 싶을 때, 각각 테스트를 기다려야 함- 현재 설계상, 아래 두 PR의 CI가 통과하면 한 번에 머지 가능함
그 후 상단 스택이 rebase되며 CI가 다시 실행될 수 있음
문서에 이 부분을 명확히 추가할 예정임
- 현재 설계상, 아래 두 PR의 CI가 통과하면 한 번에 머지 가능함
-
나는 stacked PR의 필요성을 잘 모르겠음
git에서는 원래 패치 세트를 개별적으로 리뷰하고 적용할 수 있음
PR 모델이 오히려 이걸 하나의 덩어리로 묶어버림
stacked PR은 그 문제를 우회하려는 또 다른 추상화처럼 보임- 내가 일했던 팀은 PR 자체를 “적용 가능한 최소 단위”로 봄
내부 커밋은 개발 히스토리일 뿐, 머지 시에는 squash로 하나로 합침
이렇게 하면 개발 중에는 자유롭게 커밋을 쌓고, 머지 시에는 깔끔한 변경만 남김 - Phabricator에서는 커밋과 diff가 1:1이라 훨씬 자연스러웠음
GitHub의 구현은 약간 붙여넣은 기능처럼 느껴짐 - PR은 본래 원자적 변경 단위이고, stacked PR은 그 위에 새 PR을 기반으로 작업할 수 있게 해줌
즉, 리뷰 가능한 단위로 작업을 단계적으로 쌓는 구조임
- 내가 일했던 팀은 PR 자체를 “적용 가능한 최소 단위”로 봄
-
Graphite라는 스타트업이 이미 stacked PR에 집중하고 있음
나는 Graphite를 써왔고, GitHub가 비슷한 걸 구현한 게 반가움- 회사에서도 Graphite를 써서 만족하고 있음
-
나는 stacked PR을 좋아하지만, 이번 GitHub 구현은 이상한 방식으로 느껴짐
그냥 각 브랜치가 부모를 가리키게 하면 충분함
CLI보다는 UI 지원이 더 필요함- 하지만 부모 브랜치가 머지된 후 rebase가 고통스러움
CLI가 이 과정을 자동화해주면 좋을 듯함 - CLI는 선택 사항이고, UI에서도 stacked PR을 만들 수 있음
브랜치 체인을 두는 이유는 diff가 해당 브랜치의 변경만 보여주기 위해서임 - 사실 이건 원래 git에서도 가능했음
다만 UI와 시각화가 부족했을 뿐임 - 다음엔 UI 개선이 오길 기대함
- 하지만 부모 브랜치가 머지된 후 rebase가 고통스러움