사전 체크아웃
용어함정

체크아웃

gabury1고친 사람 github-actions[bot]

체크아웃은 저장소에 보관된 버전 하나를 꺼내 내가 고칠 수 있는 파일로 펼쳐 줍니다. Git 에서는 따로 쌓아 가는 작업 줄기인 브랜치 사이를 내 컴퓨터 안에서 옮겨 가는 일을 이렇게 부릅니다. 서버 한 곳에 저장소를 두는 도구에서는 작업할 사본을 서버에서 처음 받아 오는 일을 이렇게 부릅니다. 쇼핑몰에서 말하는 체크아웃은 결제 단계를 가리키는 버전관리 밖의 낱말입니다.

쉽고 빠른 이해

무슨 일을 하는 물건인가 — 보관해 둔 코드의 한 모습을 폴더에 펼쳐 줍니다. main 에서 일하다 feature 를 체크아웃하면 폴더 안 파일이 feature 의 내용으로 바뀝니다.

왜 이렇게 하나 — 저장소 안의 버전은 도구가 관리하는 형태라 편집기로 바로 고칠 수 없습니다. 고치려면 버전 하나를 보통 파일로 꺼내 놓아야 합니다.

어떻게 도나 (Git 기준)

  1. 어느 버전을 꺼낼지 고릅니다. 브랜치 이름을 대거나, 저장소에 쌓인 버전 하나인 커밋을 댑니다
  2. 폴더의 파일이 그 버전의 내용으로 바뀝니다
  3. 「지금 이 버전에 있다」는 표시가 그쪽으로 옮겨 갑니다

브랜치 대신 파일 이름을 대면 쓰임이 바뀝니다. 그 파일 하나만 고치기 전 모습으로 되돌립니다.

대가 — 커밋하지 않은 변경이 덮일 수 있습니다. 브랜치를 옮길 때는 덮일 파일이 있으면 Git 이 멈춰서 막아 줍니다. 파일을 되돌릴 때는 묻지 않고 덮습니다.

도구마다 뜻이 달라서 대화가 엇갈리기도 합니다. Subversion 을 쓰던 사람에게 체크아웃은 서버에서 작업할 사본을 처음 받아 오는 일입니다.

상세

이 절은 버전관리에서 「체크아웃」이 가리키는 동작들을 가릅니다.

저장소와 작업 폴더

버전관리 도구는 파일이 바뀌어 온 버전을 차례로 쌓아 둡니다. 쌓아 둔 곳이 저장소입니다. 저장소 안의 버전은 도구가 제 방식으로 묶어 보관합니다. 그래서 편집기로 바로 열어 고칠 수 없습니다.

고치려면 버전 하나를 보통 파일로 꺼내 폴더에 펼쳐 둬야 합니다. Git 은 이 폴더를 작업 트리라고 부릅니다. 또 다른 버전관리 도구인 Subversion 은 같은 폴더를 작업 사본이라고 부릅니다. 이름만 다릅니다. 하는 일은 같습니다.

체크아웃은 저장소에서 이 폴더로 꺼내는 방향의 이름입니다. 반대로 고친 파일을 저장소에 새 버전으로 넣는 일은 커밋입니다. 오래된 도구에서는 이 반대 방향을 체크인이라고 불렀습니다.

도구마다 갈리는 뜻

체크아웃의 뼈대는 도구마다 같습니다. 저장소에서 버전 하나를 꺼내 폴더에 펼칩니다. 어디서 무엇을 꺼내는지는 저장소를 어디에 두느냐에 따라 갈립니다. 이 소절은 저장소를 두는 두 방식을 먼저 보고, 체크아웃의 뜻을 표 하나로 나란히 놓습니다.

첫째 방식은 저장소를 서버 한 곳에만 둡니다. 모두가 같은 서버의 저장소에서 파일을 꺼내 갑니다. 이 방식을 중앙집중식 버전관리라고 합니다. Subversion 이 여기에 듭니다.

둘째 방식은 저장소 전체를 각자의 컴퓨터에 복사해 둡니다. 서버가 멈춰도 내 컴퓨터에서 이력을 보고 커밋할 수 있습니다. 이 방식을 분산 버전관리라고 합니다. Git 이 여기에 듭니다.

