티스토리 뷰
commit, branch, HEAD

git의 내부구조는 C의 포인터와 연결리스트 개념과 아주 비슷한 듯 하다.
(1)
각 커밋 개체는 내부 포인터로 해당 작업 시점의 스냅샷 (트리구조로 이루어짐) 과 부모 커밋을 가리킨다.
연결리스트로 연결된 링크를 통해 차례로 이전 커밋에 도달할 수 있고,
도달한 커밋을 통해 해당 작업 시점으로 인덱스와 워킹 디렉토리를 돌려 놓을 수 있게 된다.
(2)
브랜치는 포인터! (커밋을 가리키는 포인터)
Git의 브랜치는 커밋 사이를 가볍게 이동할 수 있는 어떤 포인터 같은 것이다.
기본적으로 Git은 master 브랜치를 만든다. 처음 커밋하면 이 master 브랜치가 생성된 커밋을 가리킨다. 이후 커밋을 만들면 master 브랜치는 자동으로 가장 마지막 커밋을 가리킨다. - [ git-scm.com/book ]
브랜치를 삭제한다는 것도 그 브랜치에 속한 커밋들을 지운다던가 실제 데이터들을 지우는게 아니라
free(p)처럼 필요없어진 포인터를 해제하는 것이다.
(2-1)
리모트 트래킹 브랜치 ((로컬의 브랜치))는 리모트 브랜치=upstream branch ((리모트의 브랜치))를 추적하는 레퍼런스이며 브랜치다.
리모트 트래킹 브랜치의 이름은 <remote>/<branch> 형식으로 되어 있다
리모트 트래킹 브랜치는 로컬에 있지만 임의로 움직일 수 없다. 리모트 서버에 연결할 때마다 리모트의 브랜치 업데이트 내용에 따라서 자동으로 갱신될 뿐이다.
리모트 트래킹 브랜치는 일종의 북마크라고 할 수 있다. 리모트 저장소에 마지막으로 연결했던 순간에 브랜치가 무슨 커밋을 가리키고 있었는지를 나타낸다. - [ git-scm.com/book ]
fetch 했을때 가져오는 커밋들은 이 remote/branch 형식의 리모트 트래킹 브랜치가 가리킨다.
(git pull origin master === git fetch origin master ; git merge origin/master)


origin/main 브랜치만 이동한 것을 보라!!
이런 트래킹 브랜치는 읽기 전용이라서 reset등의 명령어로 임의로 다른 커밋을 가리키게 만들 수 없고,
fetch, pull, push등의 명령어로 리모트 저장소랑 동기화 되는 시점에만 가리키는 커밋 위치가 업데이트 된다.
(3)
HEAD도 특수한 포인터! (C의 이중포인터 처럼, 브랜치를 가리키는 포인터)
지금 작업 중인 브랜치가 무엇인지 Git은 어떻게 파악할까. 다른 버전 관리 시스템과는 달리 Git은 'HEAD’라는 특수한 포인터가 있다. 이 포인터는 지금 작업하는 로컬 브랜치를 가리킨다. - [ git-scm.com/book ]
checkout = HEAD가 가리키는 브랜치 바꾸기. (change current local branch)
중요 개념 알아두기

reset 옵션
reset으로 바뀔수 있는 3가지
(1) HEAD 브랜치 (HEAD가 가리키는 브랜치) 가 가리키는 커밋
(2) 인덱스
(3) 워킹디렉토리
soft : (1) - commit 명령 되돌리는 효과 (이미 생성된 커밋 개체가 없어지진 않으므로 좀 다르긴 하지만)
mixed : (1)+(2) - add + commit 명령 되돌리는 효과 (명시적으로 적지않으면 default값이 mixed임)
hard : (1)+(2)+(3) - 작업 내용 되돌려지고 + add + commit 명령 되돌리는 효과
조심해야할 것은 hard 명령어 정도이다.
커밋한적 없는 변경사항이 (그 변경이 없었던 작업상태로) 덮여진다.
그럼 커밋한 적이 없으니 어디가서 다시 불러올 수 도 없다. 그냥 바이바이
★reset 한걸 다시 되돌리고 싶으면 git reflog 명령어로 돌아가길 원하는 커밋번호 확인하기
Merge 유형
(1) fast-forward merge

Merge 메시지에서 “fast-forward” 가 보이는가. hotfix 브랜치가 가리키는 C4 커밋이 C2 커밋에 기반한 브랜치이기 때문에 브랜치 포인터는 Merge 과정 없이 그저 최신 커밋으로 이동한다.
이런 Merge 방식을 “Fast forward” 라고 부른다. 다시 말해 A 브랜치에서 다른 B 브랜치를 Merge 할 때 B 브랜치가 A 브랜치 이후의 커밋을 가리키고 있으면 그저 A 브랜치가 B 브랜치와 동일한 커밋을 가리키도록 이동시킬 뿐이다.
- [ git-scm.com/book ]
(2) 3 way merge + merge commit

이 경우에는 Git은 각 브랜치가 가리키는 커밋 두 개와 공통 조상 하나를 사용하여 3-way Merge를 한다.
단순히 브랜치 포인터를 최신 커밋으로 옮기는 게 아니라 3-way Merge 의 결과를 별도의 커밋으로 만들고 나서 해당 브랜치가 그 커밋을 가리키도록 이동시킨다. 그래서 이런 커밋은 부모가 여러 개고 Merge 커밋이라고 부른다.
- [ git-scm.com/book ]
Rebase 주의하기
커밋 히스토리를 "선형"으로 만들어서 보기 깔끔하게 할 수 있고,
내가 메인 브랜치에서 분기해서 작업한 커밋들을 메인 브랜치의 최신 커밋에서 이어지는 것처럼 만들어서,
나의 push에 대해 원격저장소 입장에서 fast-forward 방식으로 간단히 합칠 수 있다는 편의성이 있지만
절대!!! 이미 remote에 공개한 커밋에 대해서는 이런 변형을 가하지 말 것!!!!! (혼자 작업하는 것이 아니라면)
이미 공개 저장소에 Push 한 커밋을 Rebase 하지 마라
이 지침만 지키면 Rebase를 하는 데 문제 될 게 없다. 하지만, 이 주의사항을 지키지 않으면 사람들에게 욕을 먹을 것이다. - [ git-scm.com/book ] (ㅋㅋㅋㅋ)
참고 :
'조각글' 카테고리의 다른 글
SDKMAN (0) | 2023.10.08 |
---|---|
golang 모듈 (0) | 2023.04.05 |
devops 따라하기 시리즈 (0) | 2022.03.22 |
영역함수 (0) | 2021.11.05 |
git 빠르게 시작하기 (0) | 2021.02.21 |