사전 GitHub
구현체

GitHub

gabury1고친 사람 github-actions[bot]

GitHub 는 코드와 그 코드가 바뀐 기록을 인터넷에 맡아 두고 여러 사람이 함께 고치게 해 주는 서비스입니다. 각자 자기 컴퓨터에서 고친 코드를 이곳에 올리고 남이 올린 코드를 받아 옵니다. 합치기 전에 동료가 바뀐 줄을 읽고 의견을 남기는 일도 이 사이트에서 합니다.

쉽고 빠른 이해

GitHub 는 팀의 코드를 한곳에 맡아 두는 인터넷 창고입니다. 내가 고친 코드를 올리면 동료가 받아 가서 이어서 고칩니다.

창고가 없으면 각자 가진 코드가 서로 어긋납니다. 모두 같은 창고를 기준으로 받고 올리면 작업이 한곳에서 만납니다.

  1. 창고에서 코드를 받아 내 컴퓨터에서 고칩니다
  2. 고친 것을 올리고 합쳐 달라고 요청합니다
  3. 동료가 바뀐 줄을 읽고 승인하면 합칩니다

혼자서 한 컴퓨터에서만 고치는 코드라면 창고가 없어도 됩니다.

대가도 있습니다. 리뷰 댓글과 할 일 기록은 GitHub 서버에만 남습니다. 코드를 받아 와도 따라오지 않습니다. 아주 큰 파일은 올리지 못하게 막힙니다.

상세

GitHub 가 맡아 주는 것과 그 위에 덧붙인 것을 가릅니다. 프로젝트 하나와 그것을 함께 고치는 사람들을 놓고 봅니다. 코드가 놓이는 곳, 코드가 오가는 길, 합쳐지기 전에 읽는 사람을 차례로 짚습니다.

Git 과 GitHub

Git 은 파일이 바뀐 이력을 남기는 버전관리 프로그램입니다. 내 컴퓨터에 설치해서 씁니다. Git 을 쓰면 프로젝트의 내 사본에서 일할 수 있습니다. 바꾼 이력도 남습니다. 남이 바꾼 것과 안전하게 합칠 수도 있습니다.

이 이력을 담는 단위가 저장소입니다. 저장소에는 코드와 파일, 그리고 파일마다 바뀐 기록이 함께 들어 있습니다. 한 저장소를 여러 협업자가 함께 쓸 수 있습니다.

GitHub 는 Git 위에 서 있는 서비스입니다. 사람들의 Git 저장소를 클라우드에 맡아 둡니다. 그리고 팀이 함께 일하기 쉽도록 계획과 협업 도구를 그 위에 더합니다. 남의 코드를 읽고 의견을 주는 코드 리뷰와, 버그 제보나 할 일을 적어 두는 글인 이슈가 그런 도구입니다.

Git GitHub
무엇인가 버전관리 프로그램 Git 저장소를 맡아 두는 서비스
어디서 도나 내 컴퓨터 GitHub 의 서버
하는 일 이력 남기기 · 합치기 저장소 보관 · 코드 리뷰와 이슈 같은 협업 도구

저장소는 공개와 비공개로 나뉩니다. 공개 저장소는 인터넷의 누구나 볼 수 있습니다. 비공개 저장소는 나와 내가 직접 권한을 준 사람만 봅니다. 조직 계정의 저장소라면 정해진 조직 구성원도 봅니다.

원격 저장소와 주고받는 명령

커밋은 한 번에 고친 묶음을 이력에 남긴 단위입니다. 고친 내용이 커밋 하나로 묶여 이력에 쌓입니다.

내 컴퓨터가 아니라 GitHub 에 놓인 저장소를 원격 저장소라고 부릅니다. GitHub 에서 하는 협업은 내 저장소의 커밋을 원격 저장소에 올리는 데서 시작합니다. 올라간 커밋을 다른 사람이 보고, 받아 가고, 이어서 고칩니다.

기준이 되는 저장소가 없으면 각자 가진 사본이 서로 어긋납니다. 누구 것이 최신인지 따로 맞춰야 합니다. 모두 같은 원격 저장소를 기준으로 받고 올리면 작업이 한곳에서 만납니다. 원격 저장소를 상대로 쓰는 Git 명령은 이렇습니다.

터미널
git clone <저장소 주소>   # 저장소 한 벌을 처음 받아 온다
git fetch                # 원격에 올라온 커밋을 받아만 둔다
git pull                 # 받아 온 것을 내 브랜치에 합치기까지 한다
git push                 # 내가 만든 커밋을 올린다

클론은 저장소 전체를 처음 받아 오는 명령입니다. 푸시는 내 커밋을 원격 저장소에 올립니다. 페치는 남이 올린 커밋을 받아 두기만 합니다. 풀은 페치한 것을 내 브랜치에 합치는 데까지 갑니다. 네 줄 모두 Git 의 명령입니다. GitHub 는 이 명령이 닿는 상대편 서버입니다.

