checkout

checkout 이란

HEAD를 다른 브랜치의 최신 커밋이나 현재 현재 브랜치의 과거 커밋, 또는 아예 특정 커밋을 지정해서 이동시키는 것을 말한다. 다른 브랜치로 이동할 때에는 해당 브랜치의 이름을, 특정 커밋으로 이동할 때에는 특정 커밋 ID를 지정할 수 있다.

checkout의 대상

대상 설명
브랜치 - 현재 브랜치가 아닌 다른 브랜치의 이름을 지정함으로써, 대상 브랜치의 최신 커밋으로 HEAD를 이동한다.
- 작업 영역과 인덱스(스테이지 영역)이 해당 브랜치가 가리키는 커밋에 상응하는 내용으로 업데이트 된다.
특정 커밋 - 현재 커밋이 아닌 다른 커밋의 해시값을 직접 지정함으로써 해당 커밋으로 HEAD를 이동한다.
현재 브랜치의 과거 커밋 - HEAD~ 또는 HEAD^ 문자열을 이용해 현재 브랜치의 직전 커밋으로 이동할 수 있다.
- 전전 커밋은 HEAD~~ 또는 HEAD^^와 같이 지정할 수 있으며
- 세번째 부터는 HEAD~3과 같이 지정한다. (^n 방식은 사용 불가)

checkout을 하기 위한 전제 조건

다른 커밋으로 이동하는 것이므로, git status명령의 결과가 깨끗해야(working tree clean) 체크아웃이 가능하다. 결과가 깨끗하다는 의미는 작업 디렉터리, 스테이지 영역, 저장소의 상태가 모두 동일한 상태(예시 : 모든 파일이 추적중이고 커밋이 완료된 상태)를 뜻한다.

git checkout은 브랜치의 전환이나 특정 상태로 파일을 변경하는 명령이므로, 작업 디렉터리에 변경사항이 있으면 충돌이 발생하거나 변경 사항이 덮어쓰여질 위험이 있기 때문에 이러한 전제조건이 있는 것이다.

1
2
3
4
# git status가 깨끗한 상태
git status
>> On branch main
>> nothing to commit, working tree clean
1
2
3
4
5
6
7
# git status가 깨끗하지 않은 상태
git status
>> On branch main
>> No commits yet
>> Changes to be committed:
>>   (use "git rm --cached <file>..." to unstage)
>>         new file:   test.sh

checkout의 동작

(1) HEAD가 지정한 브랜치의 최신 커밋이나, 지정한 커밋으로 이동한다.
(2) 해당 커밋의 작업 디렉터리와 스테이지 영역 상태로 업데이트 된다.

detached HEAD

git checkout 등의 명령으로 HEAD가 특정 branch 가 아닌 특정 commit 을 가리키는 경우 detached HEAD(분리된 헤드) 상태라고 한다. branch와 분리된 상태라는 뜻이다. 이 때에는 branch를 가리키지 않고 있으므로, 작업을 저장하려면 새로운 branch 를 생성해야한다. 이 점을 주의하자.

switch 와 restore 로 대체됨

git 2.23 버전 이후부터는 checkout의 역할을 더 명확히 분리하기 위해 git switchgit restore로 대체 사용이 권장된다.

명령어 설명
git switch 브랜치 전환
git restore 파일 복원

checkout 명령어

명령어 설명

HEAD를 다른 브랜치의 최신 커밋이나 현재 현재 브랜치의 과거 커밋, 또는 아예 특정 커밋을 지정해서 이동시키는 명령어.

기본 사용법

