2026년 6월 8일
GitDeveloper ToolsProductivity

Git 기본값이 당신의 시간을 낭비시키고 있다

매일의 짜증을 없애주는 전역 git 설정 11개와 alias 20개: 업스트림 브랜치, 머지 노이즈, 아이덴티티 혼선, 반복되는 리베이스 충돌까지, git이 꺼둔 채로 출시한 기능들.

8 분 읽기

내가 모든 머신에서 돌리는 git 설정을 공개한다, 전역 설정 11개와 alias 20개, 각각이 특정한 일상적 짜증을 없애기 위해 존재한다. 전부 가져다 써도 좋다.

얼마 전, 동료가 내가 새 브랜치를 푸시하는 걸 보고 나를 멈춰 세웠다.

"잠깐, 그게 어떻게 그냥 됐어? --set-upstream 안 붙였는데?"

설정 한 줄이었다. 그는 몇 년째 그 우회법을 손으로 치고 있었다.

그 대화가 이 글을 쓰게 된 이유다. 대부분의 개발자는 git을 공장 초기값으로 쓴다, 그리고 git의 공장 초기값은 당신을 위해 설계된 게 아니다. 호환성을 위해 설계됐다. git은 한 번 당신을 놀라게 하느니 천 번 방해하는 쪽을 택한다.

그래서 모두가 조용히 같은 세금을 낸다. 이제는 대부분 눈치도 못 챈 채로.

  • fatal: The current branch has no upstream branch, 하도 많이 쳐서 근육 기억이 된 해결법
  • 평범한 pull이 머지를 해버려서 히스토리를 더럽히는 머지 커밋
  • 맥 프로젝트마다 git status에 나타나는 .DS_Store
  • 다섯 번째로 똑같은 리베이스 충돌을 또 푸는 일
  • 개인 이메일로 회사 저장소에 커밋하는 일

이 모든 것은 git이 이미 갖고 있지만 꺼둔, 한 줄짜리 해결법이다.

git 공장 초기값의 일상적 세금: 각 짜증과 그 한 줄 해결법

지금부터 소개할 건 내 실제 설정이다, 모든 머신에 나와 함께 다니는 그 설정. git이 지원하는 모든 걸 덤프해놓은 게 아니다. 여기 있는 한 줄 한 줄은 실제 짜증을 없애서 자리를 얻었다. 2막 구성이다. 먼저 전역 설정, git의 동작 자체를 어디서나 바꾸니까. 그다음 alias, 그걸 얼마나 빠르게 다룰 수 있는지를 바꾸니까.

🪪 1막: 아이덴티티, 당신을 곤란하게 만들 수 있는 설정

결과가 따르는 설정부터 시작하자.

git config --global user.name "Paurush Rai"
git config --global user.email "personal@email.com"

당연한 얘기다. 하지만 대부분의 개발자가 절대 설정하지 않는 부분이 있다. 자동 업무/개인 라우팅이다.

나는 회사 코드를 ~/Developer/company/ 아래에 둔다. ~/.gitconfig에 블록 하나면 된다.

[includeIf "gitdir:~/Developer/company/"]
    path = ~/.gitconfig-work

그리고 ~/.gitconfig-work에는 딱 하나만 들어 있다.

[user]
    email = work@company.com

저장소가 어디 있는지에 따라 git 아이덴티티를 자동으로 라우팅하는 includeIf

이제 아이덴티티는 저장소가 어디 있는지로 결정된다. company/ 안에 뭐든 클론하면 → 자동으로 업무 이메일. 그 외 모든 곳은 → 개인 이메일. 기억할 필요도, 저장소별 설정도, 회사 감사 로그에 개인 이메일이 찍히는 일도 없다, 주말 사이드 프로젝트에 업무 이메일이 찍히는 일도 없다.

(work 파일에 없는 걸 눈여겨보라. 이름이다. includeIf는 전역 설정 위에 레이어로 얹히므로, work 파일은 달라지는 부분, 이메일, 만 선언한다. 나머지는 전부 상속된다.)

이게 보이는 것보다 중요한 이유는, 커밋 이메일이 영구적이기 때문이다. 잘못된 아이덴티티로 푸시하면 영원히 히스토리에 남는다. GitHub는 그 이메일을 소유한 계정에게 커밋을 귀속시킨다. 아이덴티티는 저장소의 속성이어야지, 마지막으로 기억해서 입력한 무언가의 속성이어서는 안 된다.

⚙️ 1막 계속: 동작 설정들

11줄. 각각 특정하고 반복되는 짜증 하나를 없앤다.

"no upstream branch"를 다시는 보지 않기

git config --global push.autoSetupRemote true

모든 개발자가 외워버린 그 에러, fatal: The current branch has no upstream branch, 는 git이 당연한 일을 해도 되는지 허락을 구하기 위해 존재한다. 이 설정은 그 허락을 영구적으로 내준다. 새 브랜치에서의 첫 푸시가 그냥 된다. (이게 내 동료를 말문 막히게 한 그 줄이다.)

뜻하지 않은 머지 커밋 생성 멈추기

git config --global pull.rebase true