그래서 Git 을 쓰면 저장소가 두 벌 생깁니다. 내 컴퓨터에 있는 것이 로컬 저장소입니다. 서버에 두고 여럿이 주고받는 것은 원격 저장소입니다.

맥락 어디서 꺼내나 체크아웃 뒤에 바뀌는 것 Git 으로 치면
Git 내 컴퓨터의 로컬 저장소 작업 트리가 다른 브랜치의 모습이 된다 git checkout
Subversion 서버의 저장소 빈 폴더에 작업 사본이 처음 생긴다 git clone
잠금을 거는 오래된 도구 여럿이 함께 쓰는 저장소 파일 하나가 내 몫으로 잠긴다 기본 명령에는 없다

표의 마지막 열이 이 낱말의 함정입니다. Subversion 을 쓰던 사람이 Git 에서 「체크아웃부터 하세요」를 들으면 저장소를 받아 오라는 말로 알아듣습니다. Git 에서 그 일은 클론이 합니다.

Git 과 Subversion 을 가르는 것은 꺼내는 화살표가 어디를 지나느냐입니다. Subversion 의 체크아웃은 서버에서 내 컴퓨터로 네트워크를 건넙니다. Git 의 체크아웃은 내 컴퓨터 안에서 끝납니다. 네트워크를 건너는 일은 클론이 먼저 해 둡니다.

flowchart TD
    subgraph 서버
        S["Subversion 저장소"]
        R["원격 저장소"]
    end
    subgraph 내컴퓨터["내 컴퓨터"]
        W1["작업 사본"]
        L["로컬 저장소"]
        W2["작업 트리"]
    end
    S -->|"svn checkout"| W1
    R -->|"git clone"| L
    L -->|"git checkout"| W2

브랜치 옮기기

브랜치는 커밋이 이어지는 줄기에 붙인 이름입니다. 커밋 하나가 저장소에 쌓인 버전 하나입니다. main 줄기에서 일하다가 새 기능은 feature 줄기에 따로 쌓는 식으로 씁니다.

git checkout feature 를 치면 Git 은 세 가지를 feature 쪽으로 바꿉니다. 셋은 HEAD · 인덱스 · 작업 트리입니다.

바뀌는 것 무엇인가 체크아웃 뒤
HEAD 지금 어느 브랜치에 있는지 가리키는 표지 feature 를 가리킨다
인덱스 다음 커밋에 넣을 파일을 모아 두는 곳. 스테이징 영역이라고도 부른다 feature 의 마지막 커밋과 같아진다
작업 트리 내가 편집기로 여는 파일들 feature 의 마지막 커밋과 같아진다

눈으로 보이는 변화는 셋째 줄입니다. version.txt 가 브랜치마다 다른 내용을 가진다고 해 봅시다. 체크아웃 한 번에 같은 파일의 내용이 바뀝니다.

터미널
git checkout main
cat version.txt   # 1.0
git checkout feature
cat version.txt   # 2.0-beta

폴더 경로는 그대로입니다. 안의 내용만 바뀌었습니다. feature 에만 있는 파일은 새로 생깁니다. main 에만 있던 파일은 사라집니다. 체크아웃은 한 폴더를 여러 브랜치의 모습으로 번갈아 바꿔 끼웁니다.

새 브랜치를 만들면서 바로 옮겨 가려면 -b 를 붙입니다. git checkout -b fix 는 지금 커밋에서 fix 브랜치를 만듭니다. 그리고 HEAD 를 거기로 옮깁니다. 새 브랜치가 지금 커밋에서 출발하므로 작업 트리의 파일은 바뀌지 않습니다.

커밋하지 않은 변경이 있을 때

고치던 파일이 있는 채로 체크아웃하면 Git 은 먼저 그 변경이 덮이는지 봅니다. 고친 파일이 두 브랜치에서 내용이 같으면 변경을 들고 옮겨 갑니다. 두 브랜치에서 내용이 다르면 체크아웃을 거부하고 멈춥니다.

flowchart TD
    A["git checkout feature"] --> B{"고치던 파일이 있나"}
    B -->|없다| C["feature 로 옮긴다"]
    B -->|있다| D{"그 파일이 두 브랜치에서 같은가"}
    D -->|같다| E["변경을 들고 feature 로 옮긴다"]
    D -->|다르다| F["거부하고 멈춘다"]

