이 포스트는 생활 코딩의 지옥에서 온 Git 강의를 참고하였습니다.

git add

git add 명령은 git에 현재 commit된 버전과 다르게 변경된 파일이 있음을 알려주는 동작이다.
따라서 git add가 실행되면, git은 이를 표시하기 위해 가진 파일들에 변화가 생긴다.

여기서 변화가 생기는 파일들은 objects 파일과 index 파일이다.
objects 파일은 파일의 내용을 가지고 있고, index 파일은 objects 파일 링크의 list(파일 이름 포함)를 가지고 있다.

만약 a라는 내용을 가진 파일 f1.txt를 add한다고 하자. 그러면 ‘a’를 저장하고 있는 objects 파일(링크: abcd)이 생성되고, 파일을 뜻하는 수식어 ‘blob’, objects 링크 ‘abcd’, 파일 이름 ‘f1.txt’를 담고 있는 index 파일이 생성(정확히는 변경)된다.

이 때의 index 파일 내용은 아래와 같다.

blob abcd f1.txt

이후에 b라는 내용을 가진 파일 f2.txt를 추가로 add하면 ‘b’를 저장하고 있는 objects 파일(링크: efgh)과 위 정보가 index파일에 추가된다.

이 때 index 파일은 아래와 같이 변경된다.

blob efgh f2.txt
blob abcd f1.txt

이 이후에 만약 f2.txt와 똑같은 b라는 내용을 가진 f3.txt가 add 되면 조금 다른 동작을 하게 된다. 원래라면 새로운 objects 파일이 생성 되어야 하지만, ‘b’를 저장하고 있는 objects가 이미 있기 때문에 새로운 objects는 생기지 않는다. 하지만 새로운 파일이 생겼기 때문에 index 파일에 이 파일에 대한 정보는 추가된다.

따라서 새로운 objects는 추가되지 않지만 index 파일은 아래와 같이 변경된다.

blob efgh f3.txt
blob efgh f2.txt
blob abcd f1.txt

이와 관련된 강의는 여기를 참고한다.

git commit

git commit 명령은 git에 변경된 파일이 있음을 명시하는 동작이다. 따라서 commit을 하면, 그 전까지 add한 파일들이 해당 commit에 기록된다.
add 동작과 마찬가지로 git commit이 실행되면, git은 이를 기록하기 위해 가진 파일들에 변화가 생긴다.

먼저 index 파일이 변경된다.

commit에도 어떤 파일들이 어떻게 변경되었는지에 대한 정보가 필요하기 때문에, add 당시 index에 저장된 내용과 같은 내용을 가진 objects파일을 생성한다. 파일들의 변경 정보가 담긴 objects파일이 생성되면, commit 동작으로 인해 파일들이 모두 최신 버전으로 올라갔기 때문에 add 정보가 담겨있던 index에 있는 내용은 초기화 된다. 이후 과정에서 새로운 add list를 추가하기 위함이다.

변경된 파일 정보들을 가지고 있는 objects가 생성되었으니, 이번에는 commit의 전체 정보가 담긴 파일이 생성되어야 한다. 이름이 같아 헷갈릴 수 있지만 이 파일의 이름도 objects 파일이다. 이 파일은 변경된 파일 정보들을 가지고 있는 objects 파일의 링크, commit 저자의 정보, commit에서 남긴 메시지, 이전 commit의 링크와 같은 내용을 담고 있다.

이름이 같아 조금 난해할 수 있으니, 예를 들어 설명해보자.
add index의 내용을 옮긴 objectsindex_objects라고 하고, commit의 정보가 담긴 objectscommit_objects라고 한다면,

  • index_objects에는 아래와 같은 정보가,
    blob efgh f3.txt
    blob efgh f2.txt
    blob abcd f1.txt
    
  • commit_objects에는 아래와 같은 정보가 담기게 되는 것이다.
    tree {index_objects link}
    parent {previous_commit}
    author {committer_info}
    committer {committer_info} 
    

이 외에도 마지막 commit을 가르키는 HEAD 등 그와 관련된 파일들이 변경된다.

이렇게 각 commit마다 현재 버전에서 변경된 사항을 가지고 있고, 이전 commit에 대한 정보도 가지고 있기 때문에 git을 통해 이전 commit과의 다른 점(diff)를 확인할 수 있게 되는 것이다.

이와 관련된 강의는 여기를 참고한다.

정리

간략하게 요약해보자면,
좀 더 큰 단위의 objects가 작은 단위, 이전 단위의 objects를 가르키고 있다고 보면 될 것 같다.

commit objects 
 ├ commit file list objects
 │  └ file objects  
 └ previous commit objects
    └ (previous) commit file list objects
    └ (previous) file objects