1
2
3
4
5
6
7
git checkout <branch name>        # 특정 브랜치의 최신 커밋으로 이동
git checkout <commit ID>          # 특정 커밋으로 이동 (detached HEAD)
git checkout HEAD~                # 현재 HEAD가 가리키는 commit의 직전 커밋으로 이동
git checkout HEAD~3               # 현재 HEAD가 가리키는 commit의 3전 커밋으로 이동
git checkout -                    # 직전 브랜치 (이전 HEAD 위치) 로 이동
git checkout <대상> <-- file>      # 지정 파일만 해당 커밋 상태로 되돌린다.
git checkout -b <new branch name> # 새로운 브랜치를 생성하고, 동시에 해당 브랜치로 전환

옵션

옵션 full name 설명
<branch name>   지정 브랜치의 최신 커밋으로 이동
<commit ID>   지정 커밋으로 이동
HEAD~ or HEAD^   현재 브랜치의 직전 커밋으로 이동
HEAD~~ or HEAD^^   현재 브랜치의 2전 커밋으로 이동
HEAD~n   현재 브랜치의 n전 커밋으로 이동
-- <file>   지정 파일만 복원
-b <new branch name> branch 새로운 브랜치를 생성하고, 해당 브랜치로 전환
-   직전 브랜치로 이동

예시

(1) 직전 커밋으로 이동

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
# 첫 번째 커밋 : 파일 생성
echo '#!/bin/bash' > test.sh
git add ./test.sh
git commit -m "first commit"

# 두 번째 커밋 : 파일 수정
echo "echo Hello Linux" >> test.sh
git commit -am "second commit"

# 세 번째 커밋 : 파일 수정
echo 'echo $0 $1 $2' >> test.sh
git commit -am "third commit"

# git log
git log --oneline
>> c175163 (HEAD -> main) third commit
>> cbf9cc6 second commit
>> 37b90cc first commit

# 직전 커밋으로 이동
git checkout HEAD~

# git log
git log --oneline
>> cbf9cc6 (HEAD) second commit # detached HEAD
>> 37b90cc first commit

git log --all --oneline
>> c175163 (main) third commit
>> cbf9cc6 (HEAD) second commit # detached HEAD
>> 37b90cc first commit

(2) 지정 브랜치로 이동

1
2
3
4
5
6
7
8
9
10
# 지정 브랜치로 이동  
git checkout main
>> Previous HEAD position was cbf9cc6 second commit
>> Switched to branch 'main'

# git log
git log --all --oneline
>> c175163 (HEAD -> main) third commit
>> cbf9cc6 second commit
>> 37b90cc first commit

(3) n전 커밋으로 이동

1
2
3
4
5
6
7
# n전 커밋으로 이동
git checkout HEAD~1

# git log
git log --oneline
cbf9cc6 (HEAD) second commit
37b90cc first commit

(4) 새로운 브랜치를 생성하면서 HEAD 이동

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# 새로운 브랜치를 생성하면서 HEAD 이동
git checkout -b new_branch
>> Switched to a new branch 'new_branch'

# git log
git log --oneline
>> cbf9cc6 (HEAD -> new_branch) second commit
>> 37b90cc first commit

# 파일 수정 및 커밋
echo "another branch" >> ./test.sh
git commit -am "4th commit at new branch"

# git log
git log --oneline
>> 41309a0 (HEAD -> new_branch) 4th commit at new branch
>> cbf9cc6 second commit
>> 37b90cc first commit

git log --all --oneline --graph
>> * 41309a0 (HEAD -> new_branch) 4th commit at new branch
>> | * c175163 (main) third commit
>> |/  
>> * cbf9cc6 second commit
>> * 37b90cc first commit

(5) 특정 커밋으로 이동

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 특정 커밋으로 이동
git checkout 37b9

# git log
git log --oneline
>> 37b90cc (HEAD) first commit

# git log all graph
git log --oneline --all --graph
>> * 41309a0 (new_branch) 4th commit at new branch
>> | * c175163 (main) third commit
>> |/  
>> * cbf9cc6 second commit
>> * 37b90cc (HEAD) first commit

마지막 상태를 그림으로 나타내면 아래와 같다.

Reference

UNIX시스템 - 김희천,김진욱 저