Git Notes: Git의 가장 멋지고 미움받는 기능 (2022)
(tylercipriani.com)- Git notes는 Git 객체를 바꾸지 않고 별도 네임스페이스에 메타데이터를 붙이는 기능이지만, 낮은 사용성과 제한적 채택 때문에 널리 쓰이지 않음
- 오래된 커밋 메시지를 고치지 않아도 새 정보를 덧붙일 수 있어, 리뷰·빌드·티켓 정보처럼 자동화 시스템이 남기는 기록에 잘 맞음
- Git 프로젝트와 Gerrit은 notes를 실제로 활용해 커밋별 메일링 리스트 토론, 테스트 결과, 리뷰어 정보를
git log에서 확인할 수 있게 함 - Google의 git-appraise는 git notes 위에 분산 코드 리뷰를 구현해 리뷰 요청, 댓글, 리뷰, 병합을 로컬에서 수행할 수 있게 함
- GitHub는 2014년에 커밋 notes 표시를 중단했고, blob·tree notes는 Git 내부 명령에 익숙해야 해 프로젝트 히스토리 분산이라는 가능성에도 쓰기 어려움
Git 객체를 바꾸지 않는 메타데이터
- Git notes는 Git이 추적하는 객체에 별도 메타데이터를 저장하는 기능임
- 대상은 커밋뿐 아니라 blob과 tree도 포함됨
- 객체 자체를 수정하지 않고 별도 네임스페이스에 정보를 붙임
- 이미 히스토리에 들어간 커밋 메시지는 보통 안전하게 고치기 어렵지만, notes를 쓰면 오래된 커밋에도 새 정보를 추가할 수 있음
- 다음처럼
git notes add -m으로 메모를 붙일 수 있음git notes add -m 'Acked-by: <tyler@tylercipriani.com>' - 이후
git log에서 해당 커밋 아래에Notes:블록으로 표시됨
- 다음처럼
- Scott Chacon은 2010년 GitHub.blog에서 notes를 다른 개발자와의 대화보다 티켓·빌드 시스템 같은 자동화 기록을 붙이는 데 더 적합한 기능으로 봄
실제 활용과 막히는 지점
- Git 프로젝트는 각 커밋을 메일링 리스트 토론과 연결하는 데 notes를 사용함
- 예시 커밋의
Notes (amlog)에는Message-Id가 들어 있고, 이 값이 패치 토론 스레드로 이어짐
- 예시 커밋의
- notes는 커밋이나 브랜치별 작업 시간 추적,
git log에 리뷰·테스트 정보 추가, 완전 분산 코드 리뷰 같은 용도로도 쓰임 - Gerrit의 reviewnotes 플러그인은 코드 리뷰 메타데이터를 Git 안에서 오프라인으로 볼 수 있게 함
- notes를 가져오고 표시하는 명령은 다음과 같음
git fetch origin refs/notes/review:refs/notes/review git log --show-notes=review - 표시 정보에는
Verified+1,Verified+2,Code-Review+2,Submitted-by,Submitted-at,Reviewed-on,Project,Branch등이 포함됨
- notes를 가져오고 표시하는 명령은 다음과 같음
- Google의 git-appraise는 git notes 위에 구축된 “fully distributed code review” 시스템임
- GitHub, GitLab 같은 코드 forge와 독립적으로 동작함
- 변경 리뷰 요청, 변경에 대한 댓글, 리뷰와 병합을 로컬 컴퓨터에서 수행할 수 있음
- 웹 인터페이스도 포함함
- 가장 큰 약점은 사용성임
- GitHub는 2014년에 커밋 notes 표시를 중단함
- 커밋 notes는
gitconfig설정으로 자동 fetch와git log표시를 어느 정도 쉽게 만들 수 있음git config --add \ remote.origin.fetch \ '+refs/notes/*:refs/notes/*' git config \ notes.displayRef \ 'refs/notes/*' - blob이나 tree에 notes를 저장하려면 Git의 plumbing에 익숙해야 함
- Git은 코드 히스토리를 분산하지만, Git 저장소의 많은 가치는 GitHub 같은 forge 안에 잠겨 있음
- git notes는 코드뿐 아니라 프로젝트 전체 히스토리를 분산하는 경로가 될 수 있음
댓글과 토론
Hacker News 의견들
-
잘 알려지지 않은 또 다른 기능으로 git trailers가 있음: https://alchemists.io/articles/git_trailers
커밋을 만들 때 포함할 수 있는 키-값 구조 데이터이고, 일부 시스템은 이를 메타데이터 첨부에 사용함. 예를 들어 Gerrit은 Change-Id를 붙이는 데 이 기능을 씀- 다른 시스템의 비슷한 기능으로 PostgreSQL COMMENT가 있음: https://www.postgresql.org/docs/17/sql-comment.html
PostgreSQL의 여러 데이터베이스 객체에 텍스트를 붙일 수 있게 해줌. PostgreSQL에도 편집 가능한 구조화된 키-값 형태의 데이터베이스 객체 메타데이터 기능이 있으면 좋겠음 - GitHub가
[skip ci]를 넣는 대안으로 git trailers를 쓰는 걸 최근 알게 됐고, 아마 커밋 메시지를 소비하는 하위 시스템에서 더 쉽게 제거하기 위해서일 듯함: https://docs.github.com/en/actions/managing-workflow-runs-an...
왜 마지막 trailer여야 한다고 강제하는지는 모르겠고, 정규식 때문일 수도 있음 - 내 브랜치의 커밋 중 단위 테스트를 돌린 커밋을 표시하려고 git notes를 썼고, 스크립트가 그런 커밋은 건너뛰게 했음
오픈소스 업스트림과 작업하면서git rebase -i로 브랜치를 완벽하게 다듬고 싶을 때 유용했음. 지금은 그 정보는 git trailers에 넣는 편이 더 좋아 보임. Change-Id에 관해서는 Git 자체에 이런 식별자가 있으면 도구들도 이해할 수 있어서 좋겠음. 커밋 메시지로 커밋을 식별하는 건 특히 MR에서 메시지를 바꿀 수 있을 때 취약함. 커밋 ID는 커밋을 유일하게 식별하지만, 같은 변경을 다른 커밋 위로 옮길 수 있을 때는 유용한 식별자가 아님. 다만 trailers는 실제 커밋의 일부이고 notes는 아니라서, 내가 쓰던 용도에는 좋은 대체가 아니겠음 - 흥미롭고, 이 기능은 몰랐음. conventional commits를 좋아하는데, trailers가 그런 메타데이터를 추가하는 더 나은 방식처럼 보임
커밋 메시지에 수동으로 넣는 것과--trailer플래그를 쓰는 것이 기능적으로 같은지 궁금함 - GOOG에서 일할 때 쓰던 Gerrit이 정말 그립지만, 2020년대 기준으로 배포 이야기는 꽤 별로임
로컬에서 인스턴스를 띄우고 GitHub에 호스팅된 저장소와 통합해보려다 좌절만 했음. 커밋을 넘나드는 변경 추적 등을 GitHub보다 잘 처리하면서, 더 활발히 개발되고 GitHub 통합도 친화적인 대안이 있는지 궁금함. GitHub의 코드 리뷰 도구는 정말 싫음
- 다른 시스템의 비슷한 기능으로 PostgreSQL COMMENT가 있음: https://www.postgresql.org/docs/17/sql-comment.html
-
Forgejo도 올해 1월에 나온 버전 10부터 지원함: https://forgejo.org/2025-01-release-v10-0/#new-features
https://codeberg.org/forgejo/forgejo/pulls/4753 -
정말 멋져 보이지만, amend나 rebase처럼 사실상 커밋을 수정된 복사본으로 바꾸는 히스토리 재작성 기능과 notes가 어떻게 같이 동작하는지 궁금함
notes는 특정 커밋, 트리, 블롭 ID에 붙는 것처럼 들림.git rebase등이 notes를 새 커밋으로 복사할 만큼 똑똑한지, 아니면 그냥 사라지는지 궁금함. 인터랙티브 rebase에서 여러 커밋을 하나로 squash하면 어떻게 되는지도 의문임. 블롭과 트리에 notes를 붙이는 것도 같은 문제가 있어 보임. 저장소의 파일이나 디렉터리에 메타데이터를 붙이는 것처럼 느껴지지만, 실제로는 특정 내용에 붙이는 셈임. 예를 들어"Hello world!"문자열을 담은 블롭에 note를 붙이면, Git은 그 내용을 가진 모든 파일에 note를 연결할까? 또 한 파일을"Hello, world!"로 바꾸면 notes를 잃게 될까?- 이건 설정 가능함. 기본적으로 amend와 rebase 작업은 notes를 앞으로 복사함.
notes.rewrite항목은git-config(1)에서 보면 됨
- 이건 설정 가능함. 기본적으로 amend와 rebase 작업은 notes를 앞으로 복사함.
-
Git을 아마 10년 정도 써왔는데 git notes가 있는 줄 몰랐음. 멋짐
“모든 forge가 코드 리뷰 메타데이터를 Git 안에서 오프라인으로 사용할 수 있게 해달라”는 요청은 GitHub 같은 상업적 forge에는 잘 안 먹힐 듯함. 스스로도 말했듯 Git 저장소의 많은 가치가 GitHub 같은 forge에 잠겨 있기 때문임. 영리 기업은 보통 자기들의 부가가치를 범용화하는 데 적극적이지 않음. GitHub를 비난하려는 건 아니고, 훌륭한 서비스와 매우 관대한 무료 티어를 제공하며, 옮기고 싶으면 API로 모든 데이터를 추출할 수 있게 해준다는 점에서 잘하고 있다고 봄. 그냥 상업적 운영의 본질이 그렇다는 것임- 그 기능을 차별점으로 내세우는 새 서비스를 먼저 시작해야 하고, 그러면 경쟁자들이 따라잡으려고 그 기능을 다시 추가할 수도 있음
-
Git notes는 커밋이 이미 만들어지고 다른 사람에게 보인 뒤에 텍스트를 자주 추가할 때만 멋짐
Acked-By와 메일링 리스트 토론 링크 예시는 좋은 예가 아닌 듯함. 둘 다 커밋을 만들 때 이미 알고 있을 가능성이 큼. Git 커밋 메시지는 사실상 길이 제한이 거의 없으니, forge에서 있었던 커밋 관련 논의를 커밋 메시지 자체에 그대로 복사할 수도 있음. 더 나은 예시는 나중에 되돌려진 커밋에 git note를 추가하는 경우라고 봄- 흔한 실패 모드는 커밋 메시지가 실제로는 고치지 못한 버그를 고쳤다고 당당하게 선언하는 것임. 그리고 수정이 만든 연쇄 버그들을 한 버그에 연결해버림
내가 이상한 걸 수도 있지만, 코드가 애초에 왜 작성됐는지 떠올리려고 주석이나 annotate를 제대로 보지 않는 동료를 너무 많이 봤음. 그냥 냅다 바꾸고 문제가 자기에게 연결되지 않길 바라는 식임. 하지만 버그 수정만 기다리던 화난 고객을 상대해봤고, 얼마 지나지 않아 그 버그가 다시 들어오는 걸 겪고 나면 버그 수정에 더 신중해질 수 있음. 여러 버그를 한 번에 고치려면 리팩터링이 필요한 경우가 많고, 리팩터링은 새 기능 기회나 성능 개선을 열어주기도 함 - 커밋에 대한 토론, 즉 리뷰와 커밋 승인(Ack)은 커밋이 만들어지기 전에는 일어날 수 없음
나중에 되돌려진 커밋에 표시를 남기는 용도라면 커밋 메시지가 더 나음. 파일에 대해 blame을 하면 그 파일의 최신 변경이 보이고, 어떤 커밋이 다른 커밋의 변경을 되돌렸다면 더 최신의 되돌림 커밋이 blame에 나타남 - 커밋이 만들어진 뒤에도 토론은 계속될 수 있음
- 흔한 실패 모드는 커밋 메시지가 실제로는 고치지 못한 버그를 고쳤다고 당당하게 선언하는 것임. 그리고 수정이 만든 연쇄 버그들을 한 버그에 연결해버림
-
이건 지식 부족이 아니라 UI 문제임. GitHub UI가 notes를 보여주면 사용량은 즉시 훨씬 늘어날 것임
- GitHub가 이걸 지원했으면 좋겠음
-
“Git의 가장 멋지지만 사랑받지 못하는 기능”은 많음. 예를 들면 bisect, pickaxe, reflog, range-diff, archive, annotated tags 등임
많은 사람이 Git을 화려한 Google Drive 정도로만 생각해서 이런 기능들이 자주 잊히는 게 아쉬움- Git notes는 어차피 기능 추적에는 더 높은 수준의 프로젝트 관리 도구가 필요하므로 중복임. 로드맵, 기능 계층, 비기술적 세부사항이 필요하고, 큰 추적기나 Jira를 떠올리면 됨
그래도 괜찮다고 봄. Unix 철학은 한 가지에 집중하고 그걸 잘하는 것임 - 많은 경우 그런 기능들이 실제로 그다지 유용하지 않고, 일꾼 역할을 하는 핵심 도구 주변의 장식에 가깝기 때문임
- 나열할 기능들을 다 알 거라고 예상했는데 pickaxe에서 기습당했음. 내가 너무 자신만만하면 안 되겠음
- Git notes는 어차피 기능 추적에는 더 높은 수준의 프로젝트 관리 도구가 필요하므로 중복임. 로드맵, 기능 계층, 비기술적 세부사항이 필요하고, 큰 추적기나 Jira를 떠올리면 됨
-
LibreOffice 프로젝트에서는 Apache OpenOffice 저장소의 각 커밋을 추적하는 데 Git notes를 썼음
그 저장소를 LibreOffice Git 저장소의 브랜치로 미러링하면서, 각 커밋이 관련 없는 변경인지, 예를 들어 LibreOffice가 오래전에 더 나은 것으로 바꾼 빌드 시스템 변경인지, 이미 LibreOffice에 있던 변경과 중복인지, 아니면 드문 경우로 LibreOffice에 받아들여졌는지와 어떤 커밋으로 cherry-pick됐는지를 기록했음. 아직도 https://cgit.freedesktop.org/libreoffice/core/log/?h=aoo/tru...에서 직접 볼 수 있고, 이 Git 프런트엔드는 여전히 notes를 표시함. 몇 년 전부터는 이런 변경 추적을 멈췄는데, 아마 Apache OpenOffice의 변경 속도가 아주 느려져서 몇 안 되는 변경을 cherry-pick해 얻을 이득이 별로 없어졌기 때문일 것임 -
가장 멋지지만 사랑받지 못하는 기능이 아니라, 회사 전체를 개발자만으로 운영하는 팀 같은 아주 특정한 경우에는 멋질 수도 있었던 기믹 기능에 가까움
필요한 건 커밋 메시지에 들어가고, 별도 시스템의 티켓을 참조하는 건 버그가 아니라 기능임. JIRA나 다른 시스템은 비개발자와 소통하는 데 쓰이기 때문임. 예를 들어 비즈니스 분석가는 코드나 저장소 접근 권한이 전혀 없고, 지원 담당자도 저장소와 코드에 접근하지 못함. 비개발자가 notes를 보고 편집할 수 있는 프런트엔드를 만들 수는 있겠지만 그래도 별 의미가 없음. BA나 지원팀 등은 특정 커밋에 관심이 없고, 하나의 기능이 커밋 하나에 딱 맞을 수도 있지만 보통은 그렇지 않음. 여러 저장소를 쓰고 기능 하나가 여러 서비스에 걸치면 git notes는 꽤 쓸모없어지고, 결국 외부 시스템에 대한 참조가 필요함- 비즈니스 분석가나 지원 담당자가 코드와 저장소 접근 권한을 받지 않는 게 오히려 이상하지 않나 싶음. 자기 제품을 블랙박스처럼 다뤄서 얻는 이점이 뭘까?
그런데 그게 주류임. 가끔 같은 모노레포를 공유하는 다른 팀의 분석가가 코드 한 줄로 바로 답할 수 있는 질문을 나에게 함. 그 분석가는 기술적인 편이고 SQL도 아는데도 그렇고, 우리 코드는 매우 관용적이고 높은 수준으로 작성되어 있음. 그래도 문화는 내재적 비효율 때문에 죽기 전까지는 스스로 바뀌지 못함 - 커밋 메시지에는 속하지 않지만 관련 있는 커밋 외부 데이터가 많음. 테스트 통과 여부[1], 수동 테스트 기록, 코드 리뷰의 반복 과정, 6개월 넘은 문제 커밋을 파헤칠 때 남기는 메모 같은 것들임
[^1] https://news.ycombinator.com/item?id=44348438
- 비즈니스 분석가나 지원 담당자가 코드와 저장소 접근 권한을 받지 않는 게 오히려 이상하지 않나 싶음. 자기 제품을 블랙박스처럼 다뤄서 얻는 이점이 뭘까?
-
GitLab의 notes 지원을 요청한 9년 된 기능 요청이 최근 닫힘: https://gitlab.com/gitlab-org/gitlab/-/issues/15029
안타깝게도 읽으려면 로그인해야 하지만, 아무 gitlab.com 계정이면 될 것임- 더 완성도 있는 제안이 담긴 다른 이슈도 있음: https://gitlab.com/gitlab-org/gitlab/-/issues/216351
- 궁금해할 사람들을 위해 말하자면, 완료돼서 닫힌 게 아니라 방치되어 닫힌 것임: “현재 초점이 이 영역에 있지 않아 이 기능 요청을 닫습니다”