by museonghwang

Git으로 버전 관리하기 기본 흐름 정리

|

image


현재 VSCode로 Git을 자주 사용하는데 기계적으로 사용하며, 기본적인 CLI 명령어를 자주 쓰지 않아 쉽게 잊어버린다. 이번 기회에 Git을 이용한 버전 관리에 대한 기본 흐름을 정리하려한다. 글 구성은 다음과 같다.

  1. 깃 저장소 만들기
  2. 버전 만들기
    • 2.1 스테이지와 커밋 이해하기
    • 2.2 작업 트리에서 문서 수정하기
    • 2.3 수정한 파일을 스테이지에 올리기 - git add
    • 2.4 스테이징한 파일 커밋하기 - git commit
    • 2.5 스테이징과 커밋 한꺼번에 처리하기 - git commit -am
  3. 커밋 내용 확인하기
    • 3.1 커밋 기록 자세히 살펴보기 - git log
    • 3.2 변경 사항 확인하기 - git diff
  4. 버전 만드는 단계마다 파일 상태 알아보기
    • 4.1 tracked 파일과 untracked 파일
    • 4.2 unmodified, modified, stage 상태
  5. 작업 되돌리기
    • 5.1 작업 트리에서 수정한 파일 되돌리기 - git restore
    • 5.2 스테이징 되돌리기 - git restore –staged
    • 5.3 최신 커밋 되돌리기 - git reset HEAD^
    • 5.4 특정 커밋으로 되돌리기 - git reset 해시
    • 5.5 커밋 변경 이력 취소하기 - git revert




1. 깃 저장소 만들기

깃으로 버전 관리를 하려면 폴더 안에 버전이 저장되는 공간이 필요한데 이것을 저장소(repository) 라고 합니다. 깃 저장소를 만들기 전에 git-practice 라는 새로운 디렉터리를 만들겠습니다.

$ mkdir git-practice
$ cd git-practice


git-practice 디렉터리 안의 내용을 살펴보겠습니다.

$ ls -la

image


화면에 두 줄짜리 결과가 나타날 것입니다. 아직 아무 파일도 만들지 않았으므로 파일이 하나도 없습니다. 이 디렉터리(git-practice)에 저장소를 만들기 위해 터미널에 다음과 같이 입력합니다. 현재 디렉터리에서 깃을 사용할 수 있도록 초기화하는 것 입니다.

$ git init


‘Initialized empty Git repository…’ 라는 메시지가 나타난다면 이제부터 git-practice 에서 깃을 사용할 수 있습니다. 터미널에 있는 파일 경로 끝에 master 라고 표시되어있는데, 이제 git-practice 디렉터리에는 깃을 위한 저장소가 생겼다는 의미 입니다.

image


ls 명령을 사용해서 다시 한번 디렉터리 안의 내용을 확인해 보겠습니다. 다음과 같이 입력하세요.

$ ls -la

image


.git 이라는 디렉터리가 생겼습니다. 이제 이 폴더는 깃을 사용하면서 버전이 저장될 저장소(repository) 입니다.




2. 버전 만들기

프로그램 개발에서 수정 내용이 쌓이면 새로 번호를 붙여서 이전 상태와 구별하는데, 이렇게 번호 등을 통해 구별하는 것을 버전이라고 합니다. 깃에서도 문서를 수정할 때마다 버전을 만들면서 이전 상태와 구별하는데, 깃에서 버전 이란 문서를 수정하고 저장할 때마다 생기는 것 입니다. 깃에서 버전을 관리하면 원래 파일 이름은 그대로 유지하면서 파일에서 무엇을 변경했는지를 변경 시점마다 저장할 수 있으며, 버전마다 작업한 내용을 확인할 수 있고, 그 버전으로 되돌릴 수도 있습니다.


2.1 스테이지와 커밋 이해하기

깃에서 버전을 만드는 단계를 살펴보겠습니다.

