SSD Nodes Learn Hosting plans →
가이드 Matt Connor작성자 Matt Connor · 업데이트됨 2026-09-09

Claude Code가 커밋에 기록하는 내용 확인하기

Claude Code는 커밋에 Co-authored-by 트레일러를 추가하고, 클라우드 세션은 claude.ai 링크도 남깁니다. push 전에 git 명령으로 실제 기록을 확인하고 제어하는 방법을 알아봅니다.

Claude Code가 커밋에 기록하는 내용

Claude Code는 작성하는 커밋 메시지 끝에 Co-authored-by: 트레일러를 추가하고, 생성하는 pull request 설명에 기여 표시 줄을 추가한다. 클라우드에서 실행되거나 Remote Control을 통해 실행되는 세션은 claude.ai의 세션 링크도 추가한다. 이 모든 내용은 git 기록에 저장되는 일반 텍스트다. 공개 저장소에 push하면 공개되며, 누군가 기록을 다시 작성할 때까지 그대로 남는다.

정확한 문구는 릴리스마다 변경되었으므로 이 문서를 포함해 어떤 가이드에 표시된 트레일러 사본도 그대로 신뢰하지 말아야 한다. 대신 직접 커밋을 확인해야 한다. 아래의 git 명령은 이 주제에서 변하지 않는 부분이다. git의 트레일러 처리는 수년 동안 같은 방식으로 동작해 왔으며, 다음 릴리스에서 문구가 변경된 뒤에도 같은 방식으로 계속 동작한다.

git trailer란 실제로 무엇인가

trailer는 commit message의 마지막 블록에 Token: value와 같은 형태로 작성하는 한 줄이다. Git에는 고정된 token 목록이 없다. Signed-off-by:, Reviewed-by:, Fixes:, Co-authored-by:은 하나의 메커니즘을 기반으로 한 관례다. forge, 즉 GitHub나 GitLab처럼 repository를 호스팅하는 사이트는 이 trailer를 읽고 commit 페이지에 표시할 내용을 결정한다.

Git은 이 블록의 위치를 엄격하게 처리한다. git interpret-trailers 문서에 따르면 이 그룹 앞에는 하나 이상의 빈 줄이 있어야 한다. 또한 message의 끝에 있거나 ---로 시작하는 줄 바로 앞에 있어야 한다. 그리고 전체가 trailer이거나, "Git이 생성했거나 사용자가 설정한 trailer가 하나 이상 포함되고 trailer가 전체의 25% 이상이어야 한다".

마지막 규칙이 여기서 중요하다. 마지막 블록 안에 URL만 있거나 일반 문장이 있는 줄은 trailer가 아니다. trailer가 아닌 줄이 충분히 많으면 전체 블록이 trailer로 파싱되지 않는다. 따라서 commit에 Co-authored-by: 줄이 있는 것처럼 보여도 trailer를 올바르게 읽는 모든 도구에서는 아무것도 확인되지 않을 수 있다.

기록에 이미 있는 trailer를 어떻게 확인합니까?

가장 최근 커밋의 원시 메시지부터 확인합니다.

git log -1 --format=%B

%B는 저장된 제목과 본문을 줄바꿈하거나 다시 형식화하지 않고 그대로 출력합니다. 이 출력이 기준이 됩니다. forge가 표시하는 내용은 이 메시지를 렌더링한 결과입니다.

이제 git에 해당 줄 중 trailer로 인식하는 줄을 확인하도록 요청합니다.

git log -1 --format=%B | git interpret-trailers --parse

--parse--only-trailers --only-input --unfold의 축약형이므로 trailer 블록만 출력합니다. 정상적인 결과는 trailer 하나당 한 줄입니다. Co-authored-by: 줄이 분명히 보이는데 출력이 비어 있다면 해당 블록이 위의 배치 규칙을 충족하지 못한 것입니다.

전체 기록을 검색하려면 키로 trailer를 조회합니다.

git log --format='%h %(trailers:key=Co-authored-by,valueonly)'

이전 git 버전에서는 %(trailers)에서 key= 옵션을 지원하지 않습니다. 메시지 텍스트를 검색하면 모든 버전에서 사용할 수 있습니다.

git log -i --grep='^Co-authored-by:' --format='%h %an %s'