flowchart TD
    subgraph S["GitHub 서버"]
        R["원격 저장소"]
    end
    subgraph A["개발자 A 의 컴퓨터"]
        LA["내 저장소"]
    end
    subgraph B["개발자 B 의 컴퓨터"]
        LB["내 저장소"]
    end
    LA -->|푸시| R
    R -->|풀| LB
    LB -->|푸시| R
    R -->|풀| LA

두 사람은 서로의 컴퓨터에 직접 닿지 않습니다. 둘 다 GitHub 의 원격 저장소하고만 주고받습니다.

원격 저장소의 주소를 원격 URL(Uniform Resource Locator)이라고 합니다. 코드가 놓인 곳을 가리키는 주소입니다. 푸시할 수 있는 주소는 두 꼴뿐입니다.

https://github.com/user/repo.git
git@github.com:user/repo.git

위의 것은 HTTPS(HyperText Transfer Protocol Secure) 주소입니다. 아래 것은 SSH(Secure Shell) 주소입니다. 어느 꼴로 클론하느냐에 따라 인증 방법이 갈립니다. Git 은 원격 주소에 이름을 붙여 기억합니다. 기본 이름은 대개 origin 입니다.

풀 리퀘스트

여럿이 한 저장소를 고칠 때는 작업마다 브랜치를 따로 냅니다. 브랜치는 이력을 갈래로 나눠 두는 것입니다. 갈라 둔 브랜치에서 고치면 다른 사람의 작업을 건드리지 않습니다.

저장소마다 기준이 되는 브랜치가 하나 정해져 있습니다. 이것을 기본 브랜치라고 합니다. 이름은 흔히 main 입니다.

한 브랜치의 변경을 가져다 다른 브랜치에 적용하는 일이 병합입니다. 풀 리퀘스트는 한 브랜치의 변경을 다른 브랜치로 병합해 달라는 요청입니다. 이름이 비슷하지만 앞에서 본 git pull 과는 다른 것입니다. GitHub 가 내세우는 핵심 협업 기능입니다. 병합하기 전에 그 변경을 두고 이야기하고 리뷰하게 해 줍니다.

풀 리퀘스트는 병합 앞에 코드 리뷰를 끼워 넣습니다. 도움이 되는 일은 셋입니다. 팀이 함께 일하는 것, 문제를 일찍 잡는 것, 코드 품질을 지키는 것입니다.

풀 리퀘스트 페이지는 몇 갈래로 나뉘어 보입니다.

화면 보이는 것
Checks 탭 자동 테스트 · 빌드 같은 검사 결과
Files changed 탭 리뷰어가 읽는 diff — 바뀌기 전과 후를 줄 단위로 견준 것
병합 상태 병합을 막는 것 · 모자란 승인 · 그 밖의 요건
sequenceDiagram
    participant 작성자
    participant GitHub
    participant 리뷰어
    작성자->>GitHub: 작업 브랜치를 푸시한다
    작성자->>GitHub: 풀 리퀘스트를 연다
    GitHub->>리뷰어: 바뀐 줄을 보여 준다
    리뷰어->>GitHub: 의견을 남긴다
    Note over 작성자,리뷰어: 고칠 것이 있으면 작성자가 다시 푸시하고 되풀이한다
    리뷰어->>GitHub: 승인한다
    Note over GitHub: 요건이 채워지면 병합할 수 있다

그림은 풀 리퀘스트 한 건이 지나가는 순서입니다. 승인 없이는 아예 병합하지 못하게 묶으려면 「운영」의 보호 브랜치를 겁니다.

함께 고치는 두 방식

풀 리퀘스트를 쓰는 협업 방식은 둘입니다. 누가 어느 저장소에 푸시하느냐로 갈립니다. 둘을 가르려면 포크를 먼저 알아야 합니다.

포크는 다른 저장소의 사본으로 출발하는 저장소입니다. 그 원본을 업스트림 저장소라고 부릅니다. 포크는 자기 설정과 권한을 가집니다. 그러면서도 업스트림과 이어진 채로 남습니다. 브랜치는 한 저장소의 일부지만, 포크는 설정과 협업 공간을 갖춘 별개의 저장소입니다.

공유 저장소 방식 포크와 풀 방식
푸시하는 곳 협업자 모두가 푸시 권한을 가진 저장소 하나 내가 만든 포크
고치는 단위 그 저장소 안에 낸 작업 브랜치(주제 브랜치) 포크 안의 작업 브랜치
흔한 곳 비공개 프로젝트를 함께 하는 작은 팀과 조직 오픈 소스 프로젝트

「포크와 풀 방식」의 「풀」은 풀 리퀘스트를 가리킵니다. 업스트림 소유자가 허락해 두었다면, 읽기 권한을 가진 누구나 그 저장소를 포크할 수 있습니다. 내가 만든 포크에 푸시할 때는 업스트림의 허락이 필요 없습니다. 새 기여자가 미리 맞추지 않고 혼자 일을 시작할 수 있어서 오픈 소스 프로젝트에서 이 방식을 많이 씁니다.

포크에서 고친 것을 업스트림에 넣는 길도 풀 리퀘스트입니다. 포크 안의 작업 브랜치에서 업스트림의 기본 브랜치로 병합해 달라고 요청합니다. 저장소를 건너가는 요청이라는 것만 앞 소절과 다릅니다.