image


  • 작업 트리(working tree)
    • 작업 트리는 파일 수정, 저장 등의 작업을 하는 디렉터리
    • 작업 디렉터리(working directory)
    • 즉, 우리 눈에 보이는 디렉터리가 바로 작업 트리
  • 스테이지(stage)
    • 스테이지는 버전으로 만들 파일이 대기하는 곳
    • 스테이징 영역(staging area)
    • 예를 들어 작업 트리에서 파일 10개를 수정했는데 4개만 버전으로 만들려면 이 파일 4개만 스테이지로 넘겨주면 됩니다.
  • 저장소(repository)
    • 저장소는 스테이지에서 대기하고 있던 파일들을 버전으로 만들어 저장하는 곳


스테이지와 저장소는 눈에 보이지 않습니다. 깃을 초기화했을 때 만들어지는 .git 디렉터리 안에 숨은 파일 형태로 존재하는 영역이기 때문입니다. .git 안에 숨어 있는 스테이지와 저장소 영역을 상상하며 깃이 버전을 만드는 과정을 살펴보겠습니다.

hello.txt 파일 문서를 수정하고 저장하면 그 파일은 작업 트리 에 있게 됩니다. 그리고 수정한 hello.txt 파일을 스테이지 에 넣습니다.

image


파일 수정을 끝내고 스테이지에 다 넣었다면 버전을 만들기 위해 깃에게 커밋(commit) 명령을 내리면 새로운 버전이 생성되면서 스테이지에 대기하던 파일이 모두 저장소 에 저장됩니다.

image


정리하면, 먼저 작업 트리에서 문서를 수정하면, 수정한 파일 가운데 버전으로 만들고 싶은 것을 스테이징 영역, 즉 스테이지에 저장합니다. 그리고 스테이지에 있던 파일을 저장소로 커밋하면 버전이 만들어집니다.


2.2 작업 트리에서 문서 수정하기

앞에서 만든 git-practice 디렉터리에 새로운 파일을 만들고 수정해 보겠습니다. 앞에서 git-practice 디렉터리에서 깃을 초기화했으므로 이제부터 git-practice 디렉터리에서 버전 관리를 할 수 있습니다.

$ git status

image


깃의 상태를 보여 주는 메시지가 나타나는데 어떤 의미인지 간단히 살펴보겠습니다.

  • On branch master : 현재 master 브랜치에 있습니다.
  • No commits yet : 아직 커밋한 파일이 없습니다.
  • nothing to commit : 현재 커밋할 파일이 없습니다.


git-practice 디렉터리에 hello.txt 라는 새로운 파일을 만들어 보겠습니다. Vim 편집기가 열리면 또는 I 또는 A 를 눌러 입력 모드로 바꿉니다. 간단하게 숫자 1 을 입력한 후 Esc 를 눌러 ex 모드로 바꾼 후 :wq 를 입력하고 Enter 를 누릅니다. 문서가 저장되면서 편집기가 종료됩니다.

$ vim hello.txt

image


터미널 창으로 돌아와서 ls -la 명령을 입력하면 방금 만든 hello.txt 파일이 디렉터리 안에 만들어집니다.

image


깃의 상태를 다시 한번 확인해 보겠습니다. branch masterhello.txt 라는 untracked files 가 있다고 합니다. 깃에서는 버전을 아직 한 번도 관리하지 않은 파일을 untracked files 라고 합니다.

$ git status

image


지금까지 작업 트리에서 문서 파일을 만들어 봤습니다. 그림으로 나타내면 다음과 같습니다.

image


2.3 수정한 파일을 스테이지에 올리기 - git add

작업 트리에서 파일을 만들거나 수정했다면 스테이지에 수정한 파일을 추가합니다. 이렇게 깃에게 버전 만들 준비를 하라고 알려 주는 것스테이징(staging) 또는 스테이지에 올린다 라고 표현합니다.

깃에서 스테이징할 때 사용하는 명령git add 입니다. 터미널에 다음과 같이 입력해도 아무 내용도 나타나지 않지만, 그렇다고 아무 일도 안 한 것은 아닙니다.

$ git add hello.txt


그렇다면 무엇이 바뀌었는지 깃의 상태를 확인해 보겠습니다. 볼까요?