--grep은 커밋 메시지와 일치하는 항목을 찾고, -i는 대소문자를 구분하지 않도록 합니다. 여러 도구에서 이 trailer의 대소문자 표기가 일관되지 않았기 때문에 중요합니다. push하기 전에 아직 전송하지 않은 항목만 대상으로 범위를 좁힙니다.

git log origin/main..HEAD --format=%B

이 커밋은 아직 로컬에 있으므로 적은 비용으로 수정할 수 있습니다.

GitHub에서 Co-authored-by:은 기여자 표시에 어떤 영향을 주는가?

GitHub는 trailer를 읽고 커밋 페이지에 두 번째 작성자를 표시한다. 이메일 주소가 계정에 연결된 경우에만 해당 작성자를 프로필에 연결한다. GitHub 공식 문서에서도 커밋 기여 그래프에 표시되려면 “GitHub 계정에 연결된 이메일 주소로 작성되어야 한다”고 설명한다. 따라서 어떤 계정에도 속하지 않는 주소는 프로필에 연결할 수 없다. 사람 두 명이 함께 작업하는 경우에는 이것이 핵심이다. 동료의 주소가 동료의 계정에 연결되어 있으므로 커밋이 두 사람 모두의 기여로 집계된다. 어떤 계정도 소유하지 않는 주소를 사용하면 trailer는 커밋 페이지에 표시되는 내용만 바꾸고 저장소의 기여자 목록은 바꾸지 않는다.

Git 자체는 trailer를 완전히 무시한다. git shortlog -sngit log --author는 작성자 이름과 이메일이 들어 있는 author 헤더를 읽으므로 로컬 집계에는 공동 작성자가 표시되지 않는다. 여기서 기여자 표시는 일반 텍스트 규칙 위에 forge 기능을 추가한 것이다. 즉, git 자체와 호스팅하는 forge 사이의 차이가 이 구분을 만든다.

세션 링크는 다른 문제다

트레일러는 공동 작성자를 표시한다. 세션 URL은 트랜스크립트를 가리키는 포인터다. Claude Code 설정 참고 문서에서는 attribution.sessionUrl을 "cloud 및 Remote Control 커밋에서 claude.ai 세션 링크를 제외하는" 키로 설명한다. 이를 통해 링크의 출처도 알 수 있다. 링크는 웹에서 진행한 세션과 Remote Control을 통해 진행한 세션에서 생성된다.

링크는 자격 증명이 아니다. 해당 세션을 열 수 있는지는 URL이 알려지지 않았는지가 아니라 계정 접근 권한으로 결정된다. 공개 저장소에서 링크를 제외해야 하는 이유는 더 단순하다. 링크는 내부 세션 ID를 명시하는 영구적인 공개 텍스트이며, 일반 독자를 대상으로 작성되지 않은 작업 트랜스크립트를 가리킨다. 비공개 저장소에서는 반대 논리가 적용된다. 검토자가 링크를 따라가 변경 사항이 어떻게 도출되었는지 읽을 수 있기 때문이다. 이러한 트랜스크립트가 저장되는 위치와 얼마나 오래 유지되는지는 Claude Code가 세션을 저장하고 재개하는 방법에서 설명한다.

Claude Code 커밋 attribution을 제어하는 설정

2026년 9월 1일 Claude Code 설정 참조 문서와 대조한 결과, 다음 키는 "Git and attribution"이라는 제목 아래에 문서화되어 있습니다.

  • attribution: "Claude Code가 커밋과 pull request에 추가하는 attribution을 사용자 지정"
  • attribution.commit: "Claude Code가 커밋에 추가하는 trailer를 변경하거나 숨김"
  • attribution.pr: "pull request 설명의 attribution 행을 변경하거나 숨김"
  • attribution.sessionUrl: "cloud 및 Remote Control 커밋에서 claude.ai 세션 링크를 생략"
  • includeGitInstructions: "system prompt에서 기본 제공 커밋 및 PR 지침을 제거"
  • includeCoAuthoredBy: deprecated로 표시되어 있으며, "커밋 및 PR attribution을 숨기거나 변경하려면 attribution을 사용"이라는 설명이 있습니다.

