ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Git - 4.2 Git의 원리(commit의 원리, status의 원리)
    STUDY/Git & Github 2021. 1. 5. 13:25

    #이 글은 "생활코딩" '프로젝트 관리' 강의를 기반으로 정리한 글 입니다. 

     

    지난 포스트에 이어 Git의 원리, 그중에서도 저번에 다루지 못한 commit과 status의 원리에 대해 알아보도록 하겠습니다. 

     

    git commit의 원리

    지난 번에 git add의 원리에 대해 설명하면서, 세개의 파일 f1, f2, f3.txt 파일은 add만 한 상태로 포스트를 마무리 했었습니다. 오늘은 그 파일들을 commit 해보면서 commit의 원리에 대해 알아보도록 하겠습니다.  우선 git status 를 통해, 현재 상태를 먼저 보도록 하겠습니다.

    아래의 사진과 같이 세개의 파일 f1, f2, f3.txt 이 stage area에 올라가 있는것을 확인할 수 있습니다.  이제 이 파일들을 commit 해보면서 .git 디렉토리에서는 어떤 일이 일어나는지 한번 살펴보도록 하겠습니다.

     

    현재 상태, git commit 이전

     

    먼저 f1.txt를 commit 해보겠습니다. (commit message : "1") 그리고 gistory를 갱신해보면, 여러 가지 새로운 파일들이 생성되고, 그 중에 눈에 띄는 파일은 바로 새로운 ./object 파일입니다. 

     

    git commit f1.txt

     

    commit 이후, gistroy의 모습

    commit 시, 파일을 생성하여 add한 것과 동일하게 우리가 생성한 버전도 마치 파일의 내용처럼 ./object 에 생성되게 됩니다. 이를 통해, commit 도 git의 내부에서는 하나의 object(객체)로 취급된다는 사실을 알 수 있습니다.

     

    이 object 파일의 내용을 한번 자세히 살펴보겠습니다. 

    ./objects/cc/2b59e62e5a1881965729bfce78cba65f43d973  앞서 git add에서 살펴본 것과 동일하게, SHA-1 알고리즘을 이용한 40글자의 해시를 이용하여, 앞의 두글자는 디렉토리명, 나머지 38글자는 파일명으로 사용하고 있습니다.

    파일 안의 내용을 보면, tree , author(저자), commiter(커밋을 한 사람), commit message 이렇게 네 가지의 내용으로 구성되어있습니다.  가장 눈에 띄는 것은 바로 "tree" 입니다. 이 tree가 가리키고 있는 링크를 들어가보면, 아래의 사진과 같이 우리가 commit한 f1.txt을 가리키고 있는 또 다른 ./object 파일로 연결되고, 이 파일 또한 tree로 이루어져 있습니다. 그리고 이 ./object 가 가리키고 있는 링크를 또 다시 타고 들어가면, 실제 f1.txt의 내용을 담고 있는 ./object 파일이 나옵니다. 

     

    commit 이후 생성된 ./object 파일(왼), tree의 링크를 따라 들어간 모습(오)
    commit 이후, object 디렉토리들 간의 관계

     

    commit 이후에, object 디렉토리가 어떤 구조로 이루어져있는지 조금은 감이 오시나요? 좀 더 쉽고 명확한 이해를 위해 아래의 그림을 가져와보았습니다.  Git의 객체 간의 관계를 보여주는 그림입니다. 아래의 그림처럼, object 디렉토리는 파일의 목록을 담고 있는 트리 객체와, 커밋 정보(author, commiter 등) 저장하고, 트리 객체는 다른 트리 객체를 하위에 가질 수 있습니다. 이러한 객체들간의 관계는 추후에 Branch를 다룰때 더 자세히 알아보도록 하고, 지금은 commit 이후에 생성된, object 디렉토리가 어떤 구조로 이루어져있는지 정도만 이해해보도록 합시다!

    (원본 출처:  https://git-scm.com/book/ko/v2/Git-브랜치-브랜치란-무엇인가 )

     

    이번에는 f1.txt를 'a'에서 'ab'수정하고, 새로운 버전을 생성한 이후에 gistory를 다시 한번 확인해보겠습니다. 새로운 commit을 했으니, 이번에도 새로운 object 디렉토리가 생성이 되었습니다. 이 object 디렉토리를 보면, 이전과는 또 다른 점을 볼 수 있습니다. 이번에는 parent라는 항목이 새로 생긴 것을 볼 수 있습니다. parent의 링크를 따라가 보면, 현재 commit한 버전 이전의 commit을 보여줍니다. (전 실수로 commit을 한번 더 해버려서 사진처럼 3개의 commit이 보여집니다..)

     

    새로운 버전 commit 이후 모습

     

    그리고 새로 생성한 버전의 object 파일 내(104eb6...)tree(96ab702...)를 보면, 수정된 f1.txt파일의 내용이 보여집니다. 하지만, parent(a5c86c..)tree(e4e333...)를 보면 수정된 내용이 반영되어있지 않는 것을 확인 할 수 있습니다. 

     

    우리는 버전에 적혀있는 tree를 통해, 버전이 만들어진 시점의 프로젝트 폴더에 대한 상태를 알 수 있습니다.  이를 스냅샷(Snapshot) 이라고도 합니다. 정리하자면, 각각의 버전은 해당 버전이 만들어지는 시점의 스냅샷을 Tree라는 정보구조를 통해 가지고 있는 것이라고 할 수 있습니다. 

     

    현재 버전의 commit(왼), 이전 버전의 commit(오)

     

    한가지 실습을 더 진행해보도록 하겠습니다. 우선 현재 폴더 안에 d1이라는 디렉토리를 하나 더 만들어줍니다. (mkdir d1) 그리고 cp f1.txt d1/f1.txt 를 통해, f1 파일을 복사해준 후, add와 commit을 진행해줍니다. 다음에 gistory의 변화를 살펴보도록하겠습니다. 새로 생긴 object 디렉토리를 살펴보면, 이전의 commit들과 특별히 다른점은 보이지 않습니다. tree를 한번 살펴보면, 우리가 새로 생성한 디렉토리인 d1과 나머지 파일들이 존재하는 것을 볼 수 있습니다.

     

     

    앞서 add와 commit의 원리에 대해 살펴보며 여러 종류의 .object 디렉토리를 살펴보았습니다. 마무리로 .object 디렉토리에는 어떠한 내용이 들어갈 수 있는가에 대해 정리해보도록 하겠습니다.

     

    1. Blob : 텍스트, 이미지, 이진 파일 등 다양한 형식의 파일을 저장될 수 있으며, 파일의 메타정보를 제외한 파일의 전체 내용이 저장됩니다.

    2. Tree : 디렉토리명과 파일의 내용인 Blob에 대한 정보를 가지고 있습니다. 객체(object)에 대한 접근 권한, 파일이름 등을 관리합니다.

    3. Commit : 작성자, 커밋 실행자, 날짜, 로그 메세지, tree 객체 등에 대한 정보를 가지고 있습니다. 

    4. Tag : 객체의 종류, 태그 이름, tagger, 태그 메세지 등에 대한 정보를 가지고 있습니다. 

     

     

     

    git status 의 원리

    우리는 파일을 생성하거나, add, commit 한 이후에 git status를 통해 현재 우리의 git 저장소의 상태를 알 수 있습니다. 이러한 git status 명령어는  어떻게 변경된 내용이 존재하는지, commit 할 사항이 존재하는지 등을 알 수 있을까요? 우리가 지금껏 알아본 add, commit의 원리를 생각해보면 쉽게 이해할 수 있을 것 입니다. 

     

    git은 어떻게 commit할 파일이 있음/없음을 알 수 있을까?

    우리가 commit을 하면, commit에 대한 object 파일이 생성이 되고, 내부에는 tree가 존재합니다. 이때 이 tree의 내용과 index의 내용이 일치한다면, 현재 커밋할 내용이 없다고 알 수 있습니다. 즉, commit 이후에 저장소, index, 프로젝트 폴더가 정확하게 일치할때 git status는 더이상 commit할 것이 없다고 알려줍니다. 

     

    파일을 수정하고, git status를 하면 git은 어떻게 수정된 파일이 있음을 알 수 있을까?

    예를 들어 f2.txt를 수정했다고 한다면, index에 적혀있는 f2.txt의 해시값과, f2.txt 파일의 내용이 만들어내는 해시값이 다른 경우, 수정되었음을 알수 있습니다.

     

    git add를 한 후, commit 대기 상태임을 어떻게 알 수 있을까?

    이는 예를 들어,  index에서 f2.txt와 최신 commit의 tree가 가리키는 f2.txt의 내용이 다르다면 f2.txt는 index에 add 되어 commit 대기 상태임을 알 수 있습니다.

     

     

     

    ____________

    지금까지 git의 원리에 대해 알아보았습니다. 이제 정말 마무리로 git의 프로젝트 폴더와 index, repository의 관계를 나타내는 그림을 보며, 우리가 공부한 내용을 다시 한번 정리해보겠습니다. 

    우선 Work Tree는 우리가 실습을 위해 만든 디렉토리라고 할 수 있습니다. 이곳에서 Register, 즉 add를 하면 index 파일로 저장이 되고, 이 index 디렉토리는 즉 대기 상태 공간(stage area)인 것 입니다. 이제 index 디렉토리에 있는 파일들을 commit 하면 Repository 즉, object 디렉토리에 저장이 되는 것 입니다.

    (출처 : https://backlog.com/git-tutorial/git-workflow/)

     

     

     

     

    __________

    저는 git의 원리에 대한 강의를 이렇게 포스트로 정리하며, git의 동작이 어떤 흐름으로 이루어지는 지에 대해 더 확실하게 이해할 수 있었습니다. 포스트를 작성하며 저는 개인적으로 단지 지식을 한 개 더 알아가는 것 뿐 아니라, 원리의 중요성에 대해 다시금 깨닫는 의미있는 시간이었습니다. 작성하는데는 꽤나 오랜 시간이 걸렸지만 그만큼 더 잘 이해하고, 개념을 정립할 수 있었던 좋은 기회였습니다. 다른 분들도 제 글을 보고, 도움이 되셨으면 좋겠습니다. 감사합니다.

    댓글

Designed by Tistory.