Conventional commits에서 체인지로그로
4분 분량 업데이트
Conventional commits는 체인지로그에 세 가지를 공짜로 준다. 각 변경 사항의 유형, 그것이 건드린 시스템의 부분, 그리고 무언가를 망가뜨리는지 여부다. 그 외에는 아무것도 주지 않는다. 문구, 그룹화, 선별, 즉 체인지로그 그 자체는 전적으로 열려 있는 상태로 남으며, 그렇지 않은 척하는 파이프라인은 포맷된 git log를 내보내게 된다.
feat(exports): add CSV column selection
fix(auth): reject expired refresh tokens
chore(deps): bump node-pg to 8.11
Conventional Commits 형식의 세 커밋이다. 이것들로부터 기계는 하나는 기능이고, 하나는 수정이고, 하나는 정리 작업이며, 각각이 시스템의 어느 부분을 건드렸는지를 알려줄 수 있다. 이것은 정말로 유용하며, 이 관례의 약속 전부이기도 하다. 사람이 아닌 무언가가 읽을 수 있는 커밋 히스토리. 실수는 이것이 체인지로그를 만들어준다고 생각하는 것이다. 이것이 주는 것은 원재료다.
이 관례는 무엇을 규정하는가
유형, 선택적인 범위, 그리고 설명: type(scope): description. 유형은 관례적으로 feat, fix, chore, docs, refactor, test, perf, build, ci다. 파괴적 변경을 표시하는 것은 두 가지다. 콜론 앞의 !, 또는 BREAKING CHANGE: 푸터. 도구는 마이너와 패치 버전 증가를 위해 feat와 fix에, 메이저를 위해 파괴적 변경 표시에 의존한다.
| 커밋이 주는 것 | 체인지로그가 필요로 하는 것 | 누가 그 간극을 채우는가 |
|---|---|---|
feat / fix / chore | Added / Fixed / 내부용 | 매핑, 자동 |
(scope) | 독자가 알아볼 수 있는 그룹화 | 사람, 범위당 한 번 |
! 또는 BREAKING CHANGE: | 누가, 언제까지, 무엇을 해야 하는지 | 사람, 매번 |
| 리뷰어를 위해 쓰인 설명 | 고객을 위해 쓰인 결과 | 사람, 항목마다 |
| 커밋 하나 | 여러 커밋일 수 있는 변경 사항 하나 | 스쿼시 규칙, 또는 사람 |
이 표시는 도구에게 알려줄 뿐 호출자에게는 알려주지 않는다. 그것은 API를 비추천 처리하는 방법과 파괴적 변경이란 무엇인가의 주제다. 이것은 작은 스펙이며, 거기서 아무것도 생성하지 않더라도 따를 가치가 있다. 커밋마다 하나의 결정을 강제하기 때문이다. 이것은 사용자가 보는 변경인가, 아닌가.
Conventional commits는 어디서 멈추는가
문장에서 멈춘다. 이 관례가 포착하는 모든 것은 변경 사항에 대한 메타데이터이고, 변경 사항 그 자체는 여전히 리뷰어의 어휘로 서술되어 있다.
커밋 메시지는 리뷰어를 위해 쓰인다. fix(auth): reject expired refresh tokens는 정확하지만 고객에게는 아무것도 말해주지 않는다. 체인지로그의 독자가 원하는 것은 “세션이 실제로 만료되었을 때만 로그아웃되며, 간헐적인 401은 더 이상 보이지 않습니다”다.
범위는 내부용이다. exports, auth, ingest는 모듈 이름이다. 안정적이라서 그룹화에는 좋지만, 코드베이스 밖의 누구에게도 무의미하다.
하나의 변경 사항은 흔히 여러 커밋이다. 열한 개의 커밋에 걸쳐 병합된 기능은 열한 개의 항목을 만들고, 그중 열 개는 잡음이며, 그것을 숨기려고 스쿼시하면 리뷰 히스토리를 잃는다.
chore는 분류가 아니라 쓰레기통이다. 의존성 업데이트, CI 변경, 이름 변경이 모두 그곳에 떨어지며, 그중 일부는 사용자에게 중요하지만 대부분은 그렇지 않다.
즉, 이 관례는 유형, 범위, 파괴적 여부를 공짜로 주고, 문구, 그룹화, 선별은 전적으로 열어둔다. 이 세 가지가 바로 체인지로그다. 체인지로그 항목은 실제로 누가 책임지는가는 그 문구, 그룹화, 선별을 누가 맡아야 하는지를 다룬다. 관례 자체는 그것에 대해 아무런 의견도 갖고 있지 않기 때문이다.
Conventional commits로부터 체인지로그를 어떻게 생성하는가
두 개의 층으로, 그리고 두 번째 층은 필수여야 한다.
첫 번째 층, 자동. 병합 시점에 커밋으로부터 초안 항목을 도출한다. 유형을 체인지로그 유형으로 매핑하고(feat는 Added로, fix는 Fixed로, 파괴적 변경 표시는 플래그를 단 Changed로), 범위는 텍스트가 아니라 메타데이터로 유지하고, PR로의 링크를 단다. 이것을 Keep a Changelog가 요구하는 Unreleased 섹션에 놓는다.
두 번째 층, 사람, 그리고 필수. 릴리스가 나가기 전에, 모든 초안 항목은 사용자의 어휘로 한 줄 다시 쓰이거나, 내부용으로 표시되어 공개 뷰에서 빠져야 한다. 이것이 사람들이 건너뛰려고 하는 단계이며, 이것을 건너뛰는 것이 diff처럼 읽히는 체인지로그를 만들어낸다.
중요한 설계상의 세부 사항은 두 번째 층이 파이프라인에서 선택 사항이 아니라는 점이다. 편집되지 않은 초안으로 릴리스를 자를 수 있다면, 모두가 바쁜 그 주에 그렇게 될 것이다. 어떤 단계가 기계의 것이고 어떤 단계가 사람의 것인지가 체인지로그 자동화의 전부다.
릴리스를 자르는 것은 또한 git 태그, 릴리스, 그리고 이 체인지로그 항목이 서로 맞아떨어지거나 동기화에서 벗어나기 시작하는 순간이다; git 태그, 릴리스, 그리고 당신의 체인지로그가 셋을 동기화된 상태로 유지하는 방법을 다룬다.
세 가지 함정
스쿼시 병합이 푸터를 먹어버린다. 여러분의 플랫폼이 PR 제목을 메시지로 삼아 스쿼시한다면, 그 브랜치 안의 커밋에 있던 BREAKING CHANGE: 푸터는 사라지고, 여러분의 도구는 조용히 그 파괴적 변경을 보지 못하게 된다. 여러분의 스쿼시 템플릿이 실제로 무엇을 유지하는지 확인하라.
되돌린 커밋이 유령 항목을 만든다. 다음 날 되돌려진 fix는, 도출 과정이 되돌림을 반영하지 않는 한, 결코 출시되지 않은 무언가에 대한 항목을 생성한다. 대부분의 도구는 그렇게 하지 않는다.
버전 증가와 체인지로그가 어긋난다. 버전이 커밋으로부터 계산되고 체인지로그가 나중에 손으로 쓰인다면, 이 둘은 약 두 번의 릴리스 안에 어긋난다. 둘 다 같은 패스에서 계산하거나, 둘 중 하나가 틀렸다는 것을 받아들여라.
파이프라인 없이 기계적인 부분만 원한다면
우리의 체인지로그 생성기는 브라우저에서 도출 단계를 수행한다. 커밋을 붙여넣으면 그룹화되고 유형이 붙은 항목이 나온다. 의도적으로 결정론적이고 완전히 클라이언트 측에서 동작하므로, 붙여넣은 커밋이 여러분의 기기를 벗어나는 일이 없다. 이는 비공개 저장소의 메시지일 때 중요하다. 이것은 수집 절반을 정직하게 처리하고 두 번째 층을 흉내 내려는 시도는 하지 않는다. 두 번째 층은 판단의 문제이며, 그것을 흉내 내는 도구는 정확히 이 글이 반대하는 그 체인지로그를 만들어내기 때문이다.
파이프라인 버전에 대해서는 체인지로그 도구가 무엇이 존재하는지를 다룬다.
요약
Conventional commits는 “이것이 어떤 종류의 변경인가”에 신뢰성 있고 저렴하게 답한다. “사람들에게 무엇을 말해야 하는가”에는 답하지 않으며, 커밋 메시지 위에 아무리 도구를 쌓아도 그것은 답이 되지 않는다. 그 정보가 애초에 커밋 메시지 안에 존재한 적이 없기 때문이다. 다시 쓰기를 위한 예산을 확보하라.
FAQ
Conventional commits는 체인지로그를 자동으로 생성하는가? 초안은 자동으로 생성한다. 유형이 붙고, 범위가 지정되고, 링크가 걸린 항목들이다. 고객을 위한 문구, 그룹화, 무엇을 뺄지에 대한 결정은 여전히 사람을 필요로 하며, 그 단계를 건너뛰는 파이프라인은 커밋 메시지를 그대로 발행하게 된다.
어떤 conventional commit 유형이 체인지로그에 나타나는가?
feat와 fix는 항상 Added와 Fixed로 나타난다. perf는 보통 Changed로 나타난다. chore, docs, refactor, test, build, ci는 기본적으로 내부용이며, 사람이 그중 하나를 승격시켰을 때만 나타난다.
Conventional commits는 파괴적 변경을 어떻게 표시하는가?
유형이나 범위 뒤의 !(feat(api)!: ...), 또는 커밋 본문의 BREAKING CHANGE: 푸터. 스쿼시 병합이 PR 제목만 남긴다면 둘 다 사라진다.
체인지로그를 자동화하는 데 conventional commits가 필요한가? 필요 없다. PR 라벨, PR 템플릿, issue 링크는 pull request로 병합하는 팀에게 같은 메타데이터를 전달한다. Conventional commits는 변경 단위가 커밋일 때 가장 저렴한 선택지다.
이 글의 기술적 내용은 독립적으로 검토되지 않았습니다. 잘못된 부분이 있으면 알려 주세요. 바로잡겠습니다.