flowchart TD
    subgraph U["업스트림 저장소 · 원본"]
        UM["기본 브랜치 main"]
    end
    subgraph F["포크 · 내가 만든 사본"]
        FB["작업 브랜치"]
    end
    L["내 컴퓨터의 저장소"]
    OF["그 업스트림의 다른 포크"]
    D["같은 Git 데이터"]
    U -->|사본으로 출발 · 이어진 채로 남는다| F
    L -->|푸시 · 업스트림 허락이 필요 없다| FB
    FB -->|풀 리퀘스트 · 리뷰와 승인을 거쳐 병합| UM
    U --- D
    F --- D
    OF --- D

그림에서 서버 쪽 저장소가 둘입니다. 앞 소절 그림의 원격 저장소 하나가 업스트림과 포크로 늘어난 것입니다. 포크와 업스트림은 같은 Git 데이터를 나눠 씁니다. 그래서 포크에 올린 내용은 업스트림과 그 업스트림의 다른 모든 포크에서도 접근할 수 있습니다.

포크의 공개 여부는 업스트림을 따릅니다. 공개 저장소를 포크하면 공개 포크가 됩니다. 비공개 저장소를 포크하면 비공개 포크가 됩니다. 포크만 떼어 바꿀 수는 없습니다.

MDN(Mozilla Developer Network) Web Docs 의 문서 저장소가 이 길로 기여를 받습니다. 기여하려면 GitHub 계정이 있어야 합니다. 오타 하나를 고치는 것처럼 작은 수정이라면 가장 쉬운 길은 GitHub 웹 화면입니다. GitHub 에 로그인해 원본 파일을 열고 편집 버튼을 누르면 웹 화면이 포크와 브랜치를 만들어 줍니다. 그 브랜치에서 고친 뒤 풀 리퀘스트를 열면, 리뷰와 승인을 거쳐 MDN 저장소의 main 브랜치에 병합됩니다.

명령줄 인증

푸시처럼 저장소를 바꾸는 동작은 누가 하는지 GitHub 가 알아야 합니다. 명령줄에서 GitHub 에 닿는 길은 HTTPS 와 SSH 둘입니다. 두 길은 인증하는 방법이 서로 다릅니다. 어느 쪽인지는 클론할 때 고른 원격 URL 이 정합니다.

HTTPS 쪽이 쓰는 개인 액세스 토큰은 비밀번호 대신 넣는 긴 문자열입니다. 쓰임이나 기기마다 만들어 쓸 수 있습니다. 하나씩 취소할 수 있습니다. 필요한 권한만 갖게 좁힐 수도 있습니다.

HTTPS SSH
인증 수단 개인 액세스 토큰. 비밀번호를 묻는 곳에 토큰을 넣는다 내 컴퓨터에서 만든 공개 키·개인 키 한 쌍. 공개 키를 GitHub 계정에 등록한다
막히는 곳 방화벽이나 프록시 뒤에서도 모든 저장소에 닿는다 방화벽이나 프록시가 SSH 연결을 막을 수 있다
토큰을 안 넣는 길 Git Credential Manager 같은 자격 증명 도우미를 대신 쓴다 —

GitHub CLI(Command Line Interface, 명령줄 인터페이스)는 GitHub 가 내놓은 명령줄 도구입니다. 위 표는 그 도구 없이 Git 만 쓸 때의 기준입니다. 계정 비밀번호로는 Git 작업을 인증하지 못합니다. 언제부터 막혔는지는 「운영」이 다룹니다.

토큰은 비밀번호를 넣던 곳에 들어가는 값입니다. 새어 나가면 그 권한이 남의 손에 갑니다. 그래서 토큰은 코드에 적어 올리지 않고 떼어 보관합니다. 이렇게 비밀 값을 코드와 떼어 다루는 일을 시크릿 관리라고 합니다.

쓰지 않는 때

혼자 한 컴퓨터에서만 작업하면 GitHub 가 없어도 됩니다. Git 만으로 이력을 남기고 되돌릴 수 있습니다. 대신 그 컴퓨터가 망가지면 이력도 함께 사라집니다.

코드를 공개 클라우드에 두지 않고 통제를 늘리려는 회사를 위한 판도 있습니다. 설치형 판인 GitHub Enterprise Server 입니다. 규제 준수 의무를 지는 기업에 알맞은 판입니다. 회사의 기반 시설 위에서 돕니다. 방화벽·네트워크 정책·모니터링처럼 회사가 정한 접근·보안 통제를 받습니다.

GitHub Enterprise Server 는 가상 어플라이언스로 배포됩니다. 돌리는 데 필요한 것을 한 꾸러미로 묶어 가상 머신에 올리는 꼴입니다. 설치하면 리눅스 운영체제 위에 GitHub 전용 프로그램 묶음이 돕니다. 밑의 운영체제를 고치거나 다른 소프트웨어를 깔면 지원받지 못합니다.

기능은 대개 github.com 에 먼저 나옵니다. 설치형 판에는 그 판이 새로 나올 때 함께 들어옵니다.

