포크 워크플로에서 원격 이름은 관례로 고정되어 있습니다.
| 원격 이름 | 가리키는 곳 | 권한 |
|---|---|---|
origin |
내 계정의 포크 | push 가능 |
upstream |
원본 저장소 | 보통 읽기 전용 |
git clone 은 자동으로 origin 만 등록합니다. upstream 은 clone 뒤 직접 git remote add 로 추가해야 합니다.
GitHub 웹의 Fork 버튼은 서버 쪽에서 저장소를 그대로 복사해 내 계정 아래 새 저장소를 만듭니다. 브랜치·태그·커밋 이력이 전부 그대로 옮겨집니다. 폐쇄망에는 GitHub 서버가 없으므로, git clone --bare 로 원본을 통째로 복사해 같은 결과(모든 이력을 가진 새 저장소)를 로컬에서 재현합니다.
내 포크를 clone 하면 origin 은 자동으로 잡히지만 원본 주소는 알 수 없습니다. 다음 명령으로 직접 추가합니다.
git clone <내 포크 주소> 작업폴더
cd 작업폴더
git remote add upstream <원본 주소>
git remote -vgit remote -v 로 origin 과 upstream 두 줄이 각각 fetch·push 주소와 함께 보이면 성공입니다.
일반적인 기여 절차는 다섯 단계로 요약됩니다.
main 에서 작업용 브랜치를 만듭니다.origin)에 push 합니다.upstream 에는 절대 직접 push 하지 않습니다. push 권한이 없기도 하지만, 권한이 있어도 리뷰 없이 바로 반영되는 것을 막기 위해서입니다.
프로젝트 루트의 CONTRIBUTING.md 는 기여자가 지켜야 할 규칙을 담습니다. 보통 이슈 확인 절차, 커밋 메시지 형식, 테스트 실행 방법, PR 크기 권장사항을 포함하므로, PR 을 열기 전에 먼저 읽어야 합니다. 규칙을 어긴 PR 은 리뷰 전에 반려되기 쉽습니다.
LICENSE 파일은 코드를 어떤 조건으로 쓸 수 있는지 정합니다. 라이선스가 없는 저장소의 코드는 기본적으로 복사해 쓸 수 없다고 가정해야 합니다. CODE_OF_CONDUCT.md 는 소통 규범이며, 위반 시 기여 권한이 제한될 수 있다는 점을 명시하는 프로젝트가 많습니다.
DCO(Developer Certificate of Origin)는 "이 코드를 내가 작성했거나 낼 권리가 있다" 는 선언입니다. git commit -s 를 쓰면 커밋 메시지 끝에 Signed-off-by: 이름 <이메일> 줄이 자동으로 붙습니다.
git commit -s -m "fix: 버그 수정"CLA(기여자 라이선스 동의서)와는 다릅니다. CLA 는 별도 서명 절차가 있는 법적 동의서이고, DCO 는 커밋마다 붙는 한 줄 선언입니다. 두 방식 중 하나만 요구하는 프로젝트가 대부분입니다.
내가 브랜치에서 작업하는 동안 원본(upstream)에는 다른 사람의 PR 이 계속 병합됩니다. 내 포크(origin)는 그 변경을 자동으로 받지 않으므로 시간이 지날수록 뒤처지고, 뒤처진 포크에서 새 브랜치를 만들면 나중에 PR 을 열 때 관련 없는 충돌이 늘어납니다.
동기화의 기본 순서는 git fetch upstream 으로 원본의 최신 커밋을 받은 뒤, 내 main 을 그 위로 맞추는 것입니다.
| 상황 | 명령 | 결과 |
|---|---|---|
| main 에 내 커밋이 없을 때 | git merge --ff-only upstream/main |
fast-forward, 이력 그대로 |
| main 에 내 커밋이 있을 때 | git rebase upstream/main |
내 커밋이 뒤로 옮겨짐 |
포크의 main 브랜치는 보통 직접 커밋하지 않고 upstream 을 그대로 따라가므로 --ff-only 로 충분합니다.
main 을 동기화한 뒤에는 작업 중인 브랜치도 그 위로 옮깁니다.
git switch fix/9-typo
git rebase main
git push --force-with-lease origin fix/9-typorebase 는 커밋 해시를 바꾸므로 일반 push 는 거부됩니다. --force 대신 --force-with-lease 를 쓰면 내가 마지막으로 받은 상태와 원격이 다를 때 거부되어, 다른 사람의 push 를 실수로 덮어쓰지 않습니다.
유지보수자는 내 포크의 브랜치를 직접 원격으로 추가해 fetch 하고, 자기 클론에서 병합합니다. GitHub 에서는 "Merge pull request" 버튼 하나로 이 과정이 자동화됩니다. 병합이 끝나면 내 PR 의 커밋은 upstream/main 에 들어가지만 내 포크는 아직 모르므로, 다시 fetch upstream 하고 동기화한 뒤 다 쓴 브랜치를 포크에서 삭제합니다.
gh 는 GitHub 공식 커맨드라인 도구로, 웹 화면 없이 포크·PR·이슈를 다룰 수 있습니다.
| 명령 | 역할 |
|---|---|
gh repo fork <저장소> --clone |
포크와 clone 을 한 번에 |
gh pr create --base main --head 계정:브랜치 |
PR 생성 |
gh pr checkout <PR 번호> |
PR 브랜치를 로컬로 |
폐쇄망에는 GitHub 서버가 없어 gh 를 실제로 실행할 수 없습니다. 이 레슨의 예제는 명령만 텍스트로 소개하고 실행하지 않습니다.