기본값 git pull은 fetch + merge다, 그래서 "Merge branch 'main' of github.com..." 같은 커밋들이 히스토리를 도배하게 된다. 이 설정을 하면 pull이 도착한 것 위에 로컬 커밋을 재생(replay)한다. 선형적인 히스토리, 노이즈 없음.

새 저장소가 main에서 시작하게 만들기

git config --global init.defaultBranch main

이게 없으면 모든 git init이 master에서 시작하고 나중에 이름을 바꿔야 한다. 한 줄이면 다시는 신경 쓸 필요 없다.

죽은 브랜치 쌓아두지 않기

git config --global fetch.prune true

리모트에서 브랜치가 삭제되면(대부분 머지된 PR), 로컬에 남은 origin/그브랜치 사본은 영원히 남아있는다. 이 설정은 fetch할 때마다 오래된 참조를 자동으로 지운다. 브랜치 목록이 계속 정직하게 유지된다.

.DS_Store를 모든 저장소에서 영원히 추방하기

git config --global core.excludesfile ~/.gitignore_global
echo ".DS_Store" > ~/.gitignore_global

전역 ignore 파일은 각 저장소 자체의 .gitignore 위에 추가로 적용된다. macOS 부산물, 에디터 스왑 파일 등을 프로젝트마다가 아니라 머신 전체에서 한 번에 처리한다.

충돌 해결의 삼위일체

git config --global merge.conflictstyle zdiff3
git config --global rerere.enabled true
git config --global rebase.autostash true

함께 작동하며 충돌 해결을 바꿔놓는 설정 세 가지다.

zdiff3는 충돌 마커에 세 번째 섹션을 더한다, 양쪽이 시작한 원본 텍스트다. 표준 마커는 "내 것"과 "상대 것"만 보여주고 의도를 추측하게 만든다. 공통 조상을 보는 순간, 추측이 읽기로 바뀐다.

공통 조상을 함께 보여주는 zdiff3 충돌 마커

rerere("reuse recorded resolution")는 11개 중 숨은 히트작이다. git이 당신이 각 충돌을 어떻게 해결했는지 기록하고, 같은 충돌이 다시 나타나면(리베이스는 충돌을 반복하는 걸 좋아한다) 그 해결법을 자동으로 재생한다. 다섯 번째로 똑같은 충돌은 스스로 해결된다.

autostash는 "cannot rebase: you have unstaged changes" 춤을 없애준다. git이 작업 내용을 스태시하고, 리베이스하고, 복원한다. 하던 일이 그대로 남는다.

삶의 질, 두 줄

git config --global diff.algorithm histogram
git config --global branch.sort -committerdate

Histogram은 기본값인 Myers 알고리즘보다 의미 있게 더 깨끗한 diff를 만든다. git이 관련 없는 줄들을 짝지어버리는 뒤섞인 블록이 줄어든다. 그리고 브랜치를 최근 활동순으로 정렬하면 git branch가 알파벳순 고고학이 아니라 실제로 작업 중인 것을 먼저 보여준다.

⌨️ 2막: alias들

설정은 git의 동작을 바꾼다. alias는 당신의 속도를 바꾼다. 나는 엄선한 20개를 유지한다, 무엇을 아껴주는지에 따라 그룹으로 묶었다.

20개의 git alias를 일상 주력, 명확하게 보기, 겁 없이 되돌리기, 프로 기술로 나눈 모습

일상 주력들

st     = status -sb
cm     = commit -m
sw     = switch
co     = checkout
amend  = commit --amend --no-edit

status -sb는 짚고 넘어갈 만하다. 두 줄짜리 status다. 브랜치 상태와 변경된 파일, 몇 년 전부터 안 읽는 조언 문단은 없다.

명확하게 보기

lg     = log --oneline --graph --decorate -20
last   = log -1 HEAD --stat
d      = diff
ds     = diff --staged
whoami = !echo "$(git config user.name) <$(git config user.email)>"

git lg는 나의 "지금 어디쯤"이다, 최근 20개 커밋을 그래프로 그려준다. 그리고 git whoami는 1막의 마무리를 짓는다. 어떤 저장소에서든 실행하면 다음 커밋에 서명할 아이덴티티가 정확히 뭔지 출력한다. company/ 안에서는 업무 이메일을, 그 외에서는 개인 이메일을 보여준다. 명령어 한 번으로 검증된 신뢰.

겁 없이 되돌리기

unstage = restore --staged
undo    = reset --soft HEAD~1
wip     = !git add -A && git commit -m "wip: checkpoint"

undo는 아무것도 파괴하지 않고 커밋을 취소한다. 변경 사항은 다시 스테이징으로 돌아간다. wip는 위험한 수술 전에 모든 걸 스냅샷으로 남긴다. 대부분의 git 불안은 안전하게 되돌아가는 법을 모르는 데서 온다. 이것들이 바로 그 안전한 길이다.

프로 기술들

pf      = push --force-with-lease
fixup   = commit --fixup
ri      = rebase -i --autosquash
cleanup = !git branch --merged | grep -vE "^\*|main|master" | xargs git branch -d

