ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 실습으로 알아보는 Git 아키텍처
    면접스터디 2025. 8. 12. 19:35

    Git의 아키텍처는 어떻게 되어 있을까요?

     

    저는 우선 다음 블로그에 정리가 잘 되있어서 참고하여 작성하였습니다.

    https://inpa.tistory.com/entry/GIT-⚡️-개념-원리-쉽게이해

     

    [GIT] ⚡️ git 개념 & 원리 (그림으로 알기쉽게 비유 😃)

    Git 이란 무엇인가? Git이란 분산형 버전 관리 시스템(Version Control System) 의 한 종류이며, 빠른 수행 속도에 중점을 둔다. 우리가 레포트를 제출한다고 가정했을때, 처음에 저장했을때 'report.txt'라

    inpa.tistory.com

     

    위의 블로그에 첨부된 깃의 아키텍처입니다.

    https://inpa.tistory.com/entry/GIT-⚡%EF%B8%8F-개념-원리-쉽게이해

    사진에 나와있는 화살표 및 추가로 실습을 해보며 학습해보도록 하겠습니다.

    1. 원격 저장소에서 Repository 만들기
    2. 원격 저장소에 있는 코드를 로컬 저장소로 가져온다. (git clone)
    3. 추적할 파일과 안할 파일을 정한다. (.gitignore)
    4. 브랜치를 2개 생성한다.(git branch)
    5. 한개의 브랜치로 이동한다. (git checkout)
    6. 파일 2개를 작성한다.
    7. 변경 사항을 스테이징 및 커밋한다.(git add, git commit)
    8. 변경사항을 원격저장소에 반영한다. (git push)
    9. 나머지 한개의 브랜치로 이동하여 원격저장소의 변경사항을 가져온다.(git pull)

    0. 원격 저장소에서 Repository 만들기

    우선 원격 저장소(Github)에서 새로운 레포지토리를 만듭니다.

    저는 이름을 git-practice로 만들었는데요, 자유롭게 설정하고

    사진과 같은 설정처럼 해줬습니다. README 및 .gitignore 는 다음 단계에서 생성할 것입니다.

    이렇게 설정하면 다음과 같은 화면이 나옵니다.

    1. 원격 저장소에 있는 코드를 로컬 저장소로 가져온다. (git clone)

    저기 HTTPS로 되어 있는 URL을 복사하고 로컬 컴퓨터에서 다음 명령어를 입력하면

    git clone <https://github.com/sungjun-singer/git-practice.git>

    다음과 같은 결과가 나옵니다.

    그리고 내부에 뭐가 들었나 확인해봤지만 아무것도 나오지 않았습니다.

    하지만 ls -al 명령어를 입력하면 숨김 파일이 출력되며 .git 디렉토리가 생성된 것을 볼 수 있습니다.

    ls -al
    total 0
    drwxr-xr-x    3 kimseongjun  staff    96 Aug 11 20:44 .
    drwxr-x---+ 245 kimseongjun  staff  7840 Aug 11 20:44 ..
    drwxr-xr-x    9 kimseongjun  staff   288 Aug 11 20:44 .git

    그리고 ls -al .git 명령어를 통해 .git 디렉토리 내부를 확인해보면 다음과 같이 출력됩니다.

    ls -al .git
    total 24
    drwxr-xr-x   9 kimseongjun  staff  288 Aug 11 20:44 .
    drwxr-xr-x   3 kimseongjun  staff   96 Aug 11 20:44 ..
    -rw-r--r--   1 kimseongjun  staff   21 Aug 11 20:44 HEAD
    -rw-r--r--   1 kimseongjun  staff  316 Aug 11 20:44 config
    -rw-r--r--   1 kimseongjun  staff   73 Aug 11 20:44 description
    drwxr-xr-x  16 kimseongjun  staff  512 Aug 11 20:44 hooks
    drwxr-xr-x   3 kimseongjun  staff   96 Aug 11 20:44 info
    drwxr-xr-x   4 kimseongjun  staff  128 Aug 11 20:44 objects
    drwxr-xr-x   4 kimseongjun  staff  128 Aug 11 20:44 refs

    7개의 파일 혹은 디렉토리는 다음 역할을 수행합니다. 지금 자세히 볼것은 아니니 대충 설명만 작성하고 넘어가겠습니다.

    • HEAD
      • 현재 작업 중인 브랜치나 커밋을 가리키는 포인터입니다.
    • config
      • 저장소별 Git 설정 파일입니다.
    • description
      • Bare 저장소에서 웹 UI에 표시될 저장소 설명입니다.
    • hooks/
      • Git 이벤트가 발생할 때 자동으로 실행되는 스크립트가 들어있는 디렉터리입니다.
    • info/
      • 로컬 저장소의 추가 정보를 저장하는 디렉토리입니다.
      • 특히 info/exclude 파일은 .gitignore 와 비슷하지만, 로컬 저장소에서만 적용되는 무시 목록을 관리합니다.
      • .gitignore 는 버전 관리에 포함되어 원격 저장소로 올라가며 다른 사람과 공유하지만 info/exclude 파일은 git에 커밋되지 않아 개인적인 개발 환경 파일, 테스트 로그, 로컬 전용 설정 파일 등을 무시할 때 사용합니다.
      • 즉 나혼자만 쓰는 .gitignore 인것으로 생각하면 됩니다.
    • object/
      • Git의 모든 데이터(커밋, 트리, 블롭, 태그 객체)가 해시(SHA-1) 기반으로 저장되는 곳입니다.
    • ref/
      • 브랜치, 태그, 원격 브랜치가 어떤 커밋을 가리키는지 저장하는 참조 파일이 들어있습니다.

    2. 추적할 파일과 안할 파일을 정한다. (.gitignore)

    다음 파일은 Git이 추적하지 않을 리스트들을 써놓는 곳입니다. 이 파일에 예를 들어 .env 라고 작성해두면 로컬 저장소에 .env 파일이 있어도 추적 대상에서 제외됩니다.

    저희는 two.txt를 써놓도록 하겠습니다.

    파일 생성 위치는 루트( .git과 같은 위치)에서 생성합니다. .gitignore는 해당 위치를 기준으로 하위 디렉토리에 재귀적으로 적용되기 때문에 루트에 두면 저장소 전체에 걸쳐 무시 규칙이 적용됩니다.

    그리고 우선 커밋이 있어야 브랜치를 생성할 수 있기 때문에 다음 명령어를 통해 커밋합니다.

    변경된 파일 → 스테이징 → 로컬 저장소로 가는 명령어인데 추후에 다시 설명하겠습니다.

    git add .gitignore
    git commit -m "add .gitignore"
    

    3. 브랜치를 2개 생성한다.(git branch)

    그리고 다음 명령어를 통해 one, two 브랜치를 생성합니다.

    git branch one
    git branch two
    

    그리고 다음 명령어로 현재 생성된 브랜치들을 확인하면

    git branch
    * main
      one
      two
    

    현재 브랜치와 브랜치 목록을 확인할 수 있습니다.

    4. 한개의 브랜치로 이동한다. (git checkout)

    이제 생성한 브랜치 중 one 브랜치로 이동하겠습니다.

    다음 명령어를 통해 이동합니다.

    git checkout one
    

    그리고 다음 명령어로 현재 브랜치를 확인하면

    git branch
      main
    * one
      two
    

    다음과 같이 one 브랜치로 이동한 것을 확인할 수 있습니다.

    브랜치를 생성해서 작업하는 이유는 작업을 안전하고 독립적이고 병렬적으로 개발하기 위해서 사용합니다.

    5. 파일 2개를 작성한다.

    one.txt  two.txt 파일을 작성합니다.

    그런데 one.txt는 초록색U, two.txt는 아무것도 없습니다. 그 이유는 아까 .gitignore two.txt를 추적하지 않겠다고 지정해줘서 그런 것입니다.

    다음 명령어를 통해 추가 확인이 가능합니다.

    git status
    
    현재 브랜치 one
    추적하지 않는 파일:
      (커밋할 사항에 포함하려면 "git add <파일>..."을 사용하십시오)
            one.txt
    
    커밋할 사항을 추가하지 않았지만 추적하지 않는 파일이 있습니다 (추적하려면 "git
    add"를 사용하십시오)
    

    근데 제 예상으로는 one.txt는 바로 추적되야 한다고 생각했는데, 추적하지 않는 파일이라고 합니다.

    그 이유는 git은 한번도 커밋된적 없는 파일을 미추적 파일로 여깁니다.

    그래서 git add 를 통해 Staging Area(인덱스)에 등록해 추적 예정 상태로 만든 후에

    git commit 을 통해 로컬 저장소에 올라가며 추적 상태로 만들 수 있습니다.

    하지만 .gitignore에 설정한 two.txt는 같은 미추적 상태인데 아예 포함되지 않는 차이점이 있습니다.

    하지만 이 파일도 git add -f 명령어를 통해 추적상태로 둘 수 있습니다.

     

    🔥그리고 중요한 포인트가 있습니다.

    이미 커밋되었던 파일을 .gitignore 에 추가해도 git은 계속 추적합니다.

    그래서 추적을 완전히 끊으려면 git rm —cached 파일 로 인덱스에서 제거해야 합니다.

    하지만 이래도 Github에 올라갔던 파일은 이전 커밋 내역에 남아있기 때문에 삭제가 어렵습니다. 그래서 처음부터 잘 설정해서 민감한 정보를 올리는 일이 없게 해야합니다.

    6. 변경 사항을 스테이징 및 커밋한다.(git add, git commit)

    그래서 다음 명령어를 통해 스테이징 환경에 올리고 커밋하면 추적중인 상태가 됩니다.

    git add one.txt
    git commit -m "add one.txt"
    

    스테이징에 올라가고 커밋이 되었을 때는 결과가 다음과 같이 나왔습니다.

    $ git add one.txt
    $ git status
    현재 브랜치 one
    커밋할 변경 사항:
      (use "git restore --staged <file>..." to unstage)
            새 파일:       one.txt
    
    $ git commit -m "add one.txt"
    [one dd42f62] add one.txt
     1 file changed, 1 insertion(+)
     create mode 100644 one.txt
    

    저기 [one dd42f62] 는 브랜치 이름과 커밋의 해시값입니다.

    7. 변경사항을 원격저장소에 반영한다. (git push)

    다음 명령어를 통해 원격 저장소에 저장합니다.

    git push origin one
    

    여기서 git push는 원격 저장소에 로컬 저장소의 변경 내역을 반영한다는 명령어이고,

    origin은 git clone시 가져왔던 origin 이름입니다. 저장된 곳은 .git/config 파일 내부에 다음과 같이 정보들이 저장되어 있는데 remote “origin” 에 URL이 저장되어 있습니다.

    [remote "origin"]
            url = <https://github.com/sungjun-singer/git-practice.git>
            fetch = +refs/heads/*:refs/remotes/origin/*
    [branch "main"]
            remote = origin
            merge = refs/heads/main
    [branch "one"]
            vscode-merge-base = origin/main
    

    그리고 one은 내 로컬 저장소의 브랜치입니다.

    그래서 총 의미는 “내 로컬 저장소의 one 브랜치를 원격 저장소(origin)에 업로드하고, 원격에도 동일한 이름의 브랜치를 만들거나 갱신하라” 입니다.

    그래서 깃허브에 들어가보면 로컬에서 저장했던 내용이 원격 저장소에 잘 업로드 되어 있는 것을 확인할 수 있습니다.

    8. 나머지 한개의 브랜치로 이동하여 원격저장소의 변경사항을 가져온다.(git pull)

    이제 아까 생성했던 two 브랜치에서 one 브랜치에서 작성한 내용을 가져오려 합니다.

    다음과 같은 명령어를 입력하면 됩니다.

    git checkout two
    git pull origin one
    

    그러면 다음과 같은 결과가 나옵니다.

    <https://github.com/sungjun-singer/git-practice> URL에서
     * branch            one        -> FETCH_HEAD
    업데이트 중 9c6850f..dd42f62
    Fast-forward
     one.txt | 1 +
     1 file changed, 1 insertion(+)
     create mode 100644 one.txt
    

    우선 pull 명령어는 fetch + merge 명령어가 합쳐진 명령어 입니다.

    그래서 원격 저장소의 one 브랜치에서 커밋을 가져오는 fetch 작업을 수행합니다.

    fetch 직후 가져온 커밋을 임시 참조인데 FETCH_HEAD로 기록합니다.

    .git/FETCH_HEAD 파일을 살펴보면 다음과 같은 내용이 있습니다.

    9c6850fa74d3e9ec207158fe48293d9fde9efdfa        not-for-merge   branch 'main' of <https://github.com/sungjun-singer/git-practice>
    dd42f62570e0e7118aa4f550c3a92f8ea67a7cd8        not-for-merge   branch 'one' of <https://github.com/sungjun-singer/git-practice>
    

    이 내용은 어느 원격의 어떤 브랜치를 어떤 커밋 해시로 받았는가가 남습니다.

    이후 두번째 단계인 merge 에서 현재 브랜치(two)와 FETCH_HEAD(=origin/one 의 최신 커밋)을 병합합니다.

    병합에는 fast-forward 방식을 사용하였는데 이는 깃허브의 다양한 병합 방식 중 하나로 현재 브랜치의 커밋이 없고 FETCH_HEAD와 커밋이 이어질 때 사용되는 방식입니다.

    병합까지 완료되어 one 브랜치에서 작성했던 one.txttwo 브랜치에도 적용된 것을 확인할 수 있습니다.

    git log 명령어를 사용하여 현재 브랜치의 커밋 내용 또한 확인할 수 있습니다.

Designed by Tistory.