멈추는 까닭은 커밋하지 않은 변경이 저장소 어디에도 없기 때문입니다. 덮어 쓰면 되살릴 길이 없습니다.

이럴 때 쓰는 것이 스태시입니다. 스태시는 고치던 내용을 따로 보관했다가 나중에 꺼내 다시 붙이는 기능입니다. 변경을 커밋하거나 스태시로 치워 둔 뒤 다시 체크아웃하면 됩니다.

커밋으로 옮기기

체크아웃에는 브랜치 이름 대신 커밋을 댈 수도 있습니다. 커밋마다 붙는 고유 번호인 커밋 해시를 적습니다. 그러면 작업 트리가 그 커밋 때의 모습으로 돌아갑니다. 옛 버전에도 버그가 있었는지 확인할 때 씁니다.

이때 HEAD 는 브랜치가 아니라 커밋을 곧장 가리킵니다. 이 상태를 분리된 HEAD라고 부릅니다. 둘러보기만 할 때는 문제가 없습니다.

분리된 HEAD 에서 새 커밋을 만들면 그 커밋은 어느 브랜치에도 안 붙습니다. 다른 브랜치로 옮겨 가면 이름 없이 남아 다시 찾기 어려워집니다. 그 커밋을 남기려면 떠나기 전에 git checkout -b 이름 으로 브랜치를 만들어 붙입니다.

파일 되돌리기

git checkout 은 브랜치가 아니라 파일 하나를 대상으로도 씁니다. 파일 이름을 대면 작업 트리의 그 파일을 인덱스의 내용으로 덮어 씁니다. 인덱스에 따로 모아 둔 것이 없으면 덮어 쓰는 내용은 마지막 커밋의 것입니다.

아래는 고치던 app.py 를 되돌리는 모습입니다. 첫 줄의 M 은 그 파일이 고쳐졌다는 표시입니다.

터미널
git status --short   #  M app.py
git checkout -- app.py
git status --short   # (출력 없음)

둘째 줄의 -- 는 뒤에 오는 것이 파일 이름이라는 표시입니다. 브랜치와 파일의 이름이 같을 때 Git 이 헷갈리지 않게 해 줍니다. 셋째 줄에서는 고친 흔적이 사라졌습니다.

이 쓰임은 브랜치 옮기기와 안전장치가 반대입니다. 브랜치를 옮길 때는 덮일 변경이 있으면 멈췄습니다. 파일을 되돌릴 때는 묻지 않고 덮습니다. 버린 내용은 커밋한 적이 없어서 Git 으로 되살릴 수 없습니다.

switch 와 restore

한 명령이 안전장치가 반대인 두 일을 맡으면 헷갈리기 쉽습니다. 그래서 뒤에 나온 Git 은 두 일을 새 명령 둘로 나눠 두었습니다. git switch 는 브랜치 옮기기만 합니다. git restore 는 파일 되돌리기만 합니다.

하려는 일 git checkout 으로 새 명령으로
브랜치로 옮기기 git checkout feature git switch feature
브랜치를 만들며 옮기기 git checkout -b fix git switch -c fix
파일 되돌리기 git checkout -- app.py git restore app.py

git checkout 도 없어지지 않고 계속 동작합니다. 대화에서 「main 을 체크아웃한다」고 하면 명령과 상관없이 main 브랜치로 옮긴다는 뜻입니다.

Subversion 의 체크아웃

Subversion 에서 체크아웃은 작업을 시작할 때 한 번 하는 일입니다. 서버에 있는 저장소의 주소를 대면 빈 폴더에 작업 사본이 생깁니다.

터미널
svn checkout http://svn.example.com/repos/calc
ls calc   # Makefile  button.c  integer.c

작업 사본에는 파일과 그 파일이 어느 버전에서 왔는지 정도가 들어 있습니다. 지난 이력은 서버에만 있습니다. 그래서 새 버전을 받을 때는 svn update 로 서버에 묻습니다. 고친 것은 svn commit 으로 서버에 바로 올립니다.

