You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
4번이 핵심이다. stable 범프를 승격 브랜치가 아니라 preview 위에서 만들면 main 고유 커밋이 사라지고, 조상 관계가 정의상 유지된다. 6번으로 dev가 preview를 흡수하므로 쌍둥이가 불필요해진다.
세 브랜치는 유지한다.publish.yml:256 이 브랜치와 태그 짝을 강제하므로(preview:preview, latest:main) preview 브랜치는 beta 발행에 반드시 필요하다.
삭제 가능해지는 것
realign_branch_onto_main (promotion-checkout.sh)
publish.yml 의 certified-sha + 트리 해시 대조(:71-97) — ff면 main HEAD == 검증된 SHA라 CI 증거가 그대로 이전됨
AGENTS.md 재정렬 절과 reset --hard 처방 (dev에 새 커밋이 있을 때 파괴적)
Branch protection
main
preview
dev
required checks
ci-aggregate
ci-aggregate
ci-aggregate
strict
false
false
false
force push / deletion
금지
금지
금지
enforce_admins
false
false
false
PR 필수
아니오
아니오
예
현재 main 만 보호돼 있고(ci-aggregate, non_admins) preview/dev는 무방비다.
strict: false필수 — true면 ff push가 거부된다
platform-aggregate 는 required 금지 — postinstall-platform.yml 의 pull_request 트리거에 paths 필터가 있어 인스톨러 표면을 안 건드리는 PR에는 생성되지 않고, 그러면 PR이 "Expected — Waiting for status"로 영구 대기한다 (docs(readme): let the release badge read the release #352 실제 전례)
main/preview에 PR 미요구 — 승격이 ff push이기 때문. 검증이 사라지는 게 아니라 PR 시점에서 SHA 단위로 이동한다. 승격 대상 SHA는 dev에서 이미 ci-aggregate 를 통과했고 ff는 내용을 바꾸지 않으므로, main HEAD가 검증된 SHA와 동일해져 오히려 지금보다 강해진다
enforce_admins: false — ff가 push인 이상 불가피. #333도 같은 이유로 false를 택했다. 실질 방어는 npm publish 게이트(expected-sha 필수, exact-SHA CI 확인, 브랜치:태그 짝)가 담당하며 이 이슈에서 손대지 않는다
dev를 기본 브랜치로 전환
main → dev 로 default branch 변경. 새 PR이 자동으로 dev를 base로 잡아 base 실수를 없앤다. 대가로 GitHub 첫 화면이 dev가 된다.
단, #333이 "dev 는 릴리스 경로 밖의 contributor 통합 base로 유지"라고 명시 결정한 바 있다. 이 제안은 dev를 릴리스 경로 안으로 넣으므로 그 판단을 뒤집는다. 결정권자 확인이 필요하다.
핫픽스 경로 — 추천안
ff 구조는 preview가 항상 릴리스 가능하다고 전제하는데, 현재 preview에는 미출시 커밋이 51개 쌓여 있다.
main..preview 51 preview..main 0
이 상태에서 main만 급히 고쳐야 하면 ff 승격은 51개를 전부 함께 내보낸다. 골라낼 수 없다.
추천: hotfix/* → main → dev/preview 백머지 (아래 1번).
51커밋 격차를 보면 긴급 수정이 필요해질 상황이 실제로 보이고(#428이 그런 사례였다), 이 경로의 유일한 위험인 백머지 누락은 승격 스크립트에 사후 검증(main ⊂ preview 확인)을 넣어 기계적으로 막을 수 있다. 그 검증이 없으면 #466과 같은 결함 클래스가 재발한다.
검토한 선택지:
hotfix/* → main → dev/preview 백머지 ← 추천. 표준 경로. main에 preview가 모르는 커밋이 잠시 생기므로 백머지 + 사후 검증이 필수
핫픽스도 정규 경로로 — preview 전체를 함께 출시. 단순하지만 긴급 수정이 미검증 기능 51개를 끌고 나간다
핫픽스 없음 — preview를 항상 출시 가능 상태로 유지. 규율 부담이 크다
마이그레이션
릴리스가 정상 작동 중이므로 급하지 않다. 조용한 시점에:
보호 적용 (preview/dev 신규, main strict:false 확인), default branch → dev
스크립트 수정 — release-preview.sh preview push, promote-to-main.sh squash→ff, realign 제거
publish.ymlcertified-sha 경로 제거
test.yml/postinstall-platform.yml push 트리거 확인
누적된 쌍둥이 8개 정리 — dev/preview를 한 줄기로 재정렬
AGENTS.md/README/structure/ 동기화
핫픽스 경로 문서화 + 승격 스크립트에 main ⊂ preview 사후 검증 추가
측정 시점 2026-08-26, main 8db06a5b (v2.17.22) / preview c477f9e1 / dev 28b89527. 조사는 전부 read-only.
배경
#466은 squash 승격이 스스로 ancestor 가드를 깨뜨리는 문제였고, #468이 승격 후 자동 재정렬로 해소했다. 이후 v2.17.18/20/21/22 네 사이클이 정상 승격됐다.
이 이슈는 그 수정이 남긴 부채와, 그것을 없애는 구조 변경에 관한 것이다.
문제 1 — 재정렬이 쌍둥이 커밋을 만든다
realign_branch_onto_main이dev와preview에 각각 머지 커밋을 만든다. 두 커밋은 부모도 트리도 같은데 SHA만 다르다.baa40b45/c660dfda(v2.17.20)도 동일한 쌍이다. 서로가 서로의 조상이 아니므로 dev와 preview가 영구히 갈라진다.현재 누적 8개, 그리고 지금 이 순간:
문제 2 — 근본 원인은 그대로다
promote-to-main.sh:128은 여전히--squash다. stable 범프를 별도 승격 브랜치에서 만들어 접어 넣으므로 main에 고유 커밋이 생기고, 그래서 재정렬이 필요하다. #468은 증상을 자동으로 갚아줄 뿐 원인을 없애지 않는다.제안 — 전 구간 fast-forward
4번이 핵심이다. stable 범프를 승격 브랜치가 아니라 preview 위에서 만들면 main 고유 커밋이 사라지고, 조상 관계가 정의상 유지된다. 6번으로 dev가 preview를 흡수하므로 쌍둥이가 불필요해진다.
세 브랜치는 유지한다.
publish.yml:256이 브랜치와 태그 짝을 강제하므로(preview:preview,latest:main) preview 브랜치는 beta 발행에 반드시 필요하다.삭제 가능해지는 것
realign_branch_onto_main(promotion-checkout.sh)publish.yml의certified-sha+ 트리 해시 대조(:71-97) — ff면 main HEAD == 검증된 SHA라 CI 증거가 그대로 이전됨reset --hard처방 (dev에 새 커밋이 있을 때 파괴적)Branch protection
ci-aggregateci-aggregateci-aggregate현재
main만 보호돼 있고(ci-aggregate,non_admins) preview/dev는 무방비다.strict: false필수 — true면 ff push가 거부된다platform-aggregate는 required 금지 —postinstall-platform.yml의pull_request트리거에paths필터가 있어 인스톨러 표면을 안 건드리는 PR에는 생성되지 않고, 그러면 PR이 "Expected — Waiting for status"로 영구 대기한다 (docs(readme): let the release badge read the release #352 실제 전례)ci-aggregate를 통과했고 ff는 내용을 바꾸지 않으므로, main HEAD가 검증된 SHA와 동일해져 오히려 지금보다 강해진다enforce_admins: false— ff가 push인 이상 불가피. #333도 같은 이유로 false를 택했다. 실질 방어는 npm publish 게이트(expected-sha필수, exact-SHA CI 확인, 브랜치:태그 짝)가 담당하며 이 이슈에서 손대지 않는다dev를 기본 브랜치로 전환
main→dev로 default branch 변경. 새 PR이 자동으로 dev를 base로 잡아 base 실수를 없앤다. 대가로 GitHub 첫 화면이 dev가 된다.단, #333이 "
dev는 릴리스 경로 밖의 contributor 통합 base로 유지"라고 명시 결정한 바 있다. 이 제안은 dev를 릴리스 경로 안으로 넣으므로 그 판단을 뒤집는다. 결정권자 확인이 필요하다.핫픽스 경로 — 추천안
ff 구조는 preview가 항상 릴리스 가능하다고 전제하는데, 현재 preview에는 미출시 커밋이 51개 쌓여 있다.
이 상태에서 main만 급히 고쳐야 하면 ff 승격은 51개를 전부 함께 내보낸다. 골라낼 수 없다.
추천:
hotfix/*→ main → dev/preview 백머지 (아래 1번).51커밋 격차를 보면 긴급 수정이 필요해질 상황이 실제로 보이고(#428이 그런 사례였다), 이 경로의 유일한 위험인 백머지 누락은 승격 스크립트에 사후 검증(
main ⊂ preview확인)을 넣어 기계적으로 막을 수 있다. 그 검증이 없으면 #466과 같은 결함 클래스가 재발한다.검토한 선택지:
hotfix/*→ main → dev/preview 백머지 ← 추천. 표준 경로. main에 preview가 모르는 커밋이 잠시 생기므로 백머지 + 사후 검증이 필수마이그레이션
릴리스가 정상 작동 중이므로 급하지 않다. 조용한 시점에:
strict:false확인), default branch → devrelease-preview.shpreview push,promote-to-main.shsquash→ff, realign 제거publish.ymlcertified-sha경로 제거test.yml/postinstall-platform.ymlpush 트리거 확인structure/동기화main ⊂ preview사후 검증 추가측정 시점 2026-08-26, main
8db06a5b(v2.17.22) / previewc477f9e1/ dev28b89527. 조사는 전부 read-only.