지난번 글에서는 우리가 무엇을 알아보았을까?
일단 우리는 깃이 파일 관리를 수월하게 하기 위한 영역 분리와 그에 따른 파일의 상태들을 살펴보았다.
이렇게 하는 이유는 당연하게도 버전 관리를 위해서이고 우리는 그 근본인 commit에 대해서 이번에 알아보려고 한다.
commit을 네이버 사전이나 구글에 물어보면 어떤 뜻으로 알려줄까?
- (그릇된 일·범죄를) 저지르다[범하다]
- 자살하다
- (엄숙히) 약속하다
…- ~을 마음에 새기다[기억하다]
- ~을 적어 두다
의미들이 심상치 않다. 어떠한 이유로 이 단어를 했는지는 모르겠지만 가장 가까운 단어는 10번의 ‘적어 두다’라는 단어일 것이다.
(물론 ‘저지르다’라는 말이 맞는 경우를 코드를 짜다보면 느낀…)
즉 commit은 의미있는 변경 작업들을 저장소에 기록하는 동작을 말하는 것이다.
코드 변경 시점을 저장해둠으로 잘못된 동작을 발견했을 때 특정 시점으로 돌아갈 수 있기 때문이다.
깃의 commit은 새롭게 변경된 부분만 추출해서 저장한다.
즉 시간에 따라서 변화하는 내용만 관리하고 코드가 변화된 시간 순서에 따라서 영구적으로 저장하는 것이다.
위 그림처럼 시간에 따른 변화를 기록하고, 이 기록은 부모 커밋을 기반으로 변화된 부분만 새로운 커밋으로 생성한다.
우리는 이 commit이란게 ‘시간에 따라서 변화되는 내용을 관리한다’ 라고 위에서 알아봤는데
이게 어떻게 동작하는건가?
이걸 알아보기 위해서 앞에서 영역과 파일의 상태를 알아보았던 것이고 좀 더 내부적인 내용도 처음에 알아보았다.
우선 파일의 상태가 추적가능해야 한다. 뭐가 떠오르는가? 맞다 바로 앞에서 말한 Tracked 상태인 것이다.
파일을 새로 생성했으면 Untracked 상태일 것이니 git add를 통해서 Tracked로 바꾸고, 스테이지 영역으로 옮길 수 있을 것이다.
이 과정을 같이 따라하면서 해보자.
아무런 폴더나 만들고 해당 폴더에 간단한 파일을 만들어보자.
아 그리고 git init은 해줘야한다.
이렇게 파일을 만든다고 해서 Tracked가 되는 것은 아니다. Tracked로 바꾸고 스테이지 영역으로 올리기 위해서 git add를 실행해보자.
그 전에 git status를 먼저 해보고 하는게 좋다. git status를 통해서 등록 상태를 확인할 수 있기 때문이다.
git status
git add hello.js
git status
이렇게 친절하다니. 추적하지 않는 파일(Untracked)에 우리의 hello.js가 있는 것이 보인다.
거기다 어떻게 넣을지도 알려준다. git add를 하고 나서의 상태를 확인해보자.
commit 할 변경 사항이라고 해서 hello.js가 올라간 것을 볼 수 있다.
변경 사항을 찾았다는건 지금 hello.js 파일은 Tracked 상태가 된 것이다. 오예!
보니까 스테이지를 해제할 수 있다 해서 친절하게 무언가를 알려준다. 한 번 해볼까?
오호라. 해당 명령어를 사용하니 처음으로 돌아갔다. 즉 Untracked 상태로 변경된 것이다.
저 명령어는 깊게 살펴볼 것은 아니니 일단 간단히 설명하면
파일을 등록한 후 커밋하지 않고 바로 삭제하려면 해당 명령어를 통해서 가능하다. 결과는 위와 같다.
하지만 한 번이라도 커밋을 했다면 reset 명령어를 통해서 진행해야 한다. 이거는 다음 기회에 더 알아보자.
우리는 이제 파일을 Tracked로 만들 수 있다.
그러면 본격적으로 commit을 해봐야 한다. 이전에 근데 몇 개만 더 알아가자.
commit에는 HEAD라는 포인터 개념이 있다. HEAD는 commit을 가리키는 묵시적인 참조 포인터이다.
좀 더 간단하게는 최종적인 커밋 작업의 위치를 말하는 것이다.
이게 왜 있을까?
우리는 시간 순서대로 파일의 변화를 기록 중에 있고 이를 부모 commit을 기준으로 작업한다고 위에서 언급했다.
그러려면 매 순간 가장 최신의 부모를 알고 있어야 할 것이다. 그러기 위해서 HEAD라는 포인터 개념이 필요한 것이다.
commit은 파일의 변화를 깃 레포지토리에 영구적으로 기록하는 행위이다.
근데… 어떻게 기록을 하는 것인가?
깃은 스냅샷 방식을 이용한다.
파일을 복사하는 방식으로 하는 것이 아닌 파일에서 변경된 부분을 찾아 수정된 내용만 저장하는 것이다.
이러한 방식이 마치 사진을 찍는 것과 같다고 생각해 스냅샷 방식이라는 이름이 붙은 것이다.
이렇게 저장하는 방식을 통해서 빠르게 버전의 차이점을 처리하고, 용량을 적게 사용할 수 있다.
이제 본격적으로 한번 commit을 해보자
git commit
당황스럽다 뭐지 싶다.
이것은 vi 에디터라는 것으로 이 기록이 무엇을 의미하는 것인지, 어떤 변경 사항이 있는 것인지 적을 수 있는 공간이다. (물론 이것을 사용하지 않는 방법도 있지만 일단 써보자)
i를 눌러 작성 모드로 변경 후 글을 작성해보자. 다 작성했으면 ESC를 누르면 일반 모드로 변경할 수 있고 이후 해당 내용으로 commit을 하려면 :를 누르고 wq를 입력후 엔터를 하면 된다.
정상적으로 commit이 되었는지 두 가지 방법을 통해서 살펴보자
하나는 이전에 해본 git status 이다.
정상적으로 보인다. 왜냐하면 커밋할 사항이 없다는 것은 Untracked가 없고 Tracked된 파일들이 레포지토리에 있는 저장 상황과 동일하다는 것이다.
그러면 git log를 한 번 해보자.
git log 명령어는 시간 순으로 commit 기록을 출력해준다.
우리가 넣은 commit이 잘 등록된 것으로 보인다. 해당 화면에서 나가고 싶으면 :q 를 해주면 된다.
만약 이 commit에 있는 이러한 값들이나 정보들이 궁금하다면 이전 블로그 글들을 살펴보면 대략 알 수 있다.
한 번 더 commit을 진행해보자. 간단히 hello.js에 한 줄 정도 추가해서 해볼 계획이다.
추가를 하고 git status를 통해 상태를 확인해보자.
달라졌다. 바로 추적하지 않은 파일이라는 말이 아닌 수정함 이라는 태그로 hello.js가 나온다.
맞다 이게 바로 Modified 상태인 것이다. 이때 commit을 하기 위해서 다시 스테이지로 올려줄려면 어떻게 해야 하는가? git add라고 생각했으면 정답이다.
그 전에 항상 근본을 알아야 한다. 왜 우리가 git을 사용하는가? 버전 관리를 쉽게 하기 위해서이다. 그 중 하나의 예시로 이전 버전으로 바로 갈 수 있다는 것이다. 지금 이 상황에서 git checkout . 또는 git checkout — hello.js 를 입력해보자
git checkout .
git checkout -- hello.js
어떻게 변했는가? 아마 이전 상황으로 돌아갔을 것이다. 바로 직전 commit때의 상태로 돌리기 위해서는 해당 커맨드를 사용하면 된다.
귀찮지만 다시 코드를 새로 작성하고 git add를 해주자.
이후 이번에는 vi 에디터를 안거치고 commit 메시지를 남길 수 있는 커멘드를 배워보자. 바로 아래 처럼 해주면 된다.
이번에도 log를 확인해볼 것인다. 하지만 옵션을 조금 붙여서 진행해보자 아래를 따라해보자.
git commit -m "작성하고 싶은 메시지"
git log --prettey=short
두 번째 commit이 잘 생성된 것을 볼 수 있다.
만약에 내가 첫 번째 commit이 생성된 시점으로 돌아가려면 어떻게 해야 할까?
일단 우리가 알고 있는 것은 git checkout . 같은 명령어인데 이거는 생각해보면 현 시점에서 레포지토리와 다른 부분을 돌리는 것이다. 지금은 사용할 수 없을 것이다.
아래를 따라해보자
git checkout 여러분의 첫 번째 commit의 hash 값
놀랍게도 이전으로 돌아왔다.
변경 사항들을 저장해둔 덕분에 해당 위치로 코드를 돌리는 작업이 굉장히 수월하게 된 것을 볼 수 있다.
만약 이 때 log를 찍어보면 어떨까? git log 를 실행해보자(옵션을 넣어도 좋고 아니여도 좋다.).
log가 마치 우리가 이 commit만 해둔 상황마냥 나왔다.
돌아온 것도 신기하고 HEAD가 움직인 것도 볼 수 있다. 근데 불안하다.
이전 commit이 사라진건가? 그러면 우리 작업이(물론 한 줄이지만) 다 날아가는 거 아닌가?
다행인건 그것은 아니다. 우리는 checkout 전 log에서 괄호 안에가 어떻게 되있었는가?
HEAD → master 라고 되어있다. 이 master란건 무엇인가?
이는 브렌치를 배우고 나서 더 알아볼 내용이지만 지금 변경을 하고 있는 git의 한 줄기라고 보면 된다. 단순하게는 그냥 지금까지 commit의 맨 끝단을 가리킨다고 보면 된다.
이를 감사하게도 저장하고 있는 것을 볼 수 있는데 바로 .git 폴더의 ref 폴더를 봐보자
heads 중에 master 라는 것을 볼 수 있다.
한번 그러면 git checkout master 라고 두근두근 하면서 작성해보자.
폼 대단하다 깃.
우리는 이렇게 실습도 해보면서 어떻게 과거의 상태로 돌아오는지, 그리고 commit이라는 것이 쌓이는 과정을 볼 수 있었다.
우선 우리는 나름의 핵심 기능인 commit을 알아볼 수 있었다.
물론 도움이 되는 글이었는지, 따라오면서 잘 알 수 있는 것인지 그것은 잘 모르겠다.
다음에는 우리가 살펴보지 못한 영역을 탐험해볼지 브랜치라는 개념을 알아볼지 잘은 모르겠다.
다만 빠른 시일 내에 돌아올 것을 알리며 긴 두서없는 글을 읽어주신 분이 있다면 감사함을 표하면 마무리하겠다.
총총총…