각 키가 허용하는 값은 가이드가 아니라 settings reference의 해당 항목에서 확인해야 합니다. 키 이름은 안정적입니다. 변경되는 부분은 허용 값과 기본값입니다. 키는 올바르게 입력했지만 값의 철자가 잘못된 설정 파일은 조용히 실패합니다.

설정 파일을 어디에 작성하는지에 따라 적용 대상이 달라집니다. ~/.claude/settings.json은 여는 모든 프로젝트에 적용됩니다. 저장소 최상위에 커밋한 .claude/settings.json은 저장소를 clone하는 모든 사용자에게 적용됩니다. .claude/settings.local.json은 해당 프로젝트에서만 사용자에게 적용됩니다. Claude Code는 이 파일을 처음 작성할 때 해당 파일을 global git excludes에 추가하므로 커밋에 포함되지 않습니다. 우선순위는 managed settings, command line, project local, shared project, user 순서입니다. 따라서 팀원의 local 파일이 사용자가 커밋한 파일보다 우선할 수 있습니다. 커밋한 설정은 보장된 강제가 아니라 기본값으로 취급해야 합니다.

그런 다음 설정을 검증해야 합니다. 설정이 적용되었다고 믿는 것만으로는 증거가 되지 않습니다. Claude Code가 평소 방식으로 다음 커밋을 만들게 한 뒤 결과를 다시 확인합니다.

git log -1 --format=%B
git log -1 --format=%B | git interpret-trailers --parse

trailer가 계속 출력된다면 변경 사항이 세션에 적용되지 않은 것입니다. 키가 고장 났다고 판단하기 전에 수정한 파일이 무엇인지 확인하고, 위의 우선순위 순서를 점검해야 합니다.

설정에 의존하지 않는 제어

설정은 하나의 도구를 구성한다. 저장소 규칙은 다른 도구를 사용하거나 에이전트를 전혀 사용하지 않는 기여자에게도 적용되어야 한다. Git은 이 규칙을 둘 곳을 제공한다. commit-msg hook은 메시지 파일 경로를 첫 번째 인수로 받아 실행되며, 해당 파일을 수정하거나 커밋을 즉시 거부할 수 있다.

#!/bin/sh
# .githooks/commit-msg
grep -qi '^co-authored-by: claude' "$1" || exit 0
grep -vi '^co-authored-by: claude' "$1" > "$1.new" && mv "$1.new" "$1"
chmod +x .githooks/commit-msg
git config core.hooksPath .githooks

첫 번째 grep는 처리할 내용이 없으면 즉시 종료하므로 일반적인 커밋에는 거의 비용이 들지 않는다. 두 번째는 일치하는 줄을 제거한 뒤 메시지를 다시 기록한다. 모든 trailer가 아니라 정확히 하나의 토큰만 일치시켜야 한다. "drop the last block"처럼 작성한 필터는 프로젝트에 필요한 Signed-off-by: 줄까지 제거하기 때문이다.

.git/hooks은 저장소에 포함되지 않는다. 따라서 이 디렉터리에 둔 hook은 다른 사람에게 전달되지 않는다. core.hooksPath은 Git이 커밋할 수 있는 디렉터리를 사용하도록 지정한다. 각 사용자는 여전히 git config 줄을 직접 실행해야 한다. Git이 이를 대신 설정하지 않는 것은 의도된 동작이다. clone 과정에서 저장소가 자체 실행 파일을 설치할 수 있다면 사용자 컴퓨터에서 코드를 실행하는 수단이 될 수 있기 때문이다.

메시지를 다시 작성하지 않고 커밋을 거부하려면 표준 오류에 메시지를 출력하고 hook에서 exit 1한다. 공유 저장소에서는 거부하는 편이 정직한 선택이다. 누군가의 커밋 메시지를 조용히 수정하면 규칙을 알려 주는 대신 숨기게 되기 때문이다. 이는 에이전트 자체 hook과는 다른 계층이다. 에이전트 자체 hook은 Git이 전혀 개입하기 전에 도구 호출 시 실행된다. Claude Code hook이 도구를 일치시키고 차단하는 방법에서 이 부분을 다룬다.

둘 다 fork에서 생성한 pull request에는 도움이 되지 않는다. hook이 사용자가 제어할 수 없는 컴퓨터에 있기 때문이다. CI(continuous integration)의 검사가 병합 전에 모든 커밋을 확인하는 유일한 계층이다.