pf가 중요한 것이다. --force-with-lease는 리모트가 내가 마지막으로 본 상태 그대로일 때만 강제 푸시한다, 그 사이 도착한 동료의 작업을 물리적으로 덮어쓸 수 없다는 뜻이다. 순수한 --force가 더 나은 선택인 상황은 없다. 이걸 alias로 만들어두면 내 손가락은 위험한 버전을 절대 치지 않는다.

fixup과 ri 조합은 깨끗한 히스토리 워크플로다. 이전 커밋을 겨냥한 수정 커밋을 만들고, 인터랙티브 리베이스 한 번이면 모든 걸 자동으로 접어 넣는다.

🎯 이걸 영구적으로 만드는 부분

여기 설정에 관한 진실이 있다. 만드는 건 쉽다. 유지하는 게 진짜 문제다. 지금 쓰는 머신에만 있는 설정은, 다음 머신에서 기억을 더듬어 다시 만들어야 할 설정이다.

내 ~/.gitconfig는 그냥 파일이 아니다. 변경이 일어나는 순간 자동으로 커밋하고 푸시하는 dotfiles 저장소로의 심링크다. 최근에 alias 하나를 추가했더니, 백그라운드 에이전트가 내가 테스트를 끝내기도 전에 그걸 GitHub에 커밋해놓았다.

(심링크와 launchd 에이전트로 이뤄진 그 시스템, cron도, 서드파티 도구도 없이, 은 따로 정리해둔 별도의 이야기다.)

결과는 이렇다. 아이덴티티 라우팅과 alias 20개를 포함한 이 설정 전체가, install.sh 하나로 어느 머신에든 안착한다. 한 번 설정하면 영원히 유지된다.

📋 전체 내용, 복사-붙여넣기 가능

# 아이덴티티 (여기 수정!)
git config --global user.name "Your Name"
git config --global user.email "you@personal.com"
 
# 동작
git config --global init.defaultBranch main
git config --global push.autoSetupRemote true
git config --global pull.rebase true
git config --global fetch.prune true
git config --global core.excludesfile ~/.gitignore_global
echo ".DS_Store" > ~/.gitignore_global
git config --global merge.conflictstyle zdiff3
git config --global rerere.enabled true
git config --global rebase.autostash true
git config --global diff.algorithm histogram
git config --global branch.sort -committerdate
 
# alias
git config --global alias.st "status -sb"
git config --global alias.cm "commit -m"
git config --global alias.sw "switch"
git config --global alias.co "checkout"
git config --global alias.amend "commit --amend --no-edit"
git config --global alias.lg "log --oneline --graph --decorate -20"
git config --global alias.last "log -1 HEAD --stat"
git config --global alias.d "diff"
git config --global alias.ds "diff --staged"
git config --global alias.unstage "restore --staged"
git config --global alias.undo "reset --soft HEAD~1"
git config --global alias.wip '!git add -A && git commit -m "wip: checkpoint"'
git config --global alias.pf "push --force-with-lease"
git config --global alias.fixup "commit --fixup"
git config --global alias.ri "rebase -i --autosquash"
git config --global alias.cleanup '!git branch --merged | grep -vE "^\*|main|master" | xargs git branch -d'
git config --global alias.root "rev-parse --show-toplevel"
git config --global alias.aliases "config --get-regexp ^alias"
git config --global alias.whoami '!echo "$(git config user.name) <$(git config user.email)>"'

거기에 업무 코드를 전용 디렉토리에 둔다면 아이덴티티 라우팅까지.

git config --global includeIf."gitdir:~/Developer/company/".path ~/.gitconfig-work
printf '[user]\n    email = you@work.com\n' > ~/.gitconfig-work

교훈

이 설정들 하나하나는 단독으로는 인상적이지 않다. 그게 핵심이다.

git의 기본값은 아무도 놀라게 하지 않는 걸 최적화한다. 그 결과 모두를 방해한다. 위의 각 줄은 반복되는 방해 하나를 침묵으로 바꾼다, 그리고 침묵은 쌓인다. 앞으로 만질 모든 저장소에 걸쳐 아낀 몇 초와 피한 잘못된 이메일 커밋을 곱해보면, 이 30분짜리 설정 작업은 도구에 쓸 수 있는 시간 중 가장 레버리지 높은 축에 든다.

내 동료는 그걸 본 바로 그날 오후에 push.autoSetupRemote를 설정했다. 몇 년째 치고 있던 우회법이 한 줄로 사라졌다, 그게 선택 사항이었다는 걸 깨닫는 데 필요했던 건, 누군가 그 세금을 내지 않는 걸 보는 것뿐이었다.

이 글을 그 순간의 문서화된 버전이라고 생각해달라. cat ~/.gitconfig를 쳐서 지금 뭐가 들어 있는지 보라.

기본값은 호환성을 위한 것이다. 설정은 당신을 위한 것이다.

당신의 gitconfig엔 뭐가 있나

나는 늘 다음 한 줄짜리 해결법을 찾아다닌다. 자리를 얻어낸 설정이나 alias가 있다면, 그게 바로 내가 지금 것들의 절반을 찾아낸 방법이다.