$ git status

image


untracked files: 이라는 문구가 changes to be committed: 으로 바뀌었습니다. 그리고 hello.txt 파일 앞에 new file: 이라는 수식어가 추가로 나타납니다. '새 파일 hello.txt를 (앞으로)커밋할 것이다.' 라는 뜻 입니다.

수정한 파일 hello.txt스테이지에 추가되었고, 이제 버전을 만들 준비를 마쳤습니다. 그림으로 나타내면 다음과 같습니다.

image


2.4 스테이징한 파일 커밋하기 - git commit

파일이 스테이징 영역에 있다면 이제 버전을 만들 수 있습니다. 버전 만드는 것을 깃에서는 커밋(commit)한다 라고 합니다. 커밋할 때는 버전의 변경 사항을 확인할 수 있도록 메시지를 함께 기록해 두어야 합니다.

깃에서 파일을 커밋하는 명령git commit 입니다. 그리고 한 칸 띄운 후에 -m 옵션을 붙이고 커밋과 함께 저장할 메시지, 즉 커밋 메시지를 작성합니다.

$ git commit -m "message1"


커밋한 후에 결과 메시지를 보면 파일 1개가 변경되었고(1 file changed), 파일에 1개의 내용이 추가되었다(1 insertion(+)) 고 나타납니다. 스테이지에 있던 hello.txt 파일이 저장소에 추가된 것입니다.

image


커밋한 후 깃의 상태를 확인하겠습니다.

$ git status

image


버전으로 만들 파일이 없고(nothing to commit), 작업 트리도 수정 사항 없이 깨끗하다(working tree clean)고 나타납니다. 버전이 제대로 만들어졌는지 확인하겠습니다. 저장소에 저장된 버전을 확인할 때log 명령을 사용합니다.

$ git log

image


방금 커밋한 버전을 설명하는 정보가 나타납니다. 커밋을 만든 사람과 시간, 커밋 메시지가 함께 보입니다. 수정한 파일을 커밋하면 이렇게 수정과 관련된 여러 정보를 함께 저장할 수 있고 필요할 때 확인할 수도 있습니다. 이렇게 스테이지에 있던 hello.txt 파일의 버전이 만들어졌습니다. 이 개념을 그림으로 나타내면 다음과 같습니다.

image


2.5 스테이징과 커밋 한꺼번에 처리하기 - git commit -am

수정한 파일을 하나씩 스테이지에 올려 두었다가 한꺼번에 커밋할 수도 있지만, 수정한 내용을 스테이지에 올리는 동시에 커밋까지 처리할 수도 있습니다. commit 명령에 -am 옵션을 사용하면 스테이징과 커밋을 한꺼번에 처리할 수 있습니다. 단, 이 방법은 한 번이라도 커밋한 적이 있는 파일을 다시 커밋할 때만 사용할 수 있습니다.

앞에서 만들었던 hello.txt 파일을 다시 수정해서 스테이징과 커밋을 한꺼번에 해보겠습니다. Vim이 열리면 입력 모드로 바꾸어 숫자 ‘2’ 를 추가한 후 Esc 를 누르고 :wq 를 입력해 문서를 저장하면서 편집기를 종료합니다.

$ vim hello.txt

image


앞에서는 수정한 파일을 스테이지에 올리고 커밋하는 것을 git add 명령과 git commit 명령을 사용해서 처리했습니다. hello.txt 파일은 이전에 커밋한 적이 있으므로 git commit 명령에 -am 옵션을 붙여서 스테이징과 커밋을 한꺼번에 처리할 수 있습니다. 스테이징과 커밋 과정이 한꺼번에 보일 것입니다.

$ git commit -am "message2"

image


방금 커밋한 버전에 어떤 정보가 들어 있는지 확인해보겠습니다.

$ git log

image




3. 커밋 내용 확인하기

지금까지 버전 만드는 방법을 알아보았습니다. 이제는 만든 버전을 확인하고, 버전마다 어떤차이가 있는지 파악하면서 버전 관리하는 방법을 알아보겠습니다.


