Git에서 말하는 Origin은 절대경로가 아니다.
오늘 세무 업무와는 전혀 상관없는 곳에서, 아주 좋은 공부를 하나 했다. 운영 중인 웹사이트 서버를 정리하다가 우연히 마주친 해프닝인데, 파고들어보니 git의 origin이라는 개념을 제대로 이해하는 데 이만한 실전 사례가 없다 싶어서 기록으로 남긴다.
#git#origin#바이브코딩#인프라정리
1. 발단 — “로컬에서 커밋만 하고 푸시는 안 해도 될까?”
운영 중인 홈페이지의 UI를 손보다가, 사소한 질문 하나를 던졌다. “지금 로컬에서 커밋만 하고 GitHub에 푸시는 안 해도 되나?” 돌아온 답이 흥미로웠다.
처음엔 이 말이 무슨 뜻인지 감이 안 왔다. “서버 git도 커밋해달라”고 시켰더니 별문제 없이 서버에서도 커밋이 됐다. 그런데 뭔가 이상했다. 로컬 커밋 해시와 서버 커밋 해시가 서로 다르다는 것이다. 분명 같은 파일, 같은 내용인데 왜 서로 다른 “이력”을 갖고 있는 걸까?
2. 먼저 origin이 뭔지부터 — 우체통 비유
git에서 origin은 사실 아무 의미도 없는 이름표다. “이게 내 주 원격 저장소야”라고 스스로 붙인 별명일 뿐이라, 실제로 어디를 가리킬지는 완전히 자유다. GitHub 주소를 가리킬 수도 있고, 서버 안의 로컬 파일을 가리킬 수도 있다.
문제는 여러 컴퓨터가 협업하는 구조에서 생긴다. 로컬PC와 서버가 진짜로 “같은 히스토리”를 공유하려면, 둘의 origin이 같은 곳을 가리키고 있어야 한다.
그림 1. origin이 같은 곳(GitHub)을 보면 협업이 되고, 다른 곳을 보면 겉보기엔 똑같이 동작해도 실제로는 서로 무관한 두 개의 역사가 쌓인다.
3. 왜 서버만 딴 곳을 보고 있었나 — 4단계로 재구성한 전말
Claude Code와 함께 서버를 뒤져본 결과, 원인은 “처음엔 GitHub 저장소가 없었다”는 아주 단순한 사실에서 출발한 것으로 드러났다. 시간 순으로 재구성하면 이렇다.
그림 2. “GitHub 없이 시작 → 나중에 GitHub 생성 → 로컬만 전환 → 서버는 방치”라는 흐름이 오늘 해프닝의 근본 원인이었다.
/root/.ssh/를 뒤져보니 두 달 전쯤 생성된 배포 전용 SSH 키가 이미 존재했다. GitHub Deploy Keys 목록에도 지문이 똑같은 키가 등록되어 있었다. 즉, 과거의 나(혹은 과거 세션)가 오늘과 똑같은 전환 작업을 한 번 시도했다가, 키만 만들고 GitHub 등록까지 하고서 실제 연결은 마무리 짓지 않고 멈췄던 것이다. 미스터리를 풀어보니 결국 “내가 예전에 벌여놓고 잊어버린 일”이었다는 게 이 해프닝의 반전 포인트였다.
4. 왜 이게 “겉보기엔” 문제없이 굴러갔나
가장 헷갈렸던 지점은 바로 이거였다. 서버 origin이 잘못돼 있어도, 배포는 몇 달간 아무 문제 없이 잘 됐다. 어떻게 그럴 수 있었을까?
이유는 배포 스크립트(deploy-to-server.ps1류의 배포 자동화 스크립트)가 애초에 git의 push/pull 기능을 아예 쓰지 않는 구조였기 때문이다.
그림 3. git의 이력 관리 기능을 안 쓰고 파일 복사로만 배포했기 때문에, origin이 잘못돼 있어도 티가 안 났다. 이게 이 해프닝이 오래 안 들킨 이유다.
5. 전환 — “서버는 pull만 하면 되는” 구조로
정상적인 구조라면 이래야 한다. 로컬에서 커밋하고 push하면, 서버는 그저 git pull 한 줄로 GitHub의 최신 상태를 그대로 받아오면 된다. 별도의 파일 복사도, 서버 자체 커밋도 필요 없다.
전환 후: 로컬(커밋+push) → 서버(
git pull만) — 파일 내용도, 커밋 해시도 완전히 일치
다만 origin 주소만 GitHub로 바꾼다고 끝나는 게 아니었다. 서버가 그동안 쌓아온 독자적인 커밋들이 있어서, 곧바로 pull하면 충돌이 날 수 있었다. 그래서 다음 순서를 밟았다.
- 안전 확인 — 서버가 추적하던 파일 80개 전체를 GitHub와 blob 해시(내용 지문)로 대조 → 100% 일치 확인. 즉 이력만 다를 뿐 내용 손실 위험은 없다는 게 증명됨
- 백업 브랜치 보존 — 혹시 모를 상황을 대비해 서버의 기존 이력을
backup/pre-pull-migration브랜치로 남겨둠 - origin 교체 — 서버 origin을 번들 파일에서 실제 GitHub 주소(SSH)로 변경, 저장소 전용 배포키(Deploy Key)로 인증 연결
- 이력 정렬 —
git reset --hard origin/main으로 서버를 GitHub와 완전히 동일한 커밋으로 맞춤 - 배포 스크립트 재작성 — scp+파일복사 방식을
git fetch && merge --ff-only방식으로 전면 교체
그림 4. 로컬 · GitHub · 서버 세 곳의 커밋 해시가 완전히 하나로 통일된 최종 구조.
6. 오늘의 교훈
돌아보니 이번 건이 처음이 아니었다. 사무실과 집, 두 군데에서 작업하다 배포 과정에서 겪었던 문제, 로컬에서 커밋·푸시는 했는데 서버가 fetch를 안 해서 생겼던 문제… 그리고 오늘처럼 “처음엔 GitHub 없이 시작했다가 중간에 저장소를 만들면서” 생긴 문제까지. 1인 개발 체제로 인프라를 하나씩 늘려가다 보면 자연스럽게 마주치는 성장통들인 것 같다.
- origin은 이름표일 뿐, 어디를 가리키든 자유다 — 그래서 여러 컴퓨터가 협업할 땐 반드시 “같은 곳”을 보게 맞춰줘야 한다
- 파일 내용이 같다고 이력까지 같은 게 아니다 — git에서는 “무엇이 담겨있나”만큼 “어떤 경로로 여기까지 왔나”도 중요하다
- 겉보기에 잘 돌아간다고 구조가 옳은 건 아니다 — 파일 복사 기반 배포는 git의 이력 관리 기능을 우회했기 때문에 문제가 안 드러났을 뿐이다
- 미완성으로 남긴 작업은 반드시 흔적을 남긴다 — 두 달 전에 벌여놓고 잊었던 SSH 키 하나가 오늘 정확히 필요한 순간에 다시 나타났다
결국 오늘의 해프닝은 “origin”이라는, 알고 나면 별것 아닌 개념 하나가 왜 그렇게 중요한지를 몸으로 배우게 해준 사례였다. 세무 실무에서 법령 개정 히스토리를 추적하는 것과, 코드에서 커밋 히스토리를 추적하는 것 — 은근히 닮아 있다는 생각도 들었다. ^^