Subversion 에서 다른 브랜치로 옮겨 가는 명령은 따로 있습니다. svn switch 입니다. 짝을 지으면 Subversion 의 체크아웃은 Git 의 클론에 가깝습니다. Git 의 체크아웃은 Subversion 의 switch 에 가깝습니다.

클론 안에 든 체크아웃

Git 의 클론은 원격 저장소를 통째로 복사해 로컬 저장소를 만듭니다. 복사가 끝나면 기본 브랜치를 한 번 체크아웃해 작업 트리를 채웁니다. Git 에서도 클론 한 번 안에 체크아웃이 들어 있는 셈입니다.

지속적 통합은 코드가 올라올 때마다 빌드와 시험을 자동으로 돌리는 방식입니다. 이 일을 맡은 빌드 서버도 클론과 체크아웃을 차례로 합니다. 저장소를 받아 빌드할 커밋을 펼친 뒤에야 빌드를 시작할 수 있습니다.

그래서 빌드 설정에는 대개 checkout 이라는 단계가 맨 앞에 들어갑니다. GitHub Actions 의 actions/checkout 이 그런 단계입니다. 이름은 체크아웃이지만 클론까지 함께 합니다.

잠금을 거는 체크아웃

RCS(Revision Control System) 같은 오래된 도구는 체크아웃에 잠금을 붙였습니다. 파일 하나를 고치겠다고 저장소에서 꺼내면 그 파일이 내 몫으로 잠깁니다. 다른 사람은 내가 체크인할 때까지 그 파일을 고치지 못합니다.

이 방식은 두 사람이 한 파일을 동시에 고치는 일을 처음부터 막습니다. 나중에 두 변경을 합치는 병합이 필요 없어집니다. 대가는 기다림입니다. 누가 파일을 체크아웃해 둔 채 퇴근하면 나머지는 그 파일을 못 고칩니다.

Git 에는 이런 잠금이 기본으로 없습니다. 각자 자기 작업 트리에서 고친 뒤 나중에 병합합니다.

어느 뜻인지 가르는 단서

대화나 문서에서 「체크아웃」이 나오면 함께 붙은 낱말을 봅니다. 대개 그것만으로 어느 뜻인지 갈립니다.

함께 나오는 말 뜻
브랜치 이름 · git checkout · 「main 으로 체크아웃」 Git 의 브랜치 옮기기
커밋 해시 · 「옛 커밋을 체크아웃」 · 분리된 HEAD Git 의 커밋으로 옮기기
빌드 설정의 checkout 단계(actions/checkout 등) 빌드 서버가 저장소를 받아 그 커밋을 펼친다. 클론과 체크아웃을 한 번에 한다
저장소 주소 · svn checkout · 작업 사본 Subversion 에서 작업 사본을 처음 받아 오기
체크인 · 잠금 · 「누가 체크아웃해 둬서 못 고친다」 잠금을 거는 체크아웃
장바구니 · 결제 · 주문 쇼핑몰의 결제 단계. 버전관리와 상관없다

관련 항목

체크아웃이 버전을 꺼내 오는 저장소

저장소 · 로컬 저장소 · 원격 저장소 · 중앙 저장소 · 베어 저장소

체크아웃이 바꾸는 Git 의 구성 요소

작업 트리 · HEAD (Git) · 스테이징 영역 · 브랜치 · 커밋 · 커밋 해시 · 분리된 HEAD

체크아웃과 앞뒤로 쓰는 Git 명령

클론 · 페치 · 풀 · 푸시 · 병합 · 리베이스 · 스태시 · 리셋 · 체리픽

체크아웃을 대신하거나 넓히는 Git 명령

git switch · git restore · 희소 체크아웃 · git worktree

체크아웃이 뜻을 달리하는 버전관리 방식

버전관리 · Git · Subversion · CVS · 중앙집중식 버전관리 · 분산 버전관리 · 작업 사본

체크아웃과 동시 수정을 다루는 방식

체크인 · 파일 잠금 · 잠금-수정-해제 · 복사-수정-병합 · 병합 충돌

체크아웃 단계를 자동으로 부르는 빌드 도구

지속적 통합 · 빌드 파이프라인 · GitHub Actions

쇼핑몰에서 체크아웃이 가리키는 결제 절차

결제 · 장바구니 · 전자상거래

다른 이름: checkout · git checkout · svn checkout