- 빅분기
- 코딩테스트 python
- 프로그래머스
- 데이터베이스
- python
- 코딩테스트
- Django
- 이기적
- 이것이 취업을 위한 코딩테스트다 with 파이썬
- 빅데이터분석기사
- 네이버부스트캠프
- AI 플랫폼을 활용한 데이터 분석
- 부스트코스
- 기초다지기
- unsub
- 빅데이터 분석 기반 에너지 운영 관리자 양성 및 취업과정
- Oracle
- 데이터 분석 기반 에너지 운영 관리자 양성 및 취업과정
- DB
- boostcoures
- [멀티잇]데이터 시각화&분석 취업캠프(Python)
- boostcourse
- r
- 파이썬
- Ai
- 오라클
- SQL
- 정보처리기사
- 인공지능기초다지기
- PY4E
- Today
- Total
매일공부
[Git] GitHub push할 때마다 까먹는 커밋 이메일 교정 절차 본문
왜 이게 필요한가
로컬 저장소의 user.email은 회사 이메일로 고정해서 쓰고 있다. 이 저장소가 회사 NAS 서버(dev/origin)와 GitHub 양쪽에 push되기 때문에, 커밋 작성자 이메일이 회사 계정으로 남아야 회사 서버 쪽에서 추적이 된다.
문제는 GitHub 계정에 "Block command line pushes that expose my personal email address" 설정을 켜뒀다는 것. 이 설정이 켜져 있으면, 회사 이메일이든 개인 이메일이든 GitHub이 알고 있는 "진짜 이메일"로 찍힌 커밋은 push 자체가 거부된다(email privacy restrictions). GitHub용으로는 GitHub이 발급해주는 noreply 이메일(숫자+아이디@users.noreply.github.com)을 써야 한다.
하지 말아야 할 것
로컬/전역 user.email을 noreply로 바꾸지 말 것. 그러면 회사 서버로 push할 때도 커밋이 noreply 이메일로 찍혀서, 회사 쪽에서 이 사람이 커밋한 게 맞는지 계정 추적이 깨진다. (실제로 한 번 실수로 git config --unset user.email을 했다가 바로 원복한 적이 있다.)
해야 할 것 — GitHub push 직전에만 해당 범위의 커밋 이메일을 교정
평소 작업(회사 서버로 push하는 것)은 그대로 회사 이메일로 진행하고, GitHub에 올릴 때만 그 시점에 새로 추가된 커밋들의 이메일을 git filter-branch로 임시 교정해서 push한다.
브랜치 구조
- master: 실제 작업 브랜치. 회사 이메일로 계속 커밋. 회사 서버(dev/origin)로는 그대로 push
- github-mirror: GitHub 업로드 전용 브랜치. 평소엔 안 건드리다가, GitHub에 올릴 때만 master를 기준으로 최신화
절차
# 0. 편집 중인 변경사항 있으면 치워두기
git status --short
git stash -u # 변경사항 있을 때만
# 1. github 리모트 최신 상태 가져오기
git fetch github
# 2. github-mirror를 마지막으로 push된 지점(github/main)에 맞추기
git checkout github-mirror
git reset --hard github/main
# 3. 실제 새 커밋만 골라내기 — 반드시 git cherry 사용 (해시 아닌 patch 내용 비교)
git cherry github/main master
git cherry -v github/main master | grep '^+' # "+"만 진짜 새 커밋
⚠️ git log github/main..master로 새 커밋을 판단하면 안 된다. 이메일 교정(filter-branch)을 거치면서 커밋 해시가 master와 달라지기 때문에, 단순 범위 비교는 이미 올라간 커밋까지 전부 "새 커밋"으로 착각한다. 실제로 이 방식으로 확인했다가 386개가 새 커밋으로 잡혔는데, 진짜 새 커밋은 3개뿐이었던 적이 있다. git cherry는 해시가 아니라 **커밋의 실제 변경 내용(patch-id)**을 비교하기 때문에, 이메일만 바뀌고 내용이 같은 커밋은 정확히 걸러내고 진짜 새 커밋만 잡아낸다.
# 4. 확인한 새 커밋만 오래된 순서대로 cherry-pick
git cherry-pick <해시1> <해시2> <해시3>
# 충돌 시: 파일 수정 → git add <파일> → git cherry-pick --continue
# 잘못됐으면: git cherry-pick --abort (전부 되돌림, 안전)
# 5. 새 커밋 이메일 교정 (회사 이메일 → GitHub noreply)
git log --format='%h %ae %s' github/main..github-mirror # 회사 이메일인지 확인
git filter-branch -f --env-filter '
if [ "$GIT_AUTHOR_EMAIL" = "<회사이메일>" ] || [ "$GIT_AUTHOR_EMAIL" = "<개인이메일>" ]
then
export GIT_AUTHOR_EMAIL="<GitHub noreply 이메일>"
fi
if [ "$GIT_COMMITTER_EMAIL" = "<회사이메일>" ] || [ "$GIT_COMMITTER_EMAIL" = "<개인이메일>" ]
then
export GIT_COMMITTER_EMAIL="<GitHub noreply 이메일>"
fi
' -- github/main..github-mirror
# 6. noreply로 바뀌었는지 재확인 후 push
git log --format='%h %ae %s' github/main..github-mirror
git push github github-mirror:main
# 7. master로 복귀 + 편집 중이던 내용 복원
git checkout master
git rev-parse master # 위 과정에서 master가 안 바뀌었는지 확인
git stash pop # 0번에서 stash 했다면
주의사항
- git config(특히 user.email)는 절대 바꾸지 않는다 — NAS 컨테이너용 회사 이메일 설정이 깨진다
- master 브랜치 포인터는 이 절차에서 전혀 건드리지 않는다 (cherry-pick 대상이 github-mirror이지 master가 아님) — 7번에서 원래 위치인지 재확인하는 습관을 들이면 안전하다
- 3번 단계를 건너뛰고 바로 git cherry-pick github/main..master 같은 범위 명령을 쓰면 위에서 겪은 대량 오탐(386개 vs 실제 3개)이 재현될 수 있다
자주 헷갈리는 부분들
- git log 실행했는데 화면이 멈춘 것 같을 때: git log는 기본적으로 pager(보통 less)로 결과를 연다. 화면이 멈춘 게 아니라 pager 안에 들어가 있는 것.
- 나가려면 q
- 위/아래 스크롤은 방향키 또는 스페이스바
- 검색은 /
- pager 없이 그냥 쭉 출력만 보고 싶으면 --no-pager를 붙이면 된다: git --no-pager log --format='%h %ae %s' github/main..github-mirror
- github-mirror, 백업 브랜치들은 삭제할 필요 없음. 로컬에만 있는 브랜치라 다음에 GitHub 올릴 때 다시 쓰면 된다. 다른 사람이 회사 서버에서 pull/clone해도 이 브랜치들은 보이지 않는다.
- 이미 커밋된 것만 골라서 push 가능. 지금 편집 중인(unstaged) 내용은 git stash로 치워두고, 새 커밋만 git cherry로 골라서 cherry-pick한 다음 다시 꺼내 쓰면 된다.
- 새 커밋 판별은 반드시 git cherry로. git log의 범위 비교(A..B)는 커밋 해시 기준이라, 과거에 filter-branch로 이메일을 바꾼 이력이 있으면 이미 올라간 커밋까지 전부 새 커밋으로 오탐한다. git cherry는 커밋의 실제 변경 내용을 비교하기 때문에 이 문제가 없다.
- GitHub noreply 이메일 찾는 법: GitHub 계정 설정(Settings → Emails)에서 "Keep my email addresses private"를 켜면 숫자+아이디@users.noreply.github.com 형태로 발급된다. + 포함 전체 문자열을 그대로 써야 한다.
왜 매번 까먹는가 — 그리고 그래서 이 글을 쓴다
이 절차 자체가 "평소엔 안 쓰다가 GitHub에 올릴 때만" 필요한 작업이라 텀이 길고, 그래서 매번 명령어를 다시 찾아보게 된다. 다음엔 이 글을 보면 된다.
'IT > 작업기록' 카테고리의 다른 글
| [작업 기록] POP3 메일 체크 스크립트, 계정별 복사 대신 config로 관리하기 (0) | 2026.08.06 |
|---|---|
| [Docker] WeasyPrint 시스템 의존성, Dockerfile 없는 구조에서 어떻게 설치하나 (0) | 2026.08.05 |
| [Claude Code] 운영 서버에 직접 쓰기 작업을 하려니 자동 승인이 막혔다 (0) | 2026.08.05 |
| [Linux] rm -rvf가 아무 일도 안 했던 이유 — 대상을 빼먹었다 (0) | 2026.08.05 |
| [Git CI] pre-receive의 비밀키 복사 코드, 왜 필요한지 헷갈렸던 것 바로잡기 (0) | 2026.08.04 |