3.1 커밋 기록 자세히 살펴보기 - git log

커밋했던 기록을 살펴보는 git log 명령을 입력하면 지금까지 만든 버전이 화면에 보이고 버전마다 설명도 함께 나타납니다. 앞에서 git log 명령을 입력했을 때 나타난 화면을 더 자세히 살펴보겠습니다.

image


  • 커밋 로그 : git log 명령을 입력했을 때 나오는 정보
  • commit 항목 옆 영문과 숫자로 된 긴 문자열
    • 커밋 해시(commit hash), 또는 깃 해시(git hash)
    • 커밋을 구별하는 아이디
  • (HEAD -> master) : 이 버전이 가장 최신이라는 표시
  • Author : 버전 작성자
  • Date : 버전 생성 일자


3.2 변경 사항 확인하기 - git diff

git diff 명령을 사용하면 작업 트리에 있는 파일과 스테이지에 있는 파일을 비교 하거나, 스테이지에 있는 파일과 저장소에 있는 최신 커밋을 비교해서 수정한 파일을 커밋하기 전에 최종 검토 할 수 있습니다.

Vim 에서 hello.txt 파일을 열고 기존 내용 중에서 ‘2’ 를 지우고 ‘two’ 를 추가한 후 저장해보겠습니다.

$ vim hello.txt

image


git status 명령을 사용해 깃의 상태를 확인해 보면 hello.txt 파일이 수정되었고, 아직 스테이징 상태가 아니라고 나옵니다.

$ git status

image


방금 수정한 hello.txt 파일이 저장소에 있는 최신 버전의 hello.txt 와 어떻게 다른지 확인해 보겠습니다. 이때 git diff 명령을 사용합니다. ‘−2’ 는 최신 버전과 비교할 때 hello.txt 파일에서 ‘2’ 가 삭제되었다는 뜻이고, ‘+two’hello.txt 파일에 ‘two’ 라는 내용이 추가되었다는 뜻입니다.

$ git diff

image


이렇게 작업 트리에서 수정한 파일과 최신 버전을 비교한 후 수정한 내용으로 다시 버전을 만들려면 스테이지에 올린 후 커밋하고, 수정한 내용을 버리려면 git restore 명령을 사용해 취소합니다. 우선 다시 hello.txt 를 원래대로 되돌려 놓겠습니다. Vim 에서 hello.txt 파일을 열고 ‘two’ 부분을 숫자 ‘2’ 로 수정한 후 저장합니다.

image




4. 버전 만드는 단계마다 파일 상태 알아보기

깃에서는 버전을 만드는 단계마다 파일 상태가 달라집니다. 그래서 파일 상태를 이해 하면 이 파일이 버전 관리의 여러 단계 중 어디에 해당하는지, 그 상태에서 어떤 일을 할 수 있는지 알 수 있습니다.


4.1 tracked 파일과 untracked 파일

git status 명령을 사용하면 화면에 파일 상태와 관련된 여러 메시지가 나타납니다. 작업 트리에 있는 파일 은 크게 tracked 상태untracked 상태 로 나뉘는데 각각 무엇을 의미하는지 알아보겠습니다.

Vim 에서 hello.txt 파일을 열고 숫자 ‘3’ 을 추가한 후 저장합니다.

$ vim hello.txt

image


Vim 에 다음과 같이 hello2.txt 라는 새로운 파일을 만들어 보겠습니다.

$ vim hello2.txt

image


hello.txt 파일과 hello2.txt 파일 모두 작업 트리에 있습니다. git status 명령을 사용해 어떤 상태인지 확인해보겠습니다.

$ git status

image


앞에서 커밋했던 hello.txt 파일은 ‘Changes not staged for commit:’ 이라고 되어 있는데, 변경된 파일이 아직 스테이지에 올라가지 않았다는 뜻입니다. 그리고 파일 이름 앞에 modified: 라고 되어 있어 hello.txt 가 수정되었다는 것을 알 수 있습니다. 이렇게 깃은 한 번이라도 커밋한 파일은 계속해서 수정 사항이 있는지 추적합니다. 깃이 추적하고 있다는 뜻에서 tracked 파일 이라고 합니다.