포기한 것

GitHub 가 안 하기로 한 것 셋을 아래에서 짚습니다. 셋은 협업 기록, 큰 파일, Git 이 아닌 버전관리 프로그램입니다. 저마다 무엇을 버리고 무엇을 얻었는지를 짝으로 놓습니다.

협업 기록을 Git 저장소 밖에 둔다

Git 저장소에 들어가는 것은 프로젝트의 파일과 폴더, 그리고 파일마다 바뀐 이력입니다.

태그는 커밋 하나에 붙이는 이름표입니다. 미러 클론은 저장소의 브랜치와 태그를 빠짐없이 복제하는 클론입니다. Git 저장소는 미러 클론 한 번으로 이력까지 백업됩니다.

저장소에 딸린 문서 공간인 위키도 Git 저장소입니다. 그래서 클론하면 같이 백업됩니다.

풀 리퀘스트와 이슈는 이 Git 데이터 밖에 있습니다. GitHub 가 Git 저장소 위에 쌓아 올린 협업 기록입니다. 그래서 GitHub 제품끼리 저장소를 옮길 때도 「Git 소스(커밋 이력 포함)」와 「풀 리퀘스트」·「이슈」·「마일스톤」을 항목마다 따로 셉니다. 크기 한도도 Git 소스와 그 밖의 기록에 따로 매깁니다.

flowchart TD
    subgraph G["Git 저장소 · 미러 클론으로 따라온다"]
        FILES["파일과 폴더"]
        HIST["파일마다 바뀐 이력"]
    end
    subgraph W["위키 · 따로 된 Git 저장소"]
        WIKI["위키 문서"]
    end
    subgraph S["GitHub 가 그 위에 쌓은 협업 기록 · 서버에만 있다"]
        PR["풀 리퀘스트"]
        IS["이슈"]
        MS["마일스톤"]
    end
    G -->|미러 클론| B1["내 손의 사본 · 이력까지 온다"]
    W -->|클론| B1
    S -->|REST API 로 만드는 이전 아카이브| B2["보관용 사본 · 일부만 · 되살리는 길 없음"]

이 협업 기록까지 받으려면 API(Application Programming Interface, 프로그램이 GitHub 를 부르는 통로)를 씁니다. GitHub 의 API 는 REST(Representational State Transfer) 방식입니다.

이 API 로 이전 아카이브를 만들 수 있습니다. 「이전」은 저장소를 다른 곳으로 옮기는 일을 말합니다.

이 아카이브에도 모든 데이터가 들지는 않습니다. 객체는 Git 이 파일 내용이나 커밋을 저장소 안에 담는 단위입니다. 큰 파일을 떼어 맡기는 Git LFS(Git Large File Storage)의 객체, 그리고 GitHub 기능인 토론과 패키지가 빠지는 예입니다.

아카이브를 GitHub 에 되살리는 방법은 지원되지도 문서로 정해지지도 않았습니다. 그래서 이 백업은 보관용으로만 맞습니다.

얻은 것은 Git 에 없는 계획·협업 도구입니다. GitHub 는 Git 저장소를 맡아 두는 데서 그치지 않고 이 도구들을 덧붙였습니다. 풀 리퀘스트의 검사 결과와 병합 상태, 이슈가 그렇게 붙은 것들입니다.

파이썬 언어를 개발하는 CPython 프로젝트는 GitHub 로 옮기면서 이 차이를 직접 짚었습니다. 얕은 클론은 최근 이력 일부만 받는 클론입니다. 얕은 클론이 아니면 클론마다 저장소의 전체 이력이 들어 있어서 백업이 여럿 생기는 셈입니다. 그래서 코드는 백업이 저절로 됩니다.

반면 협업 기록 가운데 코드 리뷰 기록에는 그렇게 저절로 되는 백업이 없습니다. 그래서 CPython 은 리뷰 기록을 매일 떼어 백업하기로 했습니다. GitHub 에 문제가 생겨도 기록을 잃지 않으려는 것입니다. GitHub 가 하룻밤 새 사라져도 다른 리뷰 도구로 옮길 수 있게 하려는 것이기도 합니다.

저장소를 큰 파일 창고로 쓰지 않게 막는다

GitHub 는 저장소에 넣는 파일의 크기를 제한합니다. 100 MiB(메비바이트, 2의 20제곱 바이트)가 넘는 파일은 막습니다. 그보다 큰 파일을 버전관리하려면 Git LFS 를 써야 합니다.

큰 파일을 나눠 줘야 할 때는 릴리스를 쓰는 길도 있습니다. 릴리스는 파일을 저장소에 넣어 버전관리하는 대신 GitHub.com 에 따로 올려 나눠 주는 자리입니다.

저장소 전체도 작게 두기를 권합니다. 1 GB(gigabyte, 기가바이트) 미만이 이상적입니다. 5 GB 미만은 강하게 권합니다.

