git 내부 동작

💻 git 이란?


GitContent-Addressable 파일 시스템이고 그 위에 VCS 인터페이스가 있는 구조이다.

무슨 말인지 실감이 안난다. 하나씩 살펴보면서 이해해보기로 한다. 정리를 하면서 잘못 기입된 정보가 있을 경우에는 덧글을 부탁드린다.

기본 정보

  • 2005년 리눅스 커널의 개발을 위해서 만들게 된 형상 관리 시스템이다.

  • 대부분의 형상 관리 시스템과 다른 모든 디렉터리는 네트워크 접속이나, 중앙 서버와는 독립적으로 동작하는 완전한 이력 및 완전한 버전 추적 기능을 갖춘 형상 관리 시스템이다.

  • 처리 속도가 빠르며 Repository 의 완전한 복사본을 로컬에 저장이 가능하고 일시적인 작업에 대한 이력 관리가 쉽다.

  • 이미 commit 한 소스 파일도 수정이 가능하다.

  • 하지만 CVS 나 Subversion 을 사용했던 개발자들에게는 불편함이 있을 수 있으며 또한 대용량의 소스 코드 관리에는 부적절하다.

Content-Addressable Storage

  • 이름이나 위치가 아닌 내용을 기반으로 검색할 수 있도록 정보를 저장하는 방법이다.

  • 해시 기능을 통해 파일의 콘텐츠를 전달하여 고유 키인 콘텐츠 주소를 생성하는 방식이다.

  • 단순하게 말하면 git 이 Key-Value 구조의 단순한 데이터 저장구조를 가지고 있다는 것이다. 이는 .git/objects 디렉토리를 확인해보면 알 수 있다.

    • objects 디렉토리git 의 모든 변경사항을 압축해서 파일들을 폴더 내부에 저장한다.

    • 내부에 저장된 정보로는 commit, tree, blob 등이 존재하고 위 3가지가 핵심이다.

    • 아래 이미지를 먼저 확인하고 각 내용을 확인하면 대략적인 동작을 이해하기 쉽다.

    • blob

      • Binary Large Object 로 일종의 불변 객체이자 파일 객체이다.

      • SHA-1 체크섬을 이용해서 파일 내용을 식별 가능하다.

      • 다양한 파일의 데이터를 저장 가능하고, 파일의 메타 데이터를 제외한 순수 데이터 자체만을 저장한다.

    • tree

      • git 이 폴더 구조를 지원하는 방법이다.

      • 내부에는 파일 식별자, 파일 데이터의 해시 값, 파일의 이름이 저장되어있다.

      • tree 는 blob서브 tree 로 구성된다.

    • commit

      • 각각의 commit 별로 하나의 commit 파일로 저장된다.
      • 내부에는 가장 최신의 tree 해시 값, 부모 commit 에 대한 참조, commit 메시지 등이 저장된다.
      • 일종의 불변 객체이다.

VCS

  • Version Control System 의 약자로 이름 그대로 버전 관리를 도와주는 시스템이다.

  • 파일의 변화를 시간에 따라 기록했다가 나중에 특정 시점의 버전을 불러올 수 있는 시스템을 의미한다.

  • 선택한 파일을 이전 상태로 되돌릴 수 있고, 변경 사항을 비교하고, 변경한 사람 및 변경 시기를 추적할 수 있다.

  • 여러 종류가 있으며 아래와 같다. git 은 DVCS 방식을 사용한다.

    • Local VCS

      • 단순하게 데이터베이스를 사용해서 파일의 변경 정보를 관리하는 시스템이다.
      • 가장 단순한 구조이며 파일을 다른 디렉토리에 복사하는 방식이다.
      • 오류가 발생하기 쉽고, 어떤 디렉토리에 있는지 잊어버리거나 실수로 잘못된 파일에 쓰거나 복사하기 쉽다.
      • RCS (Revision control system) 이 대표적이다.
    • CVCS

      • Centralized VCS여러 사람과 함께 작업하면서 생기는 문제를 해결하기 위해서 개발되었다.

        • 서버가 별도로 존재하고 클라이언트가 중앙 서버에서 파일을 받아서 사용하는 방식이다.

        • Local VCS 보다 관리가 쉽다는 장점이 있지만 중앙 서버에 문제가 발생하면 치명적이라는 문제가 있다.

        • CVS, Subversion, Perforce 가 대표적이다.

    • DVCS

      • Distributed VCS 는 클라이언트가 단순하게 파일의 마지막 스냅샷을 이용하는 것이 아닌 전체 기록을 포함한 저장소를 완전히 미러링 하는 방식이다.
      • 이런 방식을 통해서 서버가 중단거나 문제가 있을 경우 클라이언트 저장소를 서버에 복사하여 복원할 수 있다.
      • 또한 많은 클라이언트들이 리모트 저장소를 가질 수 있기 때문에 다양한 방법의 협업이 지원된다.
      • git, Mecurial, Bazaar, Darcs 가 대표적이다.