반면에 hello2.txt 파일 앞에는 아무것도 없고 바로 위에는 ‘untracked files:’ 라고 되어 있는데, hello2.txt 파일은 한 번도 커밋하지 않았으므로 수정 내역을 추적하지 않으므로 untracked 파일 이라고 표시합니다.

수정한 hello.txt 파일과 수정하지 않은 hello2.txt 파일 모두 git add 명령을 사용해서 스테이지에 올릴 수 있습니다.

$ git add hello.txt
$ git add hello2.txt


git status 를 사용해 상태를 확인해 보겠습니다. 마지막 버전 이후에 수정한 hello.txtmodified: 라고 표시되고, 한 번도 버전 관리를 하지 않은 hello2.txtnew file: 로 표시됩니다.

image


커밋을 해보겠습니다. 이 커밋에는 hello.txt 를 수정한 내용과 새로 만든 hello2.txt 내용이 전부 포함됩니다. 커밋 메시지는 다음과 같이 작성하고, 커밋이 성공적으로 되었다면 로그를 확인해 보겠습니다.

$ git commit -m "message3"
$ git log

image


‘message3’ 라는 메시지를 붙인 커밋이 보입니다. 그런데 각 커밋에 어떤 파일이 관련되었는지 알 수 없습니다. 커밋과 관련된 파일까지 함께 살펴보려면 git log 명령에 –stat 옵션을 사용합니다.

$ git log --stat

image


가장 최근 커밋부터 순서대로 커밋 메시지와 관련 파일이 나열됩니다. message3 커밋은 hello.txt, hello2.txt 파일과 관련되어 있고, message2hello.txt 파일과 관련되었다는 것을 알 수 있습니다.


4.2 unmodified, modified, stage 상태

버전을 한 번이라도 만들었던 파일은 tracked 상태가 되는데, 파일이 tracked 상태라면 깃 명령으로 현재 작업 트리에 있는지, 스테이지에 있는지 등 더 구체적으로 알 수 있습니다. 깃의 커밋 과정에서 tracked 파일의 상태가 어떻게 바뀌는지 확인해 보겠습니다.

ls -la 명령을 사용해 git-practice 디렉터리를 살펴보면 앞에서 버전을 저장한 hello.txthello2.txt 파일이 있습니다.

image


hello2.txt 파일의 상태를 따라가 보겠습니다. 앞에서 버전을 저장한 뒤로 아직 아무 파일도 수정하지 않은 상태입니다. git status 명령을 사용해 깃의 상태와 파일의 상태를 확인해보면 작업 트리에 아무 변경 사항도 없습니다. ‘working tree clean’ 은 현재 작업 트리에 있는 모든 파일의 상태는 unmodified 라는 뜻으로 수정되지 않은 상태를 말합니다.

image


hello2.txt 파일을 수정해 보겠습니다. hello2.txt 에서 a 만 남기고 나머지 내용을 삭제한 후 파일을 저장하고 편집기를 종료합니다.

$ vim hello2.txt

image


다시 git status 명령을 실행하면 hello2.txt 파일이 수정되었고 아직 스테이지에 올라가지 않았다고 나타납니다. ‘Changes not stage for commit’ 라는 메시지가 나타나면 파일이 수정만 된 modified 상태를 뜻합니다.

image


git add 명령을 사용해 스테이지에 올리고 git status 명령을 실행하면 커밋할 변경사항이 있다고 합니다. ‘Changes to be committed:’ 라는 메시지가 나타나면 커밋 직전 단계, 즉 staged 상태입니다.

$ git add hello2.txt
$ git status

image


스테이지에 있는 hello2.txt 파일을 커밋하고 git status 명령을 실행합니다. 커밋을 끝내고 나면 hello2.txt 파일의 상태는 수정하기 직전인 unmodified 상태로 돌아갑니다.

$ git commit -m "delete b, c, d"
$ git status

image