Git 은 큰 SQL(Structured Query Language, 구조화 질의 언어) 파일을 다루도록 만든 프로그램이 아닙니다. 큰 데이터베이스를 다른 개발자와 나눠 보려면 GitHub 는 파일 공유 서비스를 쓰라고 권합니다. Git 저장소 자체는 미러 클론으로 사본을 뜰 수 있습니다. 그래도 Git 은 백업 도구로 쓰도록 설계된 것이 아닙니다.

얻은 것은 응답 시간입니다. 작은 저장소일수록 클론이 빨리 끝납니다. 다루고 관리하기도 쉽습니다. 한도는 요청이 적당한 시간 안에 끝나게 하려고 둔 것입니다. 구체적인 값과 넘었을 때의 신호는 「운영」에 모았습니다.

Git 이 아닌 버전관리 프로그램은 받지 않는다

GitHub 는 한때 Git 저장소를 Subversion 클라이언트로도 다루게 해 주었습니다. Git 백엔드 위에서 Subversion 을 받아 준 것입니다. Git 백엔드는 GitHub 안에서 Git 저장소를 받아 처리하는 서버 쪽입니다. 고객이 작업 흐름을 조금씩 바꾸며 Git 으로 옮겨 오게 하려는 장치였습니다.

GitHub 는 2023년 1월에 이 지원을 접겠다고 발표했습니다. github.com 은 2024년 1월 8일부로 Subversion 지원을 완전히 끝내기로 했습니다. 설치형 판에서도 2024년 초에 나오는 판에서 빼기로 했습니다.

접은 까닭은 숫자에 있습니다. Git 백엔드로 들어오는 요청 가운데 Subversion 통로로 온 것은 0.02% 미만이었습니다. 한 달에 Subversion 요청을 한 번이라도 받는 저장소는 5,000개 안팎이었습니다. 인터넷에 열린 서비스는 유지 비용이 계속 듭니다. 그 비용을 접고 노력을 Git 하나에 모으기로 한 것입니다.

예시

GitHub 를 고른 프로젝트 둘을 아래에 놓습니다. CPython 은 무엇이 불편해서 GitHub 로 옮겼는지를 보입니다. Kubernetes 는 GitHub 의 풀 리퀘스트 위에 자기 리뷰 규칙을 어떻게 얹었는지를 보입니다.

CPython

CPython 은 파이썬 언어를 개발하는 프로젝트입니다. 원래는 hg.python.org 에서 버전관리 프로그램 Mercurial 로 직접 운영했습니다. 기여자가 패치를 올리면 핵심 개발자가 자체 수정한 Rietveld 코드 리뷰 도구로 검토했습니다. 핵심 개발자에게 아주 무겁고 손이 많이 가는 과정이었습니다.

2014년 말, 새 개발 과정으로 옮기기로 정했습니다. 제안을 받은 끝에 PEP(Python Enhancement Proposal, 파이썬 개선 제안) 둘이 남았습니다. GitHub 로 가자는 PEP 481 과 GitLab 으로 가자는 PEP 507 입니다. 2016년 1월 1일, Brett Cannon 이 GitHub 로 옮기기로 결정했습니다. 고른 이유는 다섯입니다.

이유 내용
기반 시설 부담 직접 운영하는 기반 시설이 자원봉사자에게 짐이었다. 관리되지 않는 Rietveld 수정판을 쓰고 있었다
핵심 개발자의 시간 자체 작업 흐름이 시간을 많이 먹었다. 받쳐 줄 자동화 도구가 모자랐다
외부 기여자의 진입 장벽 CPython 에만 있는 과정을 익히는 데 시간이 들었다
GitLab 과의 차이 GitLab 이 오픈 소스라는 것 말고는 둘을 가르는 기능이 없었다
익숙함 핵심 개발자와 외부 기여자 모두 GitLab 보다 GitHub 에 훨씬 익숙했다

GitLab 안이던 PEP 507 은 반려됐습니다. GitHub 안이던 PEP 481 은 철회됐습니다. 이전 절차는 PEP 512 가 정리했습니다. CPython 의 개발 과정은 2017년 2월 10일 github.com/python/cpython 으로 옮겨졌습니다.

Kubernetes

Kubernetes 는 코드베이스를 여러 영역으로 나눠 관리하는 오픈 소스 프로젝트입니다. 풀 리퀘스트 위에 두 단계 리뷰를 얹었습니다. 두 단계를 나누는 것은 저장소 곳곳에 놓인 OWNERS 파일입니다. 이 파일은 코드베이스의 부분마다 책임을 맡을 사람을 정합니다.

YAML
approvers:
 - alice
 - bob # this is a comment
reviewers:
 - carol
 - david # this is another comment
 - sig-foo # this is an alias

reviewers 는 리뷰를 맡을 만한 사람입니다. approvers 는 최종 승인을 할 수 있는 사람입니다. 값은 GitHub 사용자 이름이나 별칭입니다. 이 방식은 Chromium 프로젝트의 OWNERS 파일에서 왔습니다. 그것이 다시 GitHub 의 CODEOWNERS 파일에 영향을 주었습니다.

