1 개요
GitHub에서 타인의 저장소를 복사해 내 계정에 독립적으로 관리하는 것을 포크(fork)라고 한다. 포크는 오픈소스 기여, 실험적 수정, 또는 참고용 사본 보관에 사용된다.
이 포스트에서는 포크 생성 방법과 원천 저장소의 변경사항을 내 포크에 반영하는 동기화 전략을 정리한다.
2 gh CLI vs git CLI
포크를 다루기 전에 두 CLI의 역할 차이를 명확히 해야 한다.
| 도구 | 역할 | 주요 명령어 |
|---|---|---|
git |
로컬 버전 관리 | commit, push, pull, merge |
gh |
GitHub API 상호작용 | repo fork, pr create, issue list |
포크는 GitHub 플랫폼 기능이다. 저장소를 복사하는 작업은 GitHub 서버에서 일어나기 때문에 로컬 버전 관리 도구인 git으로는 처리할 수 없다. gh CLI가 GitHub API를 호출하여 이 작업을 수행한다.
3 저장소 포크하기
3.1 gh CLI 사용 (권장)
✓ Created fork my-username/repo
✓ Created fork my-username/repo
Cloning into 'repo'...
remote: Enumerating objects: 512, done.
remote: Counting objects: 100% (512/512), done.
Receiving objects: 100% (512/512), 1.23 MiB | 3.45 MiB/s, done.
✓ Cloned fork
포크가 완료되면 내 포크 URL이 출력되고 바로 클론까지 완료된다.
4 포크와 원천 저장소의 관계
포크한 저장소는 자동으로 동기화되지 않는다.
원천 저장소(upstream)에 새로운 커밋이 쌓여도 내 포크는 그 시점의 스냅샷에 그대로 머문다. GitHub는 내 포크 페이지에서 “X commits behind”로 이 상태를 표시한다.
동기화는 세 가지 방법으로 수행할 수 있다.
5 동기화 방법
5.1 방법 1 — GitHub 웹 UI
내 포크 저장소 페이지에서 “Sync fork” 버튼을 클릭한다. 충돌이 없으면 즉시 반영되고, 충돌이 있으면 병합 방법을 선택해야 한다.
5.2 방법 2 — gh CLI
✓ Synced the "my-username/repo" repository
충돌이 없으면 한 줄 출력으로 완료된다. --force 사용 시:
✓ Force synced the "my-username/repo" repository
5.3 방법 3 — git 명령어
로컬 클론이 있는 경우, upstream 리모트를 등록하고 직접 병합한다.
# 1. 원천 저장소를 upstream으로 등록 (최초 1회)
git remote add upstream https://github.com/original-owner/repo.git
# 2. upstream의 최신 커밋 가져오기
git fetch upstreamFrom https://github.com/original-owner/repo
* [new branch] main -> upstream/main
* [new branch] develop -> upstream/develop
[new branch] 줄이 나타나면 upstream의 브랜치 정보가 로컬에 등록된 것이다.
Updating abc1234..f7e2a9b
Fast-forward
README.md | 5 +++++
src/app.py | 10 ++++++++++
2 files changed, 15 insertions(+)
Total 3 (delta 1), reused 0 (delta 0), pack-reused 0
To https://github.com/my-username/repo.git
abc1234..f7e2a9b main -> main
git remote -v로 리모트 목록을 확인하면 origin(내 포크)과 upstream(원천)이 모두 등록된 것을 볼 수 있다.
origin https://github.com/my-username/repo.git (fetch)
origin https://github.com/my-username/repo.git (push)
upstream https://github.com/original-owner/repo.git (fetch)
upstream https://github.com/original-owner/repo.git (push)
6 Merge Conflict 처리
내 포크와 원천 저장소가 같은 파일의 같은 위치를 각각 수정한 경우 merge conflict가 발생한다.
Auto-merging src/config.py
CONFLICT (content): Merge conflict in src/config.py
Automatic merge failed; fix conflicts and then commit the result.
충돌 파일을 열어 <<<<<<<, =======, >>>>>>> 마커를 찾아 직접 수정한 후 커밋한다.
오픈소스 기여 시 upstream과 내 포크의 수정 범위가 겹치지 않도록 브랜치를 분리하는 것이 충돌을 예방하는 가장 효과적인 방법이다.
7 정리
| 상황 | 권장 방법 |
|---|---|
| 포크만 생성 (로컬 클론 불필요) | gh repo fork owner/repo --clone=false |
| 포크 생성 + 로컬 작업 | gh repo fork owner/repo --clone=true |
| 로컬 없이 upstream 동기화 | gh repo sync 또는 웹 UI “Sync fork” |
| 로컬에서 세밀한 병합 제어 | git remote add upstream + git fetch + git merge |
포크 이후 upstream과 오래 멀어질수록 충돌 가능성이 높아진다. 주기적인 동기화 또는 작업 단위로 upstream을 반영하는 습관이 중요하다.