지금까지 살펴본 것처럼 같은 파일이더라도 깃에서 버전을 만들 때 어느 단계에 있는지에 따라 파일의 상태가 바뀝니다. 파일의 상태 변화는 다음과 같이 간단하게 정리할 수 있습니다.

image




5. 작업 되돌리기

앞에서 수정한 파일을 스테이지에 올리고 커밋하는 방법까지 살펴보았습니다. 이제부터는 스테이지에 올렸던 파일을 내리거나 커밋을 취소하는 등 각 단계로 돌아가는 방법을 알아보겠습니다. 여기까지 익히고 나면 버전 관리를 훨씬 능숙하게 할 수 있습니다.


5.1 작업 트리에서 수정한 파일 되돌리기 - git restore

수천 줄이 넘는 소스를 수정했다고 가정했을때 수정한 코드가 정상으로 동작하지 않거나 다른 이유로 수정한 것을 취소하고 가장 최신 버전 상태로 되돌려야 할 때가 있습니다. 이때 작업 디렉터리에서 수정한 내용을 되돌리려면 restore 명령을 사용합니다.

먼저 Vim 편집기에서 hello.txt 파일을 열어 숫자 ‘3’‘three’ 로 수정한 후 저장하고 편집기를 종료합니다.

$ vim hello.txt

image


git status 명령을 통해 hello.txt 파일의 상태를 살펴보면 hello.txt 가 수정되었지만 아직 스테이지에 올라가 있지 않습니다. 그리고 두 번째 괄호 안의 메시지를 보면, 작업 디렉터리의 변경 사항을 취소하려면 restore 명령을 사용하라고 되어있습니다.

image


조금 전에 수정했던 hello.txt 의 수정 사항을 git restore 명령 을 통해 취소해보겠습니다. restore 명령이 정상으로 처리되면 화면에는 아무것도 나타나지 않습니다.

$ git restore hello.txt


hello.txt 파일에서 수정했던 것이 정말 취소되었는지 확인해보기 위해 cat 명령을 사용해 파일 내용을 확인해보겠습니다. 앞에서 ‘3’ 을 지우고 ‘three’ 를 추가했던 수정 내용이 사라지고 ‘3’ 이 그대로 남은 것을 확인할 수 있습니다.

$ cat hello.txt

image


5.2 스테이징 되돌리기 - git restore –staged

앞에서 파일을 수정했을 때 스테이징하지 않은 상태에서 수정을 취소하고 원래대로 되돌리는 방법을 알아봤습니다. 이번에는 수정된 파일을 스테이징까지 했을 때 스테이징을 취소하는 방법 을 살펴보겠습니다. 스테이징을 취소할 때도 restore 명령을 사용합니다.

Vim 을 사용해서 hello2.txt 를 수정해 보겠습니다. 기존 내용을 삭제하고 대문자 A, B, C, D 를 입력한 후 저장하고 편집기를 종료합니다.

$ vim hello2.txt

image


git add 명령으로 hello2.txt 파일을 스테이지에 올린 후 git status 명령으로 파일 상태를 살펴보겠습니다.

$ git add hello2.txt
$ git status

image


상태 메시지를 보면, 스테이지에서 내리려면(to unstage) **git restore –staged ** 명령을 사용하라고 되어 있습니다. 스테이징을 취소할 때는 **restore** 명령 뒤에 **--staged** 옵션을 붙이는데, 이 옵션만 사용하면 스테이지에 있는 모든 파일을 한꺼번에 되돌릴 수 있고, **--staged** 옵션 뒤에 파일 이름을 넣으면 해당 파일만 골라서 되돌릴 수 있습니다. 여기에서는 스테이지에 있는 **hello2.txt** 를 내려 보겠습니다.

$ git restore --staged hello2.txt


git status 를 사용해 파일 상태를 확인해 보면, 파일이 아직 스테이지에 올라가기 전(not staged)으로 돌아온 것을 확인할 수 있습니다.

image


5.3 최신 커밋 되돌리기 - git reset HEAD^