리뷰어는 코드가 괜찮다고 보면 풀 리퀘스트 댓글에 /lgtm(looks good to me, 좋아 보인다)을 적습니다. 그러면 Kubernetes 가 돌리는 GitHub 봇 prow 가 lgtm 레이블을 붙입니다. 레이블은 풀 리퀘스트에 붙는 꼬리표입니다. 마음이 바뀌면 /lgtm cancel 로 거둡니다.

OWNERS 에 리뷰어로 올라 있는 사람이 붙인 lgtm 은 믿을 만한 리뷰어의 리뷰를 통과했다는 신호입니다. 이어 승인자가 /approve 를 남기면 approved 레이블이 붙습니다. 최종 리뷰를 통과해 자동 병합할 준비가 됐다는 신호입니다.

설정에 따라서는 리뷰어와 승인자를 겸한 사람의 /lgtm 이 두 레이블을 한꺼번에 붙이게 할 수도 있습니다. kubernetes/kubernetes 를 비롯한 많은 프로젝트에서는 그것이 기본이 아닙니다. /lgtm 과 /approve 는 서로 떨어져 있습니다.

테스트가 통과하고 lgtm 과 approved 두 레이블이 붙으면 풀 리퀘스트는 병합 대기열에 들어갑니다. 대기열은 Tide 가 맡습니다. Tide 는 GitHub 에 질의를 던져 병합할 풀 리퀘스트를 고릅니다. 한 번에 돌릴 수 있는 만큼 묶습니다. 테스트가 통과하면 자동으로 병합합니다.

sequenceDiagram
    participant 리뷰어
    participant 승인자
    participant 풀 리퀘스트
    participant Tide
    리뷰어->>풀 리퀘스트: /lgtm 댓글
    Note over 풀 리퀘스트: prow 봇이 lgtm 레이블을 붙인다
    승인자->>풀 리퀘스트: /approve
    Note over 풀 리퀘스트: approved 레이블이 붙는다
    Tide->>풀 리퀘스트: 질의로 병합 후보를 고른다
    Note over Tide: 테스트가 통과하면
    Tide->>풀 리퀘스트: 자동으로 병합한다

사람은 댓글 한 줄만 남깁니다. 레이블과 병합은 봇이 GitHub 위에서 처리합니다.

운영

GitHub 저장소를 굴리다 부딪히는 한도와 손잡이를 아래에 값으로 적습니다. 보는 것은 파일과 저장소의 크기, API 호출 수, Git 작업의 인증, 보호할 브랜치 넷입니다. 한도마다 어디서 막히는지와 어떤 신호가 오는지를 함께 적습니다.

파일과 저장소 크기

대상 권장 최대 강제
파일 하나를 Git 으로 올릴 때 50 MiB 를 넘으면 Git 이 경고한다. 푸시는 된다 100 MiB 를 넘으면 막힌다
파일 하나를 브라우저로 올릴 때 — 25 MiB
저장소 전체 1 GB 미만이 이상적 · 5 GB 미만을 강하게 권장 —
디스크의 .git 폴더 10 GB —
객체 하나 1 MB(megabyte, 메가바이트) 100 MB
푸시 한 번 — 2 GB
읽기 작업(페치·클론) 저장소당 초당 15회 —
푸시 빈도 저장소당 분당 6회 —

표의 「객체 하나」는 Git 이 파일 내용이나 커밋을 저장소 안에 담을 때 쓰는 단위입니다. .git 폴더는 저장소를 압축해 담습니다. 디스크의 크기는 이 폴더로 잽니다.

50 MiB 경고를 받은 파일도 푸시는 됩니다. 그래도 그 커밋을 지워 성능 영향을 줄이는 쪽을 생각해 볼 수 있습니다.

권장 최대를 넘으면 저장소 상태가 나빠질 위험이 커집니다. 기본 Git 작업의 응답이 늦어지는 것과 웹 화면이 굼떠지는 것이 그 예입니다. 이것이 전부는 아닙니다. 큰 저장소는 개발자와 CI(Continuous Integration, 지속적 통합)의 페치를 늦추고 클론 시간을 늘릴 수 있습니다. 저장소가 GitHub 기반 시설에 지나친 부담을 주면 GitHub 지원팀이 바로잡아 달라는 메일을 보낼 수 있습니다.

풀 리퀘스트 한 건의 diff 에도 상한이 있습니다. 불러올 수 있는 diff 는 모두 합쳐 20,000줄, 또는 원본 diff 데이터 1 MB 까지입니다.

API 요청 한도

GitHub 는 일정 시간 안에 보낼 수 있는 REST API 요청 수를 제한합니다. 한도는 남용과 서비스 거부 공격을 막는 데 도움이 됩니다. 모두가 API 를 쓸 수 있게 지키려는 것이기도 합니다.

요청 주체 한도
인증하지 않은 요청. 공개 데이터만 읽을 때 쓸 수 있다 시간당 60회. 요청을 보낸 IP(Internet Protocol) 주소에 묶인다
개인 액세스 토큰, 또는 나 대신 부르는 GitHub App · OAuth(Open Authorization) 앱 모두 합쳐 내 계정 기준 시간당 5,000회
GitHub Actions 워크플로(저장소에 적어 둔 자동 작업)가 쓰는 GITHUB_TOKEN 저장소당 시간당 1,000회