if git log --format=%B "origin/${BASE_BRANCH:-main}..HEAD" | grep -qi '^co-authored-by: claude'; then
  echo "Attribution trailer found. Rewrite the branch before merging." >&2
  exit 1
fi

규칙은 적용하는 것과 함께 문서로도 남겨야 한다. 사람이 읽을 수 있는 CONTRIBUTING.md 옆에 AGENTS.md를 배치하면 에이전트와 사람에게 동일한 내용을 전달할 수 있다. CI 검사가 그 규칙을 실제로 강제한다.

push하기 전에 trailer 제거

방금 만든 commit의 경우 다음과 같이 실행합니다.

git log -1 --format=%B | grep -vi '^co-authored-by: claude' | git commit --amend -F -

-F -은 standard input에서 새 message를 읽습니다. Git은 이 방식으로 제공된 message에서 앞뒤의 빈 줄을 제거합니다. 따라서 삭제한 trailer 뒤에 남은 빈 줄도 자동으로 사라집니다. 다음 단계로 진행하기 전에 git log -1 --format=%B로 결과를 다시 확인합니다.

branch의 여러 commit을 수정하려면 merge할 대상 branch를 기준으로 interactive rebase를 실행합니다. 변경할 각 message는 reword으로 표시합니다.

git rebase -i origin/main

수정한 commit 중 가장 이른 commit부터 이후의 모든 commit은 새 hash를 갖습니다. commit의 hash에는 해당 commit의 message와 parent가 포함되기 때문입니다. commit이 local에 있는 동안에는 이 작업의 비용이 없습니다. local이 아니게 되면 비용이 커집니다.

push한 뒤 trailer 제거하기

자신만 사용하는 브랜치에서 위와 같이 기록을 다시 작성한 다음, 해당 브랜치에 강제로 push한다.

git push --force-with-lease

--force-with-lease는 마지막 fetch 이후 원격 저장소가 변경되었으면 push를 거부한다. 따라서 다른 사람이 추가한 commit을 모르게 삭제할 수 없다. 일반적인 --force에는 이러한 검사가 없다.

오랜 history 전체에 trailer가 흩어져 있다면 git filter-repo가 모든 message를 한 번에 다시 작성한다. 기존 working copy 내부에서 clone을 실행한다. 그러면 이미 보유한 remote에서 URL을 가져온다.

pip install git-filter-repo
git clone "$(git remote get-url origin)" ../project-rewrite
cd ../project-rewrite
git filter-repo --message-callback '
return b"\n".join(l for l in message.split(b"\n") if not l.lower().startswith(b"co-authored-by: claude"))
'

callback은 각 message를 bytes로 받아 저장할 message를 반환한다. 따라서 callback 안의 모든 문자열에는 b 접두사가 붙는다. filter-repo--force를 전달하지 않는 한 fresh clone이 아닌 repository에서 실행되지 않는다. 또한 작업이 끝나면 origin remote를 제거하므로 실수로 다시 작성한 내용을 push할 수 없다. remote를 의도적으로 다시 추가한 뒤 force-push한다. 그런 다음 모든 사용자에게 다시 clone하라고 안내한다. 이제 각 사용자가 보유한 모든 hash가 더 이상 올바르지 않기 때문이다.

다시 작성으로 할 수 없는 작업을 명확히 이해해야 한다. 다시 작성은 자신의 repository 사본만 변경한다. fork, 기존 clone, mirror, 이미 message를 인용한 pull request 페이지, 지난주에 repository를 수집한 code search index에는 영향을 주지 않는다. secret이 유출되었다면 해결 방법은 secret을 교체하는 것이고, 다시 작성은 정리 작업이다. disclosure trailer는 secret이 아니다. 따라서 전체 history를 다시 작성할 때의 비용과 비교해 결정해야 한다. 이 작업을 하면 열려 있는 모든 pull request를 다시 만들어야 한다.

반대편 리뷰어가 기대하는 것

