Loading
2022. 4. 27. 12:23 - lazykuna

.git의 내부 구조, 그리고 브랜치 이름

Git의 내부 구조

다른 글들에서 상세하게 설명해 놓은 경우가 많아서, 여기서는 간단하게만 짚고 넘어갑니다.

먼저 .git 디렉터리를 보면 아래와 같은 파일들이 있습니다.

  • HEAD
    현재 작업중인 브랜치 이름(ref) 가 담겨 있습니다. (보통 기본이면 refs/heads/master 이겠죠?)
  • ORIG_HEAD
    머지할 때, 대상이 되는 브랜치의 SHA 해시값이 담겨 있습니다. (머지 취소/복구용?)
  • FETCH_HEAD
    git fetch 할 때 업데이트된 마지막 SHA 해시값이 담겨 있습니다.
  • COMMIT_EDITMSG
    마지막으로 시도했던 커밋 메시지는 여기 담깁니다.
    커밋 도중 실패했다고 좌절할 필요 없이 git commit -F .git/COMMIT_EDITMSG 하면 됩니다 ㅎㅎ.
  • config
    git repo에 대한 로컬 설정입니다. ref에 대한 정보를 담고 있기도 합니다.
    그나마 직접 수정할 일이 제일 많을 수 있는 파일이지 않을까 싶네요.
  • packed_refs
    브랜치 이름과 이들의 hash 정보를 담고 있습니다. 여기 없으면 checkout을 못 하죠.
    git remote update 하면 알아서 갱신됩니다.
  • index
    현재 스테이지된 파일들, 즉 git add와 같은 작업들을 수행할 때 캐시된 파일들을 담고 있습니다. 내부적으로 바이트로 된 자료를 담고 있어 따로 까볼 일은 없을 파일...

이처럼 많은 상태들을 파일로 관리하고 있습니다.

또한 디렉터리들도 많이 있는데...

  • refs
    우리가 작업하는 브랜치들이 여기 저장됩니다. 말 그대로 .git/refs/<branch_name> 형태로 저장되고, 파일 안에는 SHA 해시가 저장되어 있습니다.
  • objects
    git에서 사용되는 데이터들이 저장됩니다. blob, tree, commit 텍스트 등의 정보를 모두 압축하여 저장해놓고 있습니다.
  • logs
    말 그대로 작업 로그...
  • info
    딱히 정해진 용도로 쓰이는 건 아닌 듯 합니다 -_-; 부가적인 기능들에 대한 추가적인 정보를 넣는 용도로 쓰는 듯 합니다.
    보통 .git/info/exclude (gitignore 같은 거) 이나 .git/info/sparse-checkout 과 같은 기능을 씁니다.
  • hooks
    git에서 지원되는 hook들에 대한 정의들입니다. 말 그대로 어떤 이벤트가 실행되기 전 수행할 후킹을 여기에 정의할 수 있습니다. 참고

브랜치 이름에 따른 구조

위에서 보았다시피, 브랜치를 생성하게 되면 .git/refs/<branch_name> 으로 파일이 만들어지게 됩니다.

그런데 브랜치 명에 슬래시를 쓸 수 있습니다. 이 경우, 디렉터리 형태로 브랜치가 만들어지게 됩니다.

예) 브랜치명이 project/A1/main 이면, .git/refs/project/A1/main 와 같이 폴더 project/A1와 파일 main이 생성됨.

브랜치 관리할 때 주의할 점

브랜치에 슬래시를 넣을 경우, 본래 의도했던 바와 다르게 폴더가 생성되기 때문에 그 폴더 이름으로 된 브랜치를 만들 수 없다는 점에 주의해야 합니다.

예를 들어 project/A1/main 으로 브랜치를 만든 상태에서 project/A1 로 브랜치를 만들면, 아래와 같은 오류를 보게 됩니다.

12:28:30  error: cannot lock ref 'refs/remotes/origin/project/A1': 'refs/remotes/origin/project/A1/main' exists; cannot create 'refs/remotes/origin/user/dongwon/A1'

역으로 project/A1 이 있는 상황에서 project/A1/main 으로 브랜치를 만드는 것도 안 됩니다. 이미 A1이라는 파일이 생성되어 있기 때문입니다.

물론 브랜치를 지우고 새로운 브랜치를 만들면 되는것 아니냐? 라고 반문할 수도 있는데, 되기는 합니다. 하지만 빌드 시스템이 Jenkins와 엮여 있는 경우, 해당 빌드시스템이 깨져버릴 수도 있어 난감한 상황이 생길 수도 있으니, 이미 그렇게 만든 브랜치는 가능하면 건들지 않는 쪽이 좋습니다 ^^;.

추가로, 이렇게 구조가 명확하지 않을 수 있는 경우에는, 가능하면 슬래시 대신 언더바(_)를 쓰는 것이 이러한 문제 예방을 할 수 있어 좋습니다.

예) project/A1_main

참고