한도를 넘으면 403 또는 429 응답이 옵니다. 이때 x-ratelimit-remaining 헤더는 0 이 됩니다. x-ratelimit-reset 헤더가 가리키는 시각이 지나기 전에는 다시 보내지 않아야 합니다. 한도에 걸린 채 계속 보내면 그 연동이 차단될 수 있습니다.

계정 비밀번호 대신 토큰

GitHub 는 2021년 8월 13일부터 github.com 에서 Git 작업을 인증할 때 계정 비밀번호를 받지 않습니다. 명령줄 Git, Git 을 쓰는 데스크톱 앱, 비밀번호로 저장소에 직접 닿던 앱과 서비스가 대상이었습니다. GitHub Desktop 은 영향을 받지 않았습니다.

비밀번호 대신 HTTPS 위의 개인 액세스 토큰(권장)이나 SSH 키를 씁니다. 지금은 Git 이 비밀번호를 물으면 그 칸에 개인 액세스 토큰을 넣습니다.

이 날짜는 github.com 에 걸리는 것입니다. 설치형 GitHub Enterprise Server 쪽은 바뀌는 것을 발표하지 않았습니다.

보호 브랜치

기본 브랜치처럼 중요한 브랜치에는 보호 규칙을 겁니다. 강제 푸시는 원격 브랜치의 이력을 내 것으로 덮어쓰는 푸시입니다. 규칙은 협업자가 그 브랜치를 지우거나 강제 푸시할 수 있는지를 정합니다. 그 브랜치로 들어오는 푸시에 요건을 걸 수도 있습니다.

규칙을 걸면 기본으로 두 가지가 막힙니다. 강제 푸시와 브랜치 삭제입니다.

병합 전 리뷰를 요구할 수 있습니다. 보호 브랜치로 병합되는 모든 풀 리퀘스트가 정해진 수의 승인을 받게 하는 요건입니다. 저장소 관리자가 이 요건을 걸 수 있습니다.

사용자 지정 역할은 줄 권한을 골라 담아 만드는 역할입니다. 「edit repository rules」 권한을 담은 사용자 지정 역할도 이 요건을 걸 수 있습니다. 켜 두면 협업자가 그 브랜치에 변경을 넣는 길은 하나뿐입니다. 쓰기 권한을 가진 리뷰어에게 필요한 수만큼 승인받은 풀 리퀘스트입니다.

승인을 기다리거나 변경 요청을 받은 풀 리퀘스트를 병합하려 하면 이런 오류가 옵니다.

remote: error: GH006: Protected branch update failed for refs/heads/main.
remote: error: Changes have been requested.

검사 통과를 병합 조건으로 거는 손잡이도 같은 규칙에 있습니다. 그 검사를 누가 만드는지는 「맞물림」에서 봅니다.

맞물림

같은 저장소에 붙는 GitHub 의 형제 기능 넷이 어느 방향으로 서로 부르는지를 아래에서 따라갑니다. 따라가는 길은 풀 리퀘스트 한 건이 열려서 병합되기까지입니다. 기능마다 무엇이 무엇을 깨우는지 적습니다. 붙일 때 무엇을 치르는지도 적습니다.

flowchart TD
    P["푸시 · 풀 리퀘스트"] -->|이벤트| A["GitHub Actions 워크플로"]
    A -->|실행 결과| C["상태 검사"]
    C -->|보호 브랜치의 필수 검사가 통과해야| M["기본 브랜치로 병합"]
    M -->|닫는 키워드가 있으면| I["이슈가 닫힌다"]
    P -->|구독한 이벤트| W["웹훅 · 바깥 서버로 요청"]

워크플로를 깨우는 이벤트

GitHub Actions 는 저장소에 적어 둔 워크플로를 돌리는 기능입니다. 워크플로는 GitHub 에서 특정 활동이 일어날 때, 정해 둔 시각에, 또는 GitHub 밖의 일이 생길 때 돌도록 설정합니다. 그 활동 가운데 이 절이 따라가는 것은 push 와 pull_request 둘입니다.

push 는 커밋이나 태그를 푸시할 때 워크플로를 돌립니다. 태그는 특정 커밋에 붙이는 이름표입니다. pull_request 는 활동 종류를 따로 정하지 않으면 풀 리퀘스트가 열리거나 다시 열릴 때 돕니다. 풀 리퀘스트의 head 브랜치, 곧 병합하려는 작업 브랜치가 갱신될 때도 돕니다.

열려 있고 병합할 수 있는 풀 리퀘스트라면 테스트는 head 브랜치 혼자가 아니라 병합한 결과를 대상으로 돕니다. 워크플로가 받아 올 코드를 가리키는 값인 GITHUB_REF 에 GitHub 가 미리 병합해 둔 결과가 들어오기 때문입니다. 코드를 받아 오는 actions/checkout 은 기본으로 이 값을 씁니다.

대신 병합 충돌이 있는 풀 리퀘스트에서는 워크플로가 돌지 않습니다. 충돌부터 풀어야 합니다.