git 을 이용하는 이유

  • 주로 복잡한 프로젝트의 워크플로우 관리를 간단하게 하기 위해서 사용한다.

  • 프로젝트가 충분히 복잡하지 않다면 이 장점을 느끼기 힘드나 프로젝트가 점점 양이 많아지고 복잡해지면 이 장점을 크게 느낄 수 있다.


🛠 명령어에 따른 git 내부 흐름


  • 디렉토리에 있는 파일은 크게 TrackedUntracked 로 나뉘고 Tracked 파일은 이미 snapshot 에 포함되어 있는 파일이다.

    • 여기서 snapshot 이란 git 이 데이터를 바라보는 관점으로 파일을 하나씩 별도로 보는 것이 아닌 프로젝트 전체를 관리하는 형태이다.

    • 말 그대로 프로젝트 전체를 사진을 찍어서 관리하는 느낌으로 변경이 이루어지면 가장 최신 버전의 snapshot 만 통째로 저장하고 나머지 commit 들에 대해서는 snapshot 끼리의 차이인 delta 를 저장한다. 이러한 방법으로 인해 git 이 작은 용량으로 빠르게 동작한다.

    • 디렉토리에 있는 파일은 위와 같이 분할되지만 git 의 프로젝트는 세 가지 상태로 관리한다.

      • Committed: 데이터가 로컬 데이터베이스에 안전하게 저장됐다는 것을 의미한다.

      • Modified: 수정한 파일을 아직 로컬 데이터베이스에 commit 하지 않은 것을 한다.

      • Staged: 수정한 파일을 곧 commit 할 것이라고 표시한 상태를 말한다.

  • Tracked 파일은 또 Unmodified(수정하지 않음)와 Modified(수정함) 그리고 Staged(commit 으로 저장소에 기록할) 상태로 분리된다.

  • 처음 저장소를 clone 해서 가져온다고 하면 모든 파일은 Tracked 이면서 Unmodified 상태로 존재한다. 이 상태에서 어떤 파일을 수정하게 되면 해당 파일은 Modified 상태로 전환된다. 이후 이 수정한 파일을 실제로 commit 하려면 Staged 상태로 만들고 해당 상태의 파일을 commit 한다.

  • 아래는 위 설명에 담긴 파일의 라이프 사이클을 요약하는 그림이다.

https://git-scm.com/book/en/v2/images/lifecycle.png

  • add 명령어를 사용해 파일을 조작하면 git 은 해당 파일을 추적(Tracked)하기 시작하고(만약 Untracked 라면 그렇고 이미 Tracked 상태였으면 현행 유지) commit 에 추가될 Staged 상태로 바뀐다.

  • 이후 commit 명령어를 실행하면 Staged 상태의 파일들의 snapshot 이 저장된다. 이후 해당 파일들은 Unmodified 상태로 전환된다. 그리고 이때 생성한 snapshot 과 이전 snapshot 과의 차이를 delta 로 저장한다.


📖 참고 자료



🖼 이미지 출처