이번에는 수정된 파일을 스테이징하고 커밋까지 했을 때 가장 마지막에 한 커밋을 취소하는 방법을 알아보겠습니다. 커밋을 취소하면 커밋과 스테이징이 함께 취소됩니다. Vim 으로 hello2.txt 를 열어 대문자 E 를 끝에 추가하겠습니다.

$ vim hello2.txt

image


git commit 명령을 사용해 스테이징과 커밋을 함께 실행합니다. 커밋 메시지는 message4 로 하겠습니다. git log 명령을 사용해서 제대로 커밋되었는지 확인해 보겠습니다.

$ git commit -am "message4"

image


최신 커밋을 되돌리려면 git reset HEAD^ 명령을 해야합니다. HEAD^ 는 현재 HEAD가 가리키는 브랜치의 최신 커밋을 가리킵니다. git log 명령을 실행했을 때 가장 최신커밋에 (HEAD-> master) 표시가 있는데, 이렇게 되돌리면 master의 최신 커밋도 취소되고 스테이지에서도 내려집니다. 작업 트리에만 파일이 남습니다.

$ git reset HEAD^


참고로 스테이징만 취소할 때는 restore 명령을 사용하지만 커밋을 취소할 때는 reset 명령을 사용합니다. hello2.txt 파일의 커밋이 취소되고 스테이지에서도 내려졌다는 메시지가 나타납니다.

image


git log 명령으로 확인해보면 메시지가 message4 인 커밋이 사라진 것을 볼 수 있습니다. 이 방법으로 커밋을 취소하면 커밋 전에 했던 스테이징도 함께 취소됩니다.

image


5.4 특정 커밋으로 되돌리기 - git reset 해시

깃에는 파일을 수정하고 커밋할 때마다 저장된 버전들이 쌓여 있습니다. 앞에서 살펴본 git reset HEAD^ 명령으로 최신 커밋을 되돌릴 수도 있지만 특정 버전으로 되돌려 놓고 그 이후 버전을 삭제할 수도 있습니다. 특정 커밋으로 되돌릴 때git reset 명령 다음에 커밋 해시 를 사용합니다.

git reset 명령을 연습해 보기 위해 커밋을 몇 개 만들어 보겠습니다. Vim 을 사용해 rev.txt 를 만듭니다. 간단하게 영문자 ‘a’ 를 입력한 후 저장하겠습니다.

$ vim rev.txt

image


rev.txt 를 스테이지에 올린 후 커밋 메시지 R1 을 붙여 커밋합니다.

$ git add rev.txt
$ git commit -m "R1"

image


rev.txt 를 한 번 더 수정해서 영문자 ‘b’ 를 추가하고, R2 메시지와 함께 커밋합니다.

$ vim rev.txt

image


$ git commit -am "R2"

image


같은 방법으로 rev.txt 에 영문자 ‘c’ 를 추가한 후 R3 메시지와 함께 커밋하고, rev.txt 에 영문자 ‘d’ 를 추가한 후 R4 메시지와 함께 커밋합니다. 지금까지 커밋을 모두 4번 했습니다.

image


git log 명령을 사용해 지금까지 만든 커밋을 확인하면, 커밋이 4개 있고 커밋마다 커밋 해시가 함께 나타나 있습니다.

image


커밋 4개 가운데 R2 라는 메시지가 붙은 R2 커밋으로 되돌려 보겠습니다. 즉, R3 커밋과 R4 커밋을 삭제하고 R2 커밋을 최신 커밋으로 만들 것입니다.

reset 에서 커밋 해시를 사용해 되돌릴 때 주의할 점이 있습니다. 예를 들어 reset A 를 입력한다면 이 명령은 A 커밋을 리셋하는 것이 아니라 최근 커밋을 A 로 리셋합니다. 즉, A 커밋을 삭제하는 것이 아니라 A 커밋 이후에 만들었던 커밋을 삭제하고 A 커밋으로 이동하겠다는 의미입니다. 그래서 R3 커밋과 R4 커밋을 삭제하려면 그 이전 커밋인 R2 커밋을 최신 커밋으로 만들어야 합니다. 최신 커밋을 가리키는 HEADA 로 리셋한다고 생각하면 됩니다.