병합을 막는 상태 검사

워크플로는 잡 단위로 돕니다. 잡은 워크플로 안에서 이름을 가진 실행 단위입니다. 잡이 끝나면 그 결과가 풀 리퀘스트의 상태 검사로 보입니다.

보호 브랜치에 필수 상태 검사를 걸어 두면, 그 검사가 모두 통과해야 협업자가 변경을 병합할 수 있습니다. 통과로 치는 결과는 성공·건너뜀·중립 셋입니다. 필수 검사로 걸 수 있는 것은 검사(check)와 커밋 상태(commit status) 두 종류입니다. 둘을 가르는 기준은 자료에 없습니다(미확인).

치르는 것은 이름 관리입니다. 특정 검사를 요구하는 규칙을 쓰면 잡 이름이 모든 워크플로에서 겹치지 않아야 합니다. 같은 잡 이름이 여러 워크플로에 있으면 검사 결과가 모호해집니다. 풀 리퀘스트 병합이 막힐 수도 있습니다.

이슈를 닫는 키워드

풀 리퀘스트 설명이나 커밋 메시지에 키워드와 이슈 번호를 적으면 풀 리퀘스트와 이슈가 이어집니다. 이어진 풀 리퀘스트가 저장소의 기본 브랜치로 병합되면 그 이슈가 자동으로 닫힙니다.

쓸 수 있는 키워드 close · closes · closed · fix · fixes · fixed · resolve · resolves · resolved
같은 저장소의 이슈 Closes #10
다른 저장소의 이슈 Fixes octo-org/octo-repo#100

풀 리퀘스트 설명의 키워드는 그 풀 리퀘스트가 기본 브랜치를 겨눌 때만 읽힙니다. 다른 브랜치를 겨누면 키워드가 무시됩니다. 링크도 생기지 않습니다. 병합해도 이슈에는 아무 일이 없습니다.

바깥으로 나가는 웹훅

앞의 셋이 GitHub 안에서 서로 깨우는 것이라면 웹훅은 밖으로 나가는 방향입니다. 웹훅을 만들 때는 URL 하나를 정합니다. 그리고 GitHub 의 이벤트를 구독합니다. 구독한 이벤트가 일어나면 GitHub 가 그 URL 로 이벤트 데이터를 실은 HTTP(HyperText Transfer Protocol) 요청을 보냅니다.

받는 쪽이 API 를 이따금 불러 새 데이터가 있나 확인하는 폴링과 반대 방향입니다. 관심을 한 번만 밝혀 두면 일이 생길 때마다 받습니다. 예를 들어 브랜치에 코드가 푸시되면 바깥의 CI 서버인 Jenkins 나 CircleCI 에서 CI 파이프라인을 돌립니다. 받는 서버가 그 URL 에서 웹훅 전달을 기다리도록 차려져 있어야 받은 것을 처리할 수 있습니다.

관련 항목

GitHub 가 맡아 두는 Git 의 단위

Git · 버전관리 · 저장소 · 원격 저장소 · 로컬 저장소 · 커밋 · 커밋 메시지 · 브랜치 · 태그

원격 저장소와 주고받는 Git 명령

클론 · 푸시 · 풀 · 페치 · 강제 푸시 · 얕은 클론 · 미러 클론

풀 리퀘스트를 거쳐 병합하는 협업 방식

풀 리퀘스트 · 코드 리뷰 · 병합 · 병합 충돌 · 리베이스 · 포크 · 브랜치 전략 · 보호 브랜치 · CODEOWNERS

저장소에 붙어 서로 깨우는 GitHub 기능

GitHub Actions · 워크플로 · 상태 검사 · 이슈 · 마일스톤 · GitHub 릴리스 · GitHub 위키 · 지속적 통합 · 지속적 배포

GitHub 와 바깥 시스템을 잇는 방식

API · REST · 웹훅 · 폴링 · GitHub App · Jenkins · CircleCI

GitHub 에 닿을 때 쓰는 인증 수단

인증 · 인가 · HTTPS · SSH · 개인 액세스 토큰 · 액세스 토큰 · OAuth 2.0 · Git Credential Manager · GitHub CLI · 시크릿 관리 · 접근 제어

한도에 걸릴 때 만나는 응답과 우회 수단

HTTP 403 · HTTP 429 · 레이트 리밋 · RateLimit 헤더 필드 · Git LFS

GitHub 를 회사 안에 두는 설치형 구성

GitHub Enterprise Server · 가상 어플라이언스 · 가상 머신 · 온프레미스

같은 역할을 두고 겨루는 코드 호스팅 서비스

GitLab · Bitbucket · Gitea · Azure DevOps

GitHub 로 옮겨 오기 전에 쓰던 도구

Subversion · Mercurial · Rietveld

Kubernetes 가 풀 리퀘스트 위에 얹은 리뷰 도구

Prow · Tide · OWNERS 파일

GitHub 에 원본 저장소를 두는 프로젝트

CPython · Python · Kubernetes · MDN · React · Rails · 오픈 소스

다른 이름: 깃허브 · github · github.com