HOWTO · Git
Git Checkout과 Git Clone의 차이점
git checkout과 git clone 명령을 구분합니다.
이 페이지의 내용
git clone은 원격 저장소를 새 로컬 저장소로 복사합니다. git checkout은 이미 가지고 있는 저장소 안에서 동작하며, 과거에는 브랜치를 전환하거나 파일을 복원하는 데 사용했습니다. SVN 사용자라면 작업 사본을 가져오는 작업인 svn checkout을 떠올릴 수 있지만, Git에서는 이 작업에 git clone을 사용합니다.
두 명령은 작업의 서로 다른 단계에 속하므로 서로 바꿔 쓸 수 있는 대안이 아닙니다. 복제는 “이 프로젝트를 내 컴퓨터에 어떻게 가져오지?“라는 질문에 답하고, 체크아웃은 “내 기존 작업 트리가 지금 어떤 브랜치, 커밋, 파일 상태를 보여줘야 하지?“라는 질문에 답합니다. 저장소가 아직 없으면 체크아웃할 대상이 없고, 이미 있으면 다시 복제해도 별개의 두 번째 사본만 생길 뿐입니다.
한눈에 보기
| 측면 | git clone |
git checkout |
|---|---|---|
| 시작점 | 원격 저장소의 URL 또는 경로 | 로컬에 이미 존재하는 저장소 |
| 주요 결과 | 자체 .git 디렉터리를 갖춘 새 로컬 저장소 |
같은 저장소 안에서 변경된 작업 트리와 이동한 HEAD |
| 네트워크 사용 | 원격에서 객체와 기록을 다운로드함 | 로컬 브랜치, 커밋, 파일에 대해서는 사용하지 않음 |
| 일반적인 빈도 | 필요한 사본마다 한 번 | 작업 중에 하루에도 여러 번 |
| 저장소를 만들 수 있는가? | 예, 그것이 목적입니다 | 아니요, 저장소 밖에서는 실패합니다 |
| 관련된 최신 명령 | 없음, 복제에는 분리된 대체 명령이 없습니다 | 브랜치에는 git switch, 파일에는 git restore |
git clone으로 로컬 저장소 만들기
저장소 URL과 함께 git clone을 사용합니다. Git은 로컬 저장소를 만들고 기본 브랜치를 체크아웃합니다. 프로젝트에 처음 참여할 때뿐 아니라 로컬 사본이 더 필요할 때도 복제할 수 있습니다.
다음 단독 예제는 로컬 원본 저장소를 만들고, 이를 복제한 다음, 기능 브랜치를 만듭니다. 명령을 실행하면 새 브랜치로 전환한 뒤 확인 메시지가 출력됩니다. 아래 예제의 확인 메시지는 바이트 단위로 그대로 보존되어 영어로 표시됩니다.
set -eu
workdir=$(mktemp -d)
trap 'rm -rf "$workdir"' EXIT
git init -q "$workdir/source"
git -C "$workdir/source" config user.name "Example User"
git -C "$workdir/source" config user.email "example@example.com"
printf 'Project notes\n' > "$workdir/source/README.md"
git -C "$workdir/source" add README.md
git -C "$workdir/source" commit -qm "Add project notes"
git clone -q "$workdir/source" "$workdir/local"
git -C "$workdir/local" switch -q -c feature
printf 'Created a local clone and switched to feature.\n'
Created a local clone and switched to feature.
호스팅된 저장소를 복제하려면 복사한 HTTPS 또는 SSH URL을 git clone <repository-url>에 넣습니다. 대상 디렉터리 이름은 기본적으로 저장소 URL을 바탕으로 정해집니다. 다른 위치를 선택하려면 URL 뒤에 디렉터리 이름을 추가하세요. 핵심은 URL입니다. 이 명령은 원격 소스에서 저장소를 만듭니다.
복제는 현재 파일을 다운로드하는 것 이상입니다. Git은 커밋 기록을 복사하고, 원격 브랜치에 대한 원격 추적 브랜치를 만들며, 가져온 원본을 origin이라는 이름의 원격으로 등록합니다. 덕분에 나중에 실행하는 git fetch나 git pull이 업데이트를 어디서 가져올지 알 수 있습니다. 그런 다음 Git은 내부적으로 기본 브랜치를 체크아웃하여 작업 트리를 채웁니다. 이 마지막 단계가 두 명령이 만나는 유일한 지점입니다. 복제는 브랜치를 체크아웃하면서 끝나지만, 체크아웃으로는 결코 복제를 만들 수 없습니다.
가져오는 내용을 바꾸는 복제 옵션
실제 선택지는 대부분 세 가지 옵션으로 해결됩니다. 최신 스냅샷만 필요할 때, 예를 들어 지속적 통합에서는 --depth 1을 사용해 얕은 복제를 만드세요. 복제는 전체 기록 대신 지정한 개수만큼의 커밋만 다운로드하므로 시간과 디스크 공간을 절약하지만, 오래된 커밋은 로컬에서 사용할 수 없게 됩니다. 복제 후 기본 브랜치가 아닌 다른 브랜치를 체크아웃하려면 --branch <name>을 사용하고, 다른 브랜치가 전혀 필요 없으면 --single-branch와 함께 쓰세요. 단, --depth는 단순 로컬 경로로 복제할 때는 무시된다는 점에 유의하세요. 로컬 원본으로 얕은 복제를 시험할 때는 아래 두 번째 예제처럼 file:// URL을 전달하세요.
git checkout의 역할
git checkout은 과거에 브랜치 작업과 파일 복원을 모두 처리했습니다. 두 작업은 서로 다르므로, 최신 Git 버전에서는 더 명확한 git switch와 git restore 명령을 제공합니다. 이 명령을 사용할 수 있는지는 설치된 Git 버전에 따라 다릅니다. 사용할 수 없다면 각각에 대응하는 checkout 형식을 쓰세요.
브랜치를 만들고 전환하려면 git switch -c <branch-name>을 사용합니다. 과거 형식은 git checkout -b <branch-name>입니다. 기존 브랜치로 이동할 때는 git switch <branch-name> 또는 git checkout <branch-name>을 사용합니다. 저장소에 실제로 존재하는 브랜치 이름으로 자리표시자를 바꾸세요. 기본 브랜치 이름은 프로젝트마다 다릅니다.
추적 중인 파일의 스테이징되지 않은 수정 사항을 버리려면 git restore <file>을 사용합니다. 이 명령은 인덱스의 내용으로 파일을 복원하므로 스테이징된 변경 사항은 그대로 두지만, 해당 파일의 스테이징되지 않은 수정 사항은 버립니다. 이전에 사용하던 같은 동작의 명령은 git checkout -- <file>입니다. 복원하기 전에 git status를 확인하고, 필요한 작업은 먼저 저장하세요.
파일 형식의 이중 대시는 장식이 아닙니다. 이는 브랜치 또는 커밋 인수와 파일 경로를 구분하므로, Git은 이름이 브랜치를 뜻하는지 파일을 뜻하는지 추측할 필요가 없습니다. 브랜치와 파일이 같은 이름을 공유하면 git checkout <name>은 모호해져서 파일을 복원하려던 의도와 달리 브랜치로 전환될 수 있습니다. 반면 git checkout -- <name>은 항상 파일을 뜻합니다. 이런 모호함이 분리된 명령이 일상적인 사용에서 더 안전한 이유 중 하나입니다.
커밋 체크아웃: 분리된 HEAD
브랜치를 체크아웃하면 HEAD가 해당 브랜치로 이동하므로 새 커밋이 그 브랜치를 이어갑니다. 대신 특정 커밋 해시나 태그를 체크아웃하면 분리된 HEAD 상태가 됩니다. 작업 트리는 그 오래된 스냅샷을 보여주고, git branch --show-current는 아무것도 출력하지 않습니다. 오래된 릴리스를 검사하거나 버그 보고를 재현하는 것은 안전한 사용법입니다. 보기만 해서는 아무것도 바뀌지 않기 때문입니다. 분리된 상태에서 커밋하는 것은 위험합니다. 새 커밋이 어떤 브랜치에도 속하지 않아 다른 곳으로 전환한 뒤에는 찾기 어려워지기 때문입니다. 작업을 유지하고 싶다면 먼저 git switch -c <branch-name>으로 브랜치를 만드세요. 이 상태는 복제와는 무관합니다. 여전히 같은 저장소 안에 있으면서, 그 저장소가 이미 담고 있는 기록을 보고 있을 뿐입니다.
하나의 저장소에서 차이 확인하기
다음 단독 예제는 커밋이 세 개 있는 원본 저장소를 만든 다음 두 명령을 직접 대조합니다. 얕은 복제와 전체 복제를 비교하고, 체크아웃의 파일 형식으로 편집한 파일을 복원하며, 마지막으로 오래된 커밋을 체크아웃해 분리된 상태를 보여줍니다. 출력되는 커밋 수와 파일 내용이 검증 결과입니다. 얕은 복제는 커밋을 하나, 전체 복제는 세 개 모두 담고 있고, 복원은 추가된 초안 줄을 제거하며, 분리된 체크아웃은 두 번째 커밋에 도달합니다. 수정되지 않은 예제의 출력 메시지는 영어로 유지됩니다.
set -eu
workdir=$(mktemp -d)
trap 'rm -rf "$workdir"' EXIT
git init -q -b main "$workdir/source"
git -C "$workdir/source" config user.name "Example User"
git -C "$workdir/source" config user.email "example@example.com"
printf 'one\n' > "$workdir/source/notes.txt"
git -C "$workdir/source" add notes.txt
git -C "$workdir/source" commit -qm "First"
printf 'two\n' >> "$workdir/source/notes.txt"
git -C "$workdir/source" commit -qam "Second"
printf 'three\n' >> "$workdir/source/notes.txt"
git -C "$workdir/source" commit -qam "Third"
git clone -q --depth 1 "file://$workdir/source" "$workdir/shallow"
printf 'Shallow commits: %s\n' "$(git -C "$workdir/shallow" rev-list --count HEAD)"
git clone -q "$workdir/source" "$workdir/full"
printf 'Full commits: %s\n' "$(git -C "$workdir/full" rev-list --count HEAD)"
printf 'draft\n' >> "$workdir/full/notes.txt"
git -C "$workdir/full" checkout -- notes.txt
printf 'After restore: %s\n' "$(tail -n 1 "$workdir/full/notes.txt")"
git -C "$workdir/full" checkout -q HEAD~1
printf 'Detached commit subject: %s\n' "$(git -C "$workdir/full" log -1 --format=%s)"
if [ -z "$(git -C "$workdir/full" branch --show-current)" ]; then
printf 'HEAD state: detached\n'
fi
Shallow commits: 1
Full commits: 3
After restore: three
Detached commit subject: Second
HEAD state: detached
이 예제의 작업 순서에 주목하세요. 실제 작업을 그대로 반영하기 때문입니다. 모든 checkout은 clone(또는 git init)이 먼저 만든 저장소 안에서 실행됩니다. 이 순서를 뒤집는 것은 불가능합니다. 빈 디렉터리에서 git checkout을 실행하면 선택할 브랜치, 커밋, 추적 중인 파일이 없어 실패합니다.
작업에 맞는 명령 선택하기
- 원격 저장소 URL이 있고 로컬 저장소가 필요한가요?
git clone <repository-url>을 사용하세요. - 기존 저장소에서 브랜치를 만들거나 전환하려 하나요?
git switch또는 이에 대응하는git checkout형식을 사용하세요. - 추적 중인 파일의 커밋되지 않은 수정 사항을 버리려 하나요?
git restore <file>또는 이전 형식인git checkout -- <file>을 사용하세요. - 큰 저장소의 최신 스냅샷만 필요한가요? 예를 들어 빌드용으로요? 전부 복제하고 최신 커밋을 체크아웃하는 대신
git clone --depth 1 <repository-url>을 사용하세요. - 오래된 태그나 커밋 시점의 코드를 검사해야 하나요? 기존 복제본 안에서
git checkout <tag-or-commit>을 사용하고git switch <branch-name>으로 돌아오세요. 저장소를 다시 복제하지 마세요. - 원격에만 존재하는 동료의 브랜치에서 작업을 시작하나요? 기존 복제본 안에서 가져오기(fetch)를 하고 그 브랜치를 체크아웃하세요. 완전히 분리된 사본을 원할 때만 새 복제가 필요합니다.
혼란의 대부분은 두 가지 실수에서 비롯됩니다. 첫 번째는 저장소 URL을 넣어 git checkout을 실행하고 다운로드를 기대하는 것입니다. 체크아웃은 브랜치, 커밋, 경로 인수를 받으며 URL은 결코 받지 않으므로, 아무것도 가져오지 못하고 실패합니다. 두 번째는 다른 브랜치가 필요할 때마다 다시 복제하는 것으로, 시간과 디스크 공간을 낭비하고 서로 어긋나는 여러 사본을 남깁니다. 보통 복제본 하나면 프로젝트의 모든 브랜치를 처리할 수 있습니다. 관련된 오해로, 체크아웃이 선택한 브랜치를 다운로드한다는 생각이 있습니다. 체크아웃은 네트워크에 전혀 접속하지 않습니다. 저장소가 이미 알고 있는 브랜치와 커밋만 선택할 수 있으며, 그래서 완전히 새로운 원격 브랜치에는 먼저 git fetch가 필요할 수 있습니다.
요약하면, git clone은 원격 URL에서 저장소를 가져옵니다. git checkout은 기존 저장소에서 선택된 브랜치를 바꾸거나, 이전 파일 형식을 사용할 때 파일을 복원합니다. 원격 URL에서 로컬 저장소를 만드는 명령은 아닙니다.