참고 사이트
깃 사용법 연습
사이트에서 사용할 수 있는 명령어는 다음과 같습니다.
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 업데이트 |
| (가장 최근 커밋을 가리키도록 변경) |
+----------------------------------+

위의 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

위의 사진을 보면 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)
위에서 보면 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)
위 내용처럼 main 브런치의 최근 커밋인 F와 feature-branch브런치의 최근 커밋인 E를 병합하여 새로운 F커밋을 생성합니다.

c1에서 bugFix 브런치를 새로 생성합니다. bugFix 브런치로 이동한 후 커밋을 합니다. 이게 C2입니다. 그리고 main에서 새로 커밋을 생성시켰고, c2와 c3가 병합해서 c4를 생성시켰습니다.
git Rebase
기본적으로 커밋들을 모아서 복사한 뒤, 다른 곳에 떨궈 놓는 것입니다.
merge와 차이점
작동 방식
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는 삭제되지 않고 어딘가에 남아있게 됩니다.
긴 글 읽어주셔서 감사합니다.