.mailmap 테스터
.mailmap과 작성자 신원 목록을 붙여 넣으면 각 신원이 무엇으로 바뀌는지, 어느 줄이 그렇게 만들었는지, 누가 하나로 합쳐지는지 보여 줍니다.
신원 수
8
매핑 후
5
바뀐 항목
5
항목 수
5
지적 사항
2
| 커밋의 신원 | git이 보여 주는 값 | 결정한 항목 |
|---|---|---|
| jane <jane@corp.example> | Jane Doe <jane@corp.example> | :2 이름만 교체, 주소로 조회 Jane Doe <jane@corp.example> |
| Jane D <jane@laptop.local> | Jane D <jane@corp.example> | :3 주소만 교체, 주소로 조회 <jane@corp.example> <jane@laptop.local> |
| JANE DOE <jdoe@oldcorp.example> | Jane Doe <jane@corp.example> | :4 이름과 주소 교체, 주소로 조회 Jane Doe <jane@corp.example> <jdoe@oldcorp.example> |
| jane <ci@build.example> | Jane Doe <jane@corp.example> | :5 이름과 주소를 함께 조회 Jane Doe <jane@corp.example> jane <ci@build.example> |
| release-bot <ci@build.example> | release-bot <ci@build.example> | 주소는 등록돼 있지만 다음 이름에만 걸려 있습니다: jane |
| Ravi <ravi@users.noreply.github.com> | Ravi Patel <ravi@corp.example> | :6 이름과 주소 교체, 주소로 조회 Ravi Patel <ravi@corp.example> <ravi@users.noreply.github.com> |
| Ravi Patel <ravi@corp.example> | Ravi Patel <ravi@corp.example> | 이 주소에 해당하는 항목이 없습니다 |
| dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> | dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> | 이 주소에 해당하는 항목이 없습니다 |
아래 묶음은 각각 git shortlog -sn의 한 줄이 됩니다. 여기 없는 신원은 여전히 따로 집계됩니다.
- Jane Doe <jane@corp.example> · 3 개
- jane <jane@corp.example>
- JANE DOE <jdoe@oldcorp.example>
- jane <ci@build.example>
- Ravi Patel <ravi@corp.example> · 2 개
- Ravi <ravi@users.noreply.github.com>
- Ravi Patel <ravi@corp.example>
겉보기와 다르게 동작하는 항목과, git이 예상과 다르게 읽는 신원입니다.
- 주소는 맞았지만 이름이 달라 git이 그대로 두었습니다: release-bot <ci@build.example> · jane
- :3 이 주소 자체가 다른 항목의 키입니다. mailmap은 연쇄 적용하지 않습니다: jane@corp.example
모든 처리는 브라우저에서 이뤄집니다. 업로드하지 않고 저장소도 읽지 않습니다.
사용법
- 첫 번째 상자에
.mailmap을 디스크에 있는 그대로 붙여 넣으세요. 주석, 빈 줄, 윈도우 줄바꿈, 끝의 공백 모두 git과 같은 방식으로 읽으므로 정리하지 않고 그대로 복사해도 됩니다. - 두 번째 상자에는 확인할 신원을 한 줄에 하나씩 넣습니다. 작성자는
git log --format='%an <%ae>' | sort -u가 바로 이 목록을 출력하고, 커미터는%cn <%ce>를 쓰면 됩니다. 리베이스나 병합 뒤에는 둘이 다른 경우가 많습니다. - 각 행을 읽으세요. 붙여 넣은 신원, git이 내놓는 결과, 그리고 그것을 결정한 항목이 줄 번호와 형식과 함께 나옵니다. 줄 번호가 두 개면 이름과 주소가 서로 다른 항목에서 왔다는 뜻입니다.
- 합쳐지는 신원 패널을 확인하세요. 각 묶음이
git shortlog -sn의 한 줄이 됩니다. 합쳐질 줄 알았는데 목록에 없다면 그것이 찾던 중복입니다. - 지적 사항을 하나씩 처리하세요. 커밋 주소가 목록에 없는 항목은 동작하지 않고, 뒤 줄에 덮인 항목은 기여하는 바가 없으며, 이름이 한 번도 맞지 않은 항목은 대개 세 번째 형식으로 썼어야 할 네 번째 형식입니다.
자세한 설명
펼치기접기
.mailmap은 git shortlog -sn에서 같은 사람이 세 번 나오는 문제를 없애는 파일입니다. 그런데 실패할 때는 단서를 전혀 주지 않습니다. 항목은 분명히 있고 예제와 똑같이 생겼는데 중복은 그대로 남습니다. 파일과 실제 히스토리에 들어 있는 신원(git log가 출력하는 이름 <메일> 형식, 한 줄에 하나)을 붙여 넣으면 각 신원이 무엇이 되는지, 어느 줄이 결정했는지, 그 줄이 네 가지 형식 중 무엇인지 보여 줍니다. 실제 체크아웃에서 git check-mailmap이 내놓는 답을 브라우저 안에서 계산한 것입니다.
네 형식은 비슷해 보이지만 같지 않습니다. Proper Name <commit@x>는 이름을, <proper@x> <commit@x>는 주소를, Proper Name <proper@x> <commit@x>는 둘 다 바꾸며, 셋 모두 커밋 주소만으로 조회하므로 그 주소의 모든 커밋에 걸립니다. 네 번째인 Proper Name <proper@x> Commit Name <commit@x>는 이름과 주소를 함께 키로 씁니다. 파일에 Both Fixed <both@x> Old Name <both-old@x>가 있으면 Old Name <both-old@x>는 바뀌지만 Wrong Name <both-old@x>는 전혀 손대지 않습니다. "아무 일도 하지 않는" 항목의 대부분이 이 차이 때문이며, 표는 줄마다 그 사실을 밝혀 줍니다.
나머지 규칙도 그만큼 문자 그대로입니다. 주소와 이름 모두 대소문자를 구분하지 않지만, 이름은 그 밖에는 글자 단위로 비교합니다. 가운데 두 칸 공백도, 신원 줄에서 이름 앞에 붙은 문자도 그대로 반영됩니다. #은 첫 칸에 있을 때만 주석이라, 들여쓴 #은 이름의 일부가 됩니다. 주소는 <와 > 사이의 내용 그대로이고 공백도 포함되며, 줄에서 처음 나오는 <가 주소를 엽니다. 같은 커밋 주소에 대한 항목이 둘이면 서로를 대체하지 않고, 각 항목이 가진 필드만 기록하므로 한 줄의 이름과 다른 줄의 주소가 합쳐진 결과가 나올 수 있습니다. 조회는 정확히 한 번뿐이라 a → b와 b → c가 함께 있어도 a는 b에서 멈춥니다.
표 위에는 실제로 궁금했던 값이 있습니다. 목록이 몇 명으로 줄어드는지, 어떤 정식 신원이 둘 이상을 흡수했는지, 어떤 신원이 그대로 남았는지입니다. 지적 사항 패널은 커밋 주소가 목록에 없어 한 번도 동작하지 않은 항목, 뒤 줄에 덮인 항목, 이름이 한 번도 맞지 않은 이름 기반 항목, git이 아예 해석하지 못하는 신원을 짚어 줍니다.
알려 줄 수 없는 것은 저장소에 실제로 어떤 신원이 있는지입니다. 그 목록은 git log에서 가져와야 하며, 거기에 없는 주소를 가리키는 항목이야말로 아무것도 바뀌지 않는 가장 흔한 이유입니다. mailmap.file과 mailmap.blob 설정은 다루지 않습니다. 그리고 .mailmap은 표시 시점에만 쓰이는 조회표입니다. 커밋을 다시 쓰지 않고 객체 데이터베이스에 저장된 작성자도 바꾸지 않으며, GitHub의 기여자 그래프도 이 파일을 읽지 않습니다.
자주 묻는 질문
항목을 추가했는데도 git shortlog -sn에 같은 사람이 두 번 나옵니다.
열에 아홉은 네 번째 형식인데 이름이 맞지 않는 경우입니다. Jane Doe <jane@corp.example> jane <ci@build.example>는 작성자 이름이 정확히 jane인 커밋만 잡습니다(대소문자는 무시). 같은 주소라도 release-bot 이름으로 남은 커밋은 그대로인데, 이름 기반 항목이 빗나가면 그 주소의 일반 항목으로 넘어가고 그런 항목이 없을 수 있기 때문입니다. Commit Name 부분을 빼면 그 주소의 모든 커밋에 걸립니다. 다음으로 흔한 원인은 히스토리에 아예 없는 주소(git log --format='%an <%ae>' | sort -u로 확인하고 +tag 형태와 GitHub users.noreply 주소를 살피세요), 그리고 git이 찾는 위치인 작업 트리 최상단에 .mailmap이 없는 경우입니다.
네 가지 형식은 무엇이 다른가요?
조회 방식과 교체 범위가 다릅니다. 앞의 셋은 커밋 주소만으로 등록됩니다. Proper Name <commit@x>는 이름을 바꾸고, <proper@x> <commit@x>는 주소만 바꾸며 커밋의 이름은 그대로 두고, Proper Name <proper@x> <commit@x>는 둘 다 바꿉니다. 네 번째는 커밋 주소 앞에 이름을 하나 더 두고 그 이름으로도 등록되므로, 양쪽이 모두 맞는 커밋에만 적용됩니다. 한 주소에 두 종류가 함께 있으면 git은 이름 기반 표를 먼저 보고 일반 항목을 대비책으로 씁니다. 파일은 스크립트가 아니라 지도이므로 쓴 순서는 상관없습니다.
mailmap은 연쇄 적용되나요? A를 B로, B를 C로 매핑했습니다.
되지 않습니다. 조회는 신원마다 한 번만 일어나고 결과를 다시 넣지 않으므로, A에 있던 신원은 B에서 멈춥니다. 같은 파일 안에 B가 다른 항목의 키로 있어도 마찬가지입니다. 파일이 여러 해에 걸쳐 자랄 때 이 문제가 드러납니다. 예전 노트북 주소를 회사 주소로 접어 넣고, 나중에 그 회사 주소를 개인 주소로 접어 넣으면 첫 묶음은 따라오지 않습니다. 해결책은 모든 항목이 최종 신원을 직접 가리키게 하는 것입니다. 이 도구는 정식 주소가 다른 항목의 키이기도 한 경우를 표시합니다.
대소문자를 구분하나요?
키의 양쪽 모두 구분하지 않습니다. 주소와 이름 모두 대소문자를 무시하므로 커밋의 <OLD@EXAMPLE.COM>은 <old@example.com>으로 쓴 항목에 걸리고, Old Name으로 등록된 네 번째 형식 항목은 OLD NAME도 잡습니다. 그 밖에는 문자 그대로입니다. 공백 두 칸짜리 Two Spaces는 한 칸짜리 Two Spaces와 다르고, git은 신원 줄에서 이름 앞의 문자를 잘라 내지 않으므로 들여쓴 신원은 그 들여쓰기를 이름의 일부로 안고 다녀 이름 기반 항목에 걸리지 않습니다. 꺾쇠 안도 다듬지 않아 < old@x >는 어떤 커밋에도 없는 공백 섞인 키가 됩니다.
같은 커밋 주소에 항목이 둘이면 어느 쪽이 이기나요?
둘 다 일부씩 이깁니다. git은 커밋 주소마다 정식 이름 하나와 정식 주소 하나를 두고, 각 항목은 자신이 가진 필드만 기록합니다. 그래서 Alpha <alpha@x> <dup@x> 다음에 <beta@x> <dup@x>가 오면 결과는 Alpha <beta@x>가 됩니다. 첫 줄의 이름과 둘째 줄의 주소가 합쳐진, 파일 어디에도 없는 신원입니다. 같은 필드를 가진 뒤 항목만 앞을 덮어씁니다. 주소가 중복되면 어떤 줄이 조용히 아무 기여도 하지 않게 되는 이유이고, 이 도구가 이름과 주소의 출처가 다른 행을 표시하는 이유이기도 합니다.
.mailmap이 히스토리를 바꾸나요?
아닙니다. 지금 서 있는 저장소의 작업 트리에서 표시 시점에 읽히며 git log, git shortlog, git blame, git check-mailmap과 --use-mailmap 또는 log.mailmap 설정으로 실행한 명령이 적용합니다. 각 커밋 객체에 기록된 작성자는 그대로이고, 그것이 핵심입니다. 이 방식으로 이름을 고치면 비용이 없고 서명도 깨지지 않지만, 히스토리를 다시 쓰면 그 아래 모든 커밋 아이디가 바뀝니다. 대신 이 파일은 체크아웃된 곳에서만 효과가 있어서, 자체 기여자 목록을 만드는 서비스는 GitHub을 포함해 이 파일을 참조하지 않습니다.
관련 도구
.gitignore 테스터
.gitignore와 경로 목록을 붙여넣으면 어떤 경로가 무시되는지, 그리고 몇 번째 줄이 그렇게 결정했는지 git check-ignore -v처럼 보여줍니다.
개발
Git 설정 우선순위 테스터
git 설정 파일을 붙여 넣으면 키마다 어떤 값이 이기는지, 그 값이 나온 범위·파일·줄, 무엇을 덮었는지, 어떤 includeIf가 걸렸는지 보여줍니다.
개발
.gitattributes 테스터
.gitattributes와 경로 목록을 붙여넣으면 각 경로에 최종 적용되는 모든 속성과, 그 값을 정한 줄 또는 매크로를 보여줍니다.
개발
정적 라이브러리(.a) 분석기
.a 아카이브를 브라우저에서 읽습니다. 멤버의 크기와 날짜, 각 오브젝트가 정의하고 필요로 하는 심볼, 그리고 심볼 인덱스가 낡았는지까지 보여줍니다.
개발
JSON 정규화 (RFC 8785 JCS)
RFC 8785대로 JSON을 정규화하고 해시합니다: UTF-16 키 순서, ECMAScript 숫자 표기, 공백 제거, 그리고 그 바이트의 SHA-256.
개발
Conventional Commit 메시지 빌더
타입, 스코프, 호환성 깨짐, 푸터가 포함된 Conventional Commits 메시지를 브라우저에서 만듭니다.
개발