git에 대한 이해도 넓히기 ver.1

낚시하는 곰·2025년 3월 20일

krafton jungle

목록 보기
16/52

참고 사이트
깃 사용법 연습

사이트에 접속하면

사이트에서 사용할 수 있는 명령어는 다음과 같습니다.

commit
branch
checkout
cherry-pick
reset
revert
rebase
merge

시작하기를 누르면

export tree 또는 import tree 명령어로 git의 트리 구조를 친구들에게 공유할 수 있습니다.

훌륭한 학습 자료가 있으신가요? build level로 레벨을 만들어 보시거나, 친구의 레벨을 import level로 가져와서 도전해보세요

이제 레슨을 시작해봅시다...

git에는 export tree나 import tree 명령어가 없습니다. 이 명령어는 해당 웹 사이트에서 교육용으로 만든 명령어입니다. 자신이 학습 단계를 빌드하거나 다른 사람이 만든 빌드를 가져올 수 있도록 만든 것 같습니다.

연습 모드 시작

git commit
저도 git을 조금 써봤다고 할 수 있는데요. commit이라고 하면 떠오르는 건 'stash영역에 있는 파일들을 저장한다'라고만 기억하고 있습니다. 보통 커밋을 하기 전에 변경된 파일을 스테이징 영역에 추가하잖아요? 추가 -> 저장 -> 원격 저장소에 push 이런 식으로 기억하고 있었습니다.

그런데 위 개념으로는 정확하진 않습니다. 참고 자료를 보면 commit을 하는 동시에 파일의 변경 내역이 고유한 해시값(SHA-1 체크섬)과 함께 스냅샷(snapshot) 형태로 기록한다고 합니다. 이렇게 저장하고 log를 보면 head에 방금 커밋한 저장되어 있는 것을 볼 수 있습니다.

내부 동작 과정

## 블롭(Blob) 생성:

변경된 파일(hello.txt)의 내용을 해시(SHA-1)로 변환하여 Blob 객체로 저장함.

## 트리(Tree) 생성:

Blob을 포함하는 트리(Tree) 객체를 생성하여 디렉토리 구조를 기록함.

## 커밋 객체(Commit Object) 생성:

트리(Tree) 객체를 참조하는 Commit 객체를 생성함.
이 커밋에는 작성자(author), 날짜(timestamp), 커밋 메시지(message), 이전 커밋 정보(parent commit) 등이 포함됨.

## HEAD 업데이트:

커밋이 성공적으로 생성되면 HEAD 포인터가 가장 최근 커밋을 가리키도록 변경됨.

순서도

+----------------------------------+
| 1. 작업 디렉토리에서 파일 수정  |
+----------------------------------+
             |
             v
+----------------------------------+
| 2. git add 명령어 실행         |
|    (스테이징 영역에 추가)       |
+----------------------------------+
             |
             v
+----------------------------------+
| 3. Blob 객체 생성              |
|    (파일 내용을 해시 변환하여 저장) |
+----------------------------------+
             |
             v
+----------------------------------+
| 4. 트리(Tree) 객체 생성        |
|    (Blob을 포함하여 디렉토리 구조 기록) |
+----------------------------------+
             |
             v
+----------------------------------+
| 5. Commit 객체 생성            |
|    (트리 참조, 작성자, 메시지, 부모 커밋 정보 포함) |
+----------------------------------+
             |
             v
+----------------------------------+
| 6. HEAD 업데이트               |
|    (가장 최근 커밋을 가리키도록 변경)  |
+----------------------------------+
  • Git은 파일을 직접 저장하는 것이 아니라, Blob → Tree → Commit 형태로 객체를 생성하고, 이를 연결하여 저장소의 변경 이력을 관리합니다.
  • 커밋이 생성되면 HEAD 포인터가 업데이트 되어 최신 커밋을 가리키게 됩니다.

커밋 사진
위의 C0은 가장 최근 커밋입니다. c0을 커밋한 후 코드를 작성하다가 C1을 커밋할 경우 main의 head는 C1을 가리킵니다. 한번 더 코드를 작성하고 커밋할 경우 head가 C2로 변경된 것을 볼 수 있습니다.

git branch

