Git - Commit

본 포스트는 코드 스쿼드의 커밋하면 스테이지의 내용은 어디로 갈까를 시청하고 정리한 포스트입니다.


목차

버전관리 소트트웨어인 Git은 객체로 구성되어 있다. Git을 구성하는 객체는 다음과 같다.

  • Commit
    • 우리가 가장 신경써야할 Commit(커밋) 이다.
  • Tree
    • 커밋에 포함된 파일 목록.
  • Blob
    • 파일의 내용
    • 파일 내용 변경되면, 객체주소 변경되면서 git status 에서 modified 메세지 출력.
    • git hash-object file.txt 로 file의 객체주소 확인 가능
  • Tag
  • reference
    • branch
    • HEAD

Git status

CLI 환경에서 git status 명령어를 입력하면 알 수 있는 것들이다.

  • 작업 디렉토리
  • 스테이지
  • Commit <HEAD>

status 명령어를 통해서는 local repo에 어떤 파일이 올라갔고, 어떤 파일이 아직 local repo에 동기화되지 않은지를 볼 수 있다. 이를 위해서는 우선 Git에서 데이터가 어떻게 이동되는지 경로를 먼저 보도록 하자.

workspace는 프로그래머가 작업하고 있는 공간을 의미한다. git이 추적하지 않는 상태이다.

git을 설치하고, git에 의해 추적하길 원한다면 git add <file> 명령어를 통해 파일들을 index에 올려두어야 한다. index에 있는 파일들만 local repository로 커밋할 수 있기 때문이다.

local repository는 작업이 끝난 파일들이 저장된 최종 저장소라고 할 수 있다. 이를 원격 저장소와 연동하여 push 명령어로 서버에 git을 보낼 수 있다.

터미널에서 직접 보도록 하자.

opentutorials_git 이라는 폴더를 생성 후, code.txt, code2.txt, code3.txt 파일을 각각 생성하여 각기 다른 상황을 만들어보았다. 현재 파일들의 상태는 다음과 같다.

  • code.txt

    • 파일 생성

      • vim code.txt
    • stage에 add후, 커밋

      • git add code.txt
      • git commit -m "add code.txt"
    • 파일 수정

    • 다시 stage에 올려둠

      • git add code.txt
  • code2.txt
    • 파일 생성
      • vim code2.txt
    • stage에 add후, 커밋
      • git add code2.txt
      • git commit -m "add code2.txt"
    • 파일 수정
  • code3.txt

    • 파일 생성
    • 파일 수정

위 이미지를 보면 의도한대로 세 파일 모두 전부 다르게 git에 의해 tracking(추적)되고 있음을 알 수 있다. 먼저 code.txt부터 살펴보도록 하자.

code.txt는 커밋한 이후 파일에 변경이 발생하여, 다시 stage에 올려두어 커밋할 준비가 되어있는 상태의 파일이다. 커밋할 준비가 되어 있는 파일, 즉 stage에 올라가 있고 변경사항이없는 최신상태일 경우 파일이름은 초록색으로 표시된다.

code2.txt는 커밋한 이후 파일에 변경이 발생했지만 아직 stage에 올려두진 않은 상태다. 변경이 발생한 파일이 커밋할 준비가 되어 있지 않기 때문에 code.txt와 달리 빨간색으로 파일 이름이 표시됨을 알 수 있다.

code3.txt는 파일 생성 직후, git 명령어를 입력하지않은 상태에서 한 차례 수정한 파일이다. git에 의해 추적되지 않고 있기 때문에 code.txt나 code2.txt와 달리 파일에 변경사항이 발생했음에도 불구하고 modified라는 표시가 출력되지 않는다. 그래서 (use "git add <file>..." to include in what will be committed) 라는 메세지를 친절하게 출력하여 git에 의해 파일이 추적되도록 stage에 파일을 올릴것을 의도한다.

위의 이야기를 제대로 이해하기 위해서는 커밋(Commit)이 객체라는 사실을 숙지해야만 한다.


괜찮다. 포기할거면 지금 포기해도 좋다.
나중에 다시 필요해졌을 때 돌아오자..

Git Commit

커밋(Commit)은 Git에서 작업단위를 의미한다. 파일 하나를 수정할 때마다 커밋을 하는게 아니라, login기능을 구현했다면 login 기능을 구현하는데 사용한 파일들을 묶어서 하나의 커밋 객체를 생성하는 방식이다.

git commit 이라는 명령어를 통한 제어는 다음과 같은 일을 수행한다.

  • 스테이지에 있는 내용을 가지고 새로운 커밋 객체를 생성
  • 이전 HEAD가 가리키는 커밋이 새로운 커밋의 부모가 됨
  • Commit에 포함된 정보
    • Commit Message
    • Tree-blobs
    • Parent Commit
  • 커밋 이후엔 작업 디렉토리와 스테이지, HEAD 커밋의 내용이 모두 같아진다

git의 원리를 파악하는데 유용한 소프트웨어, Gistory를 통해 위에서 만든 git의 객체들을 구경해보자.

Gistory로 git의 객체를 확인하려면, 당연하게도 git의 객체를 생성해야 한다. 따라서 위의 예제 상황에서 code.txt를 “changed code.txt”라는 메세지와 함께 커밋하였다.

이미지를 보면, 객체가 생성되었음을 알 수 있다. 커밋 메세지도 볼 수 있다.

여기서 tree와 parent를 살펴볼건데, 위의 이미지는 해당 객체의 tree를 클릭했을 때 볼 수 있는 화면이다. 해당 객체가 어떤 파일들을 포함하고 있는지를 보여준다. blob은 위에서 파일 객체라고 하였다. 이를 클릭하면 아래처럼 파일의 내용을 볼 수 있다.

code.txt에 입력한 코드 두 줄이 보인다.

1
2
code1
changed

이제 parent를 클릭해보자.

해당 커밋 객체의 부모 객체를 보여준다. code.txt를 커밋하기 전의 커밋은 code.txt와 code2.txt를 “add code.txt and code2.txt” 라는 메세지와 함께 커밋을 한 것이다. 이 메세지를 부모 객체에서 확인할 수 있다.

그리고 ./logs/HEAD/를 들어가면 git으로 제어하고 있는 워크스페이스 즉 local repository에서 생성된 모든 커밋 객체를 확인할 수 있다. 커밋 객체들이 HEAD의 노드임을 알 수 있다.

오래 전 커밋한 객체도 보이고, 멘 아래 방금 커밋한 메세지의 커밋 객체도 볼 수 있다.

다소 복잡하지만 git을 이해하기 위해 필요한 필수 과정이라고 생각한다. 원리를 이해해야 협업과정에서 발생할 수 있는 여러가지 충돌에 대응할 수 있다고 생각한다.