git pull
Fetch properties and merge them with another repository or a local branch
— Git 공식 매뉴얼(git-pull Manual Page)
"출근해서 아무 생각 없이 이 명령어 입력했다가 오전 업무가 통째로 증발했다." 제발 충돌 나지 말고 조용히 넘어가게 해주세요 신이시여
1. 개요
Git에서 원격 저장소의 최신 변경 사항을 다운로드하여 현재 작업 중인 로컬 브랜치에 곧바로 병합(Merge)하는 명령어이다. 실상은 git fetch와 git merge를 한 데 묶어놓은 편의용 매크로에 가깝다. 동료들과 협업할 때 내 코드의 타임라인을 세상의 흐름과 동기화하는 가장 빠른 방법이지만, 동시에 평화롭던 내 작업 공간에 Merge Conflict라는 시한폭탄을 투하하는 주범이기도 하다.(...)
2. 출근길의 동기화 의식, 그리고 기습 숭배
현대적인 소프트웨어 개발 프로세스에서 아침에 출근한 개발자들이 가장 먼저 실행하는 명령어 중 하나이다. 밤새 다른 동료들이 GitHub 등의 원격 저장소에 반영해 둔 아름다운(?) 변경 사항들을 내 PC로 고스란히 끌어오는 역할을 수행한다. 이 과정이 아무 문제 없이 패스트 포워드(Fast-Forward)로 끝나면 그날 하루는 매우 상쾌하게 시작된다. 그러나 내가 수정한 부분과 동료가 수정한 부분이 단 한 줄이라도 겹치는 순간, 터미널은 시뻘건 경고창과 함께 Merge Conflict의 시작을 알린다. 그리고 개발자는 조용히 자리를 박차고 일어나 담배를 피우러 간다.1
3. 내부 동작: Fetch와 Merge의 야합
많은 입문자들이 git pull을 단일 동작으로 오해하지만, 내부적으로는 원격의 메타데이터를 얌전하게 긁어오는 git fetch를 먼저 실행한 뒤, 곧바로 내 로컬 헤드(HEAD)에 그것들을 비벼버리는 git merge가 순차적으로 실행되는 이중 구조를 취하고 있다. 이 때문에 히스토리가 심하게 꼬여 있는 상태에서 무작정 pull을 땡기면, 정체불명의 머지 커밋(Merge Commit)들이 거미줄처럼 뒤엉키며 프로젝트 그래프가 지하철 노선도를 방불케 하는 대참사가 벌어진다. 이를 방지하기 위해 숙련된 개발자들은 git pull --rebase 옵션을 사용하여 히스토리를 한 줄로 이쁘게 다듬는 작업을 선호하기도 한다.2
4. 실제 사용 예시
원격 브랜치의 최신 변경을 가져와 현재 브랜치에 반영하는 기본 흐름이다. 내부적으로는 가져오기와 병합이 한 번에 일어난다.
git switch main
git pull origin main
불필요한 merge commit을 피하고 싶다면 rebase 방식이나 fast-forward만 허용하는 방식을 선택한다. 팀 규칙에 맞춰 하나로 통일하는 편이 좋다.
git pull --rebase origin main
git pull --ff-only origin main
5. 관련 밈 및 드립
5.1. Git Pull Before Push (강제 규율)
수정본을 신나게 git push하려다 거부당하고 '아 맞다 풀 안 땡겼지' 하고 아무 생각 없이 git pull을 입력했다가, 로컬에서 공들여 작성했던 소스 코드의 절반이 머지 충돌과 함께 꼬이면서 뇌정지가 오는 현상. 주니어 개발자들이 하루에 한 번씩 겪는 통과의례로 불린다.
6. 여담
- --rebase의 강제화: 일부 깐깐한 기업의 협업 컨피그레이션에서는 아예
git config --global pull.rebase true를 기본값으로 박아두어 히스토리가 더러워지는 것을 원천 차단하기도 한다.(...) - Stash와의 연계: 수정한 코드를 커밋하지 않고 그냥 풀을 땡기려고 하면 깃이 '야, 니 코드 날아가니까 빨리 정리해'라며 단호하게 거절한다. 이때 수줍게
git stash로 코드를 구석에 처박아두고 풀을 땡긴 뒤 다시 꺼내는 것이 국룰 테크닉이다.