깃 브랜치에 대한 설명입니다.

  • 하나의 커밋과 그 부모 커밋들을 포함하는 작업 내역
  • Git의 브랜치는 단순히 커밋을 가리키는 포인터일 뿐입니다. 브랜치를 생성하면, 기존 커밋을 가리키는 새로운 포인터가 생성됩니다.
[기본 상태]
A - B - C (main)
         ↑
       HEAD

[새로운 브랜치 생성 후]
A - B - C (main, feature-branch)
         ↑
       HEAD

[feature-branch에서 새로운 커밋 추가]
A - B - C (main)
         \
          D - E (feature-branch)
                    ↑
                  HEAD
  • feature-branch가 C에서 분기됨.
  • D, E 커밋이 추가되었지만 main 브랜치는 영향을 받지 않음.


위의 사진을 보면 main에서 commit을 쌓다가 c2에서 개발하던 중에 bug를 고쳐달라는 연락을 받습니다. 그래서 개발자는 bugFix라는 새로운 브런치를 만들고, bug를 고쳐 나갑니다. main과 bugFix는 서로 가리키는 해쉬값(주소)가 다르기 때문에 서로 영향을 받지 않습니다.

git merge

  • 두 개의 브랜치를 하나로 합치는 명령어입니다.
  • 한 부모의 모든 작업내역과 나머지 부모의 모든 작업, 그리고 그 두 부모의 모든 부모들의 작업내역을 포함합니다.

병합 과정

Before:
A - B - C (main)
         \
          D - E (feature-branch)

After:
A - B - C - D - E (main)
  • feature-branch가 main의 최신 커밋에서 분기되었고, main에서 새로운 커밋이 없을 때 발생.
  • main 브랜치가 단순히 feature-branch의 최신 커밋을 가리키도록 변경됨.
  • 별도의 병합(commit) 없이 브랜치가 앞당겨지는 방식.

위에서 보면 main 브런치의 최근 커밋이 C입니다. C에서 파생된 feature-branch는 main의 커밋 해쉬값을 가지고 있기 때문에 병합하는데 문제가 없습니다.

하지만 main의 C커밋에서 새로운 브런치를 만든 다음에 개발하고 난 뒤 main에서 F커밋을 만들어버리면 어떻게 될까요?

Before:
A - B - C (main)
         \
          D - E (feature-branch)

After:
A - B - C - F (main)
         \   /
          D - E (feature-branch)
  • Git은 공통 조상(Common Ancestor) 을 찾고, main과 feature-branch의 변경 사항을 비교하여 새 병합 커밋을 생성합니다.
  • F는 C와 E를 병합한 새로운 병합 커밋(Merge Commit).

위 내용처럼 main 브런치의 최근 커밋인 F와 feature-branch브런치의 최근 커밋인 E를 병합하여 새로운 F커밋을 생성합니다.

c1에서 bugFix 브런치를 새로 생성합니다. bugFix 브런치로 이동한 후 커밋을 합니다. 이게 C2입니다. 그리고 main에서 새로 커밋을 생성시켰고, c2와 c3가 병합해서 c4를 생성시켰습니다.

git Rebase

기본적으로 커밋들을 모아서 복사한 뒤, 다른 곳에 떨궈 놓는 것입니다.

merge와 차이점

  • git merge → 브랜치를 병합하면서 새로운 Merge Commit을 생성 (히스토리가 남음)
  • git rebase → 브랜치의 커밋을 재배치하여 히스토리를 깔끔하게 정리 (불필요한 Merge Commit 제거)

작동 방식

Before:
A - B - C (main)
         \
          D - E (feature-branch)

After `git rebase main`:
A - B - C - D' - E' (feature-branch)

위 사진을 보면 c1에서 bugFix 브런치를 생성한 뒤 bugFix 브런치르 이동해서 커밋했습니다(c2). 그리고 main에서 커밋합니다(c3). c2는 rebase명령어를 통해서 main branch로 복사됩니다. 여기서 원본인 c2는 삭제되지 않고 어딘가에 남아있게 됩니다.

긴 글 읽어주셔서 감사합니다.

profile
취업 준비생 낚곰입니다!! 반갑습니다!!

0개의 댓글