git reset 명령 다음에 –hard 옵션까지 입력한 후 복사한 커밋 해시를 붙여 넣습니다.

$ git reset --hard 복사한 커밋 해시

image


방금 복사해서 붙인 커밋 해시 위치로 HEAD 가 옮겨졌다고 나옵니다. 즉, 방금 복사해서 붙인 커밋이 가장 최신 커밋이 되었습니다. git log 명령을 사용해서 로그 목록을 살펴보면 의도했던 대로 R4 커밋과 R3 커밋은 삭제되고 커밋 해시를 복사했던 커밋, 즉 R2 커밋이 최신 커밋이 됐습니다.

image


하나 더 확인해보면, R4 커밋은 rev.txt‘d’ 를 추가한 것이고, R3 커밋은 ‘c’ 를 추가한 것, 그리고 R2 커밋은 ‘b’ 를 추가한 것이었습니다. R2 커밋으로 되돌렸으니 cat 명령을 사용해서 rev.txt 파일을 확인해 보면 내용에 ‘b’ 까지만 있을 것입니다. ‘c’‘d’ 를 추가했던 R4 커밋과 R3 커밋이 사라지고, R2 커밋이 최신 커밋이 되었기 때문에 ‘b’ 까지만 남은 것입니다.

image


5.5 커밋 변경 이력 취소하기 - git revert

특정 커밋으로 되돌릴 때 수정했던 것을 삭제해도 된다면 git reset 명령을 사용하면 되지만, 나중에 사용할 것을 대비해서 커밋을 취소하더라도 커밋했던 기록은 남겨 두어야 할 때가 있습니다. 즉, 변경 사항만 취소하고 커밋은 남겨 두는 것 입니다. 이럴 경우에는 git revert 라는 명령을 사용합니다.

rev.txt 파일을 한 번 더 수정해서 영문자 ‘e’ 를 추가하고, 수정한 rev.txtR5 라는 메시지와 함께 커밋하겠습니다.

image


$ git commit -am "R5"

image


git log 를 입력해 버전을 확인하면, rev.txt 파일에 대해 R1R2, R5 라는 버전 3개가 만들어졌습니다.

image


가장 최근에 커밋한 R5 버전을 취소하고, R5 직전 커밋인 R2 로 되돌아가려고 합니다. 여기에서는 취소하는 R5 버전을 삭제하지 않고 남겨 두려고 합니다. revert 명령을 사용하고 명령 뒤에 취소할 버전, 즉 R5 의 커밋 해시를 지정합니다. 먼저 revertR5 커밋 해시를 복사합니다. revert 명령을 사용해서 R5 커밋을 취소하겠습니다.

$ git revert 복사한 커밋 해시


기본 편집기가 자동으로 나타나면서 다음과 같이 커밋 메시지를 입력할 수 있습니다. 커밋 메시지 맨 위에는 어떤 버전을 revert 했는지 나타납니다. 커밋을 취소하면서 남겨 둘 내용이 있다면 문서 맨 위에 입력하고 저장합니다.

image


R5 버전이 revert 되었다는 간단한 메시지가 나타나는데, 실제로 버전이 어떻게 바뀌었는지 git log 를 통해 확인해보겠습니다.

$ git log


로그에 R5revert 한 새로운 커밋이 생겼습니다. 그리고 기존의 R5 역시 사라지지 않았습니다. R5 버전을 지우는 대신 R5에서 변경했던 내용만 취소하고, R5를 취소했다는 커밋을 새로만든 것 입니다.

image


방금 취소한 R5 커밋은 rev.txt 문서에 영문자 ‘e’ 를 추가한 것이었습니다. R5 커밋을 취소한 것이 문서에도 반영되었는지 확인해 보겠습니다.

$ cat rev.txt


앞에서 추가한 ‘e’ 가 없어진 것을 볼 수 있습니다. 이렇게 revert 명령을 사용하면 커밋 자체를 삭제하지 않으면서도 변경한 이력을 취소할 수 있습니다.

image