유지 관리자는 이 문제에 합의하지 않았으며, 무엇이든 제거하기 전에 확인해야 하는 실제 이유도 바로 이 의견 차이에 있다. 일부 프로젝트는 공개 내용을 원하고 다시 추가하라고 요청한다. 리뷰어가 기계가 작성한 패치를 다른 관점에서 검토하기 때문이다. 일부 프로젝트는 이를 금지한다. 대개 변경 사항의 법적 작성자가 누구인지가 쟁점이다. DCO(개발자 원본 증명서)를 사용하는 프로젝트는 Signed-off-by: 줄을 요구한다. 이 줄은 코드를 제출할 권리가 있음을 밝히는 내용이며, 부주의한 메시지 필터가 이를 attribution과 함께 제거할 수 있다.

먼저 CONTRIBUTING.md를 읽는다. 프로젝트에 지침이 없으면 저장소에 적용할 규칙 하나를 정하고 문서로 남긴다. 커밋의 절반에만 trailer가 나타나는 것은 어느 쪽을 선택하는 것보다 나쁘다. 하나의 기록이 마치 두 프로젝트의 기록처럼 보이기 때문이다.

노트북 대신 서버에서 agent를 실행하면 같은 문제가 한 단계 아래에서 다시 발생한다. 자체 계정으로 VPS에서 Claude Code 실행하기에서는 agent가 접근할 수 있는 저장소 자체를 결정하며, 코딩 agent가 시스템 외부로 전송하는 내용에서는 커밋 메시지에 전혀 나타나지 않는 traffic을 다룬다.

FAQ

Co-authored-by trailer가 내 repository의 contributor 통계에 반영됩니까?

아닙니다. GitHub는 GitHub 계정에 연결된 이메일 주소를 통해 commit을 profile에 연결하고, 이를 기준으로 contribution을 집계합니다. 어떤 계정에도 속하지 않은 주소는 연결할 수 없으므로 trailer는 commit 페이지를 변경할 뿐 contributor 목록은 변경하지 않습니다. Git 자체는 이 작업에 trailer를 사용하지 않습니다. git shortlog -sn는 author header를 집계하므로 co-author는 해당 목록에 나타나지 않습니다.

이미 trailer가 포함된 모든 commit을 어떻게 찾습니까?

git log -i --grep='^Co-authored-by:' --format='%h %an %s'는 대소문자를 구분하지 않고 전체 history에서 해당 commit을 나열합니다. 최신 git에서는 git log --format='%h %(trailers:key=Co-authored-by,valueonly)'가 raw text를 검색하는 대신 git 자체의 trailer parser를 통해 값을 읽습니다. 아직 push하지 않은 항목만 보려면 range를 추가합니다: git log origin/main..HEAD --format=%B.

이미 push한 commit에서 trailer를 제거할 수 있습니까?

가능하지만 history를 다시 작성해야 하며 그 비용이 큽니다. 본인만 사용하는 branch라면 amend 또는 rebase를 수행한 다음 git push --force-with-lease를 실행합니다. 공유 branch에서는 가장 이른 수정 commit부터 모든 commit의 hash가 새로 생성되므로 모든 clone과 열려 있는 pull request를 다시 구성해야 합니다. history를 다시 작성해도 fork, mirror 또는 다른 사람이 어제 만든 clone에는 절대 반영되지 않습니다.

credential은 아니며, session 접근 여부는 URL을 추측하기 어려운지보다 account에 따라 결정됩니다. 문제는 이 링크가 작업 메모로 작성된 transcript를 가리키는 영구적인 공개 텍스트라는 점입니다. Claude Code settings reference에서는 attribution.sessionUrl를 cloud 및 Remote Control commit에서 해당 링크를 제외하는 핵심 설정으로 설명하며, commit-msg hook은 이 설정이 적용되지 않는 항목에서 링크를 제거합니다.

attribution을 아예 해제해야 합니까?

취향이 아니라 repository의 목적에 따라 결정해야 합니다. 공개 project에서는 CONTRIBUTING.md를 따르십시오. disclosure를 원하는 maintainer가 이를 다시 요구할 수 있기 때문입니다. 회사 repository에서는 trailer를 유지하는 것이 유용한 경우가 많습니다. 1년 후 reviewer가 변경 사항이 현재와 같은 형태가 된 이유를 확인할 수 있기 때문입니다. 전체 repository에 적용할 방침을 한 번 결정하고 CI에서 강제하여 history의 일관성을 유지하십시오.

#claude-code#git#commit-messages#attribution#privacy