17. 포크(Fork)와 오픈소스 기여
🎯 이 장의 목표
- 포크가 무엇이고 협업자 방식과 어떻게 다른지 이해한다
- 포크한 저장소를 원본(upstream)과 동기화한다
- 포크에서 변경을 만들어 원본에 PR을 보낸다
- 오픈소스 기여의 전체 흐름을 익힌다
17.1 포크란 무엇인가?
16장에서는 협업자(collaborator)로 초대받아야 저장소에 push할 수 있었습니다. 하지만 세상 모든 오픈소스 프로젝트가 나를 협업자로 초대해줄 리는 없습니다. 권한이 없는 남의 저장소에 어떻게 기여할까요?
포크(Fork)는 남의 저장소를 통째로 내 GitHub 계정으로 복사해오는 것입니다. 복사본은 완전히 내 것이라 마음대로 수정·push할 수 있고, 다 되면 원본에 "이 변경 받아주세요"라고 PR을 보냅니다.
flowchart LR
O["📦 원본 저장소<br/>octocat/repo<br/><small>권한 없음</small>"]
F["🍴 내 포크<br/>나/repo<br/><small>내 소유·자유 수정</small>"]
L["💻 내 로컬<br/><small>자유 작업</small>"]
O -- "Fork" --> F
F -- "clone" --> L
L -. "Pull Request<br/>(변경 받아달라 요청)" .-> O
classDef origin fill:#fee2e2,stroke:#dc2626,color:#991b1b
classDef fork fill:#fef3c7,stroke:#d97706,color:#92400e
classDef local fill:#dcfce7,stroke:#16a34a,color:#166534
class O origin
class F fork
class L local
포크 vs 협업자 — 무엇이 다른가?
| 협업자(Collaborator) | 포크(Fork) | |
|---|---|---|
| 권한 | 원본에 직접 push 가능 | 원본 권한 없음 |
| 작업 위치 | 원본 저장소의 브랜치 | 내 계정의 복사본 |
| 적합한 상황 | 같은 팀·회사 내부 | 오픈소스, 외부 기여 |
💡 팁
요약: 내부 팀원이면 협업자 방식, 외부에서 오픈소스에 기여하면 포크 방식.17.2 포크 만들기
- 기여하려는 GitHub 저장소 페이지에서 우측 상단 Fork 버튼 클릭
- 내 계정으로 복사본이 생성됨 (
내아이디/저장소명) - 그 포크를 로컬로 clone
BASH
git clone https://github.com/내아이디/저장소명.git cd 저장소명
또는 12장의 gh로 포크와 clone을 한 번에:
BASH
gh repo fork octocat/repo --clone
17.3 origin과 upstream — 두 개의 원격
포크를 clone하면 origin은 내 포크를 가리킵니다. 하지만 시간이 지나면 원본 저장소에 새 변경이 쌓입니다. 내 포크가 뒤처지지 않으려면 원본도 원격으로 등록해야 합니다. 관례적으로 이 원본을 upstream이라 부릅니다.
BASH
# 현재 원격 확인 (origin = 내 포크) git remote -v
CODE
origin https://github.com/내아이디/저장소명.git (fetch) origin https://github.com/내아이디/저장소명.git (push)
BASH
# 원본 저장소를 upstream으로 추가 git remote add upstream https://github.com/원본소유자/저장소명.git git remote -v
CODE
origin https://github.com/내아이디/저장소명.git (내 포크 - push 가능) upstream https://github.com/원본소유자/저장소명.git (원본 - 보통 읽기만)
flowchart LR
U["📦 upstream<br/>(원본)"]
L["💻 내 로컬"]
O["🍴 origin<br/>(내 포크)"]
U -- "fetch / pull" --> L
L -- "push" --> O
classDef up fill:#fee2e2,stroke:#dc2626,color:#991b1b
classDef local fill:#dcfce7,stroke:#16a34a,color:#166534
classDef ori fill:#fef3c7,stroke:#d97706,color:#92400e
class U up
class L local
class O ori
17.4 원본 변경 동기화하기
원본(upstream)에 새 커밋이 생겼을 때, 내 포크를 따라잡는 방법입니다.
BASH
# 1. 원본의 최신 변경 가져오기 git fetch upstream # 2. 내 main으로 이동 git switch main # 3. 원본 main의 변경을 내 main에 병합 git merge upstream/main # 4. 동기화된 내 main을 내 포크(origin)에도 반영 git push origin main
💡 팁
GitHub 포크 페이지에는 "Sync fork" 버튼이 있어, 웹에서 클릭 한 번으로 원본과 동기화할 수도 있습니다. 하지만 로컬에서 fetch upstream → merge를 직접 해보면 무슨 일이 일어나는지 명확히 이해됩니다.📌 핵심
기여 전 항상 동기화부터. 원본이 한참 앞서 있는 상태에서 작업하면 나중에 충돌이 잔뜩 납니다. 새 작업을 시작하기 전에 먼저 upstream과 동기화하는 습관을 들이세요.17.5 포크에서 기여하기 (전체 흐름)
오픈소스에 기여하는 표준 절차입니다.
BASH
# 0. (사전) 원본과 동기화 git fetch upstream git switch main git merge upstream/main # 1. 작업용 브랜치 생성 (main에서 직접 작업하지 않기!) git switch -c fix/typo-in-readme # 2. 변경 작업 후 커밋 # ... 파일 수정 ... git add . git commit -m "Fix typo in README" # 3. 내 포크(origin)에 브랜치 push git push -u origin fix/typo-in-readme
- 원본에 PR 보내기: GitHub의 내 포크 페이지에서 "Contribute → Open pull request"를 누르면, base는 원본 저장소, compare는 내 포크의 브랜치로 자동 설정됩니다. 설명을 적고 PR을 생성합니다.
BASH
# gh로도 가능 (12장)
gh pr create --repo 원본소유자/저장소명 --fill
- 원본 관리자가 리뷰 → 승인 → 병합. 내 변경이 원본에 반영되면 기여 완료! 🎉
⚠️ 흔한 실수
흔한 실수: main에서 직접 작업하지 마세요. 포크의 main은 원본과 동기화하는 용도로 깨끗이 두고, 모든 기여는 별도 브랜치에서 하세요. 그래야 동기화가 꼬이지 않고, 여러 기여를 동시에 진행할 수 있습니다.17.6 좋은 오픈소스 기여 매너
- CONTRIBUTING.md를 먼저 읽기: 많은 프로젝트가 기여 규칙을 문서로 둡니다.
- 작은 단위로 기여: 거대한 PR보다 명확한 작은 PR이 환영받습니다.
- 이슈 먼저 확인: 큰 변경은 PR 전에 이슈로 제안해 합의하는 게 예의입니다.
- 커밋 메시지·PR 설명을 정성껏: 관리자가 맥락을 이해해야 병합됩니다.
- 리뷰 피드백에 열린 태도: 수정 요청은 거절이 아니라 협업입니다.
17.7 이 장에서 배운 것 (요약)
- 포크 = 남의 저장소를 내 계정으로 복사 (권한 없이 기여하는 길)
- 협업자(내부) vs 포크(외부 오픈소스)
origin= 내 포크,upstream= 원본 (직접 추가해야 함)- 동기화:
git fetch upstream→git merge upstream/main→git push origin main - 기여: 동기화 → 브랜치 생성 → 커밋 → 포크에 push → 원본에 PR
- 포크의 main은 동기화용으로 깨끗이, 작업은 항상 별도 브랜치
✍️ 확인 문제
- 오픈소스 프로젝트에 권한 없이 기여하려면 협업자와 포크 중 무엇을 쓰나요?
origin과upstream은 각각 무엇을 가리키나요?- 포크에서 기여할 때 main에서 직접 작업하면 안 되는 이유는?
다음 장에서는 cherry-pick, squash, amend 등 한 단계 위의 고급 명령들을 모아 다룹니다. → 18_고급명령모음.md