Profile

Git Basic

CATEGORY
Git
TOPIC
STATUS
CREATED TIME
2023/03/10 14:48
ORIGINAL SOURCE
ORDER
0
SERIES

Local Git

1. Git 기본

Commit

Git 커밋은 디렉토리에 있는 모든 파일에 대한 스냅샷을 기록 - 각 커밋은 저장소의 이전 버전과 다음 버전의 변경내역(delta)을 저장함. - 따라서 대부분의 커밋이 그 커밋 위의 부모 커밋을 가리킨다. 저장소를 복제(clone)하려면 모든 변경분(delta)를 풀어내야 하는데, 이 때문에 다음과 같은 문구만남 - resolving deltas
Plain Text

Branch

Branch: 하나의 커밋과 그 부모 커밋들을 포함하는 작업 내역 - Branch는 특정 커밋에 대한 참조 (reference)다. - 브랜치는 메모리나 디스크 공간에 부담을 주지 않는다.
Plain Text

Merge

Merge: merge는 두 개의 부모 (parent)를 가리키는 특별한 커밋을 만든다. - 두개의 부모가 있는 커밋이란: 한 부모의 모든 작업내역과 나머지 부모의 모든 작업, 그리고 그 두 부모의 모든 부모들의 작업내역을 포함한다. * Merge: 메인브랜치 <- bugFix브랜치 1. git checkout main 2. git merge bugFix C1 ------- C3 -------- C4 (main*) \___ C2 (bugFix) ___/ 3. git checkout bugFix C1 ------- C3 -------- C4 (main) \___ C2 (bugFix*) ___/ 4. git merge main C1 --- C3 --- C4 (main, bugFix*) \___ C2 ___/
Plain Text

Rebase

Rebase: rebase는 기본적으로 커밋들을 모아서 복사한 뒤, 다른 곳에 떨궈 놓는 것이다. - 커밋들의 흐름을 보기 좋게 한 줄로 만들 수 있다는 장점 - 저장소의 커밋 로그와 이력이 한결 깨끗해진다. * Rebase: bugFix의 Base 이동 시키기 1. git checkout bugFix 2. git rebase main C1 ------- C3 (bugFix) \___ C2 (main) ___ C3` (bugFix*) 3. git checkout main 4. git rebase bugFix C1 ------- C3 (bugFix) \___ C2 ___ C3` (main*, bugFix) 단순히 Fast-Forward
Plain Text

2. HEAD

HEAD는 현재 체크아웃 된 커밋을 가리킨다. 즉 현재 작업중인 커밋이다.
작업트리에 변화를 주는 git 명령어들은 대부분 HEAD를 변경하는 것으로 시작한다.

HEAD 분리

HEAD를 분리한다는 것은 HEAD를 브랜치 대신 커밋에 붙이는 것을 의미한다.
Plain Text

상대 참조 (^) Relative Refs

- ^ : 한번에 한 커밋 위로 움직임 - ~<NUM> : 한번에 여러 커밋 위로 올라감 main^ : main의 부모와 같은 의미 main^^ : main의 부모의 부모와 같은 의미 HEAD~4 : HEAD 가 가리키는 커밋의 위로 4번 째 커밋
Plain Text

브랜치 강제 옮기기

git branch -f main HEAD~3 : main 브랜치를 HEAD에서 세번 뒤로 옮긴다. - 상대 참조를 사용하는 가장 일반적인 방법 - -f 옵션을 이용하여 브랜치를 특정 커밋에 직접적으로 재지정할 수 있다.
Plain Text

작업 되돌리기 - reset, revert

변경내역을 되돌리는 것도 커밋과 마찬가지로 - 낮은 수준의 일 (개별 파일이나 묶음을 스테이징 하는 것)과 - 높은 수준의 일 (실제 변경이 복구되는 방법)이 있다.
Plain Text
Reset
Reset: 브랜치로 하여금 예전의 커밋을 가리키도록 이동시키는 방식으로 변경 내용을 되돌린다. - 이런 관점에서 "히스토리를 고쳐쓴다"고 할 수 있음. - 즉 애초에 커밋하지 않은 것처럼 예전 커밋으로 브랜치를 옮기는 것 1. git checkout main C0 --- C1 --- C2 (main*) 2. git reset HEAD~1 C0 --- C1 (main*) --- C2
Plain Text
Revert
Reset 은 히스토리를 고쳐쓴다는 점에서 다른 사람이 작업하는 리모트 브랜치에는 적용할 수 없다. Revert를 통해 변경분을 되돌리고, 이 되돌린 내용을 다른 사람들과 공유한다. 1. git checkout main C0 --- C1 --- C2 (main*) 2. git revert HEAD C0 --- C1 --- C2 --- C2` (main*) C2라는 새로운 커밋에 변경내용이 기록되는데, 이 변경내역이 정확히 C2 커밋 내용의 반대되는 내용이다. Push 를 통해 다른사람들과 변경 내역 공유.
Plain Text
문제: remote와 local 두 브랜치의 최근 변경 사항을 되돌린다. C0 --- C1 (main) --- C3 (local*) \____ C2 (remote) 1. git reset HEAD^ C0 --- C1 (main, local*) --- C3 \____ C2 (remote) 2. git checkout remote C0 --- C1 (main, local) --- C3 \____ C2 (remote*) 3. git revert HEAD C0 --- C1 (main, local) --- C3 \____ C2 ___ C2` (remote*)
Plain Text

3. 작업트리 수정

git의 나머지 10% 기능
작업중 막히는 등의 복잡한 작업 중 유용

Cherry-pick

Cherry-Pick: 현재 위치 (HEAD) 아래에 있는 일련의 커밋들에 대한 복사본을 만든다. git cherry-pick <Commit1> <Commit2> <...> * main 브랜치 <- side 브랜치의 작업내역 1. git checkout main C0 --- C1 --- C5 (main*) \___ C2 ___ C3 ___ C4 (side) 2. git cherry-pick C2 C4 C0 --- C1 --- C5 --- C2` --- C4` (main*) \___ C2 ___ C3 ___ C4 (side)
Plain Text

인터렉티브 리베이스

- 체리픽은 원하는 커밋이 무엇인지 알때 (해시값) 유용하다. - 하지만 원하는 커밋을 모르는 상황에서 인터렉티브 리베이스를 사용한다. 인터렉티브 리베이스: rebase 명령어에 -i 옵션 사용 인터렉티브 리베이스 대화창(UI)에서 할 수 있는 일 - 적용할 커밋들의 순서를 UI를 통해 변경할 수 있다. - 원하지 않는 커밋을 제외할 수 있다. (pick 을 통해) - 커밋을 스쿼시 (squash) 할 수 있다. <- 커밋을 합칠 수 있다. 1. git checkout main C0 --- C1 --- C2 --- C3 --- C4 --- C5 (main*) 2. git rebase -i HEAD~4 - 생략 / 선택 / 커밋 순서 변경의 작업 가능 - 최종 적용 : C2(X), C4, C3, C5 C0 --- C1 --- C2 --- C3 --- C4 --- C5 \___ C4` ___ C3` ___ C5` (main*)
Plain Text

4. 다양한 테크닉

한 개의 커밋만 가져오기

개발 중 일어날 수 있는 상황: bugFix 상황에서 디버깅용 커밋들이 많이 들어가있는데 bugFix 브랜치의 내용을 main 에 병합시키고 fast-forward 하면 불필요한 디버깅용 코드들도 함께 포함된다.
cherry-pick 혹은 rebase -i 를 통해 선택적으로 커밋을 취하거나 버릴 수 있다.

커밋들 갖고 놀기

상황 : newImage와 caption 브랜치에 각각의 변경내역이 있고, 서로 관련이 있어 저장소에 차례로 쌓이는 상황이다. 때로는 이전 커밋의 내용을 살짝 변경해야 하는 상황이 있다. 디자인 쪽에서 우리의 작업이력에서는 이미 한참 전의 커밋 내용에 있는 newImage의 크기를 살짝 변경해달라는 요청이 들어왔다. - git rebase -i 명령을 통해 바꿀 커밋을 가장 최근 순서로 바꾼다. - git commit --amend 명령으로 커밋 내용을 정정한다. - git rebase -i 명령으로 이 전의 커밋 순서대로 되돌려 놓는다. 1. git checkout caption C0 --- C1 (main) --- C2 (newImage) --- C3 (caption*) 2. git rebase -i HEAD~2 C0 --- C1 (main) --- C2 (newImage) --- C3 \___ C3` ___ C2` (caption*) 3. git commit --amend C0 --- C1 (main) --- C2 (newImage) --- C3 \___ C3` ___ C2` \___ C2`` (caption*) 3. git rebase -i HEAD~2 C0 --- C1 (main) --- C2 (newImage) --- C3 \___ C3` ___ C2` \ \___ C2`` \___ C2`` ___ C3`` (caption*) 4. git checkout main C0 --- C1 (main*) --- C2 (newImage) --- C3 \___ C3` ___ C2` \ \___ C2`` \___ C2`` ___ C3`` (caption) 5. git rebase caption C0 --- C1 --- C2 (newImage) --- C3 \___ C3` ___ C2` \ \___ C2`` \___ C2`` ___ C3`` (main*, caption)
Plain Text

커밋 갖고 놀기 #2

cherry-pick 으로 해결하기: cherry-pick으로 HEAD에다 어떤 커밋이든 떨어 뜨려 놓을 수 있다. 1. git checkout caption C0 --- C1 (main) --- C2 (newImage) --- C3 (caption*) 2. git checkout main C0 --- C1 (main*) --- C2 (newImage) --- C3 (caption) 3. git cherry-pick newImage C0 --- C1 --- C2 (newImage) --- C3 (caption) \___ C2`` (main*) 4. git commit --amend C0 --- C1 --- C2 (newImage) --- C3 (caption) \___ C2`` \___ C2`` (main*) 5. git cherry-pick caption C0 --- C1 --- C2 (newImage) --- C3 (caption) \___ C2`` \___ C2`` ___ C3` (main*)
Plain Text

태그

Tag: 프로젝트의 작업 이력 중 중요한 지점에 영구적으로 표시할 방법 - 릴리즈, 큰 브랜치 병합 등 - 태그는 커밋들이 추가적으로 생성되어도 절대 움직이지 않는다. 1. git checkout main C0 --- C1 --- C2 (main*) 2. git tag v1 C1 C0 --- C1 (v1) --- C2 (main*)
Plain Text

Git Describe

git describe: git 커밋 트리를 이동하던 중 커밋 트리상 현재 위치 (방향감각)을 다시 찾는데 도움을 준다. git bisect: 문제가 되는 커밋을 찾는 명령어 사용방법 git describe <ref> / <ref>: 커밋을 의미함. 미지정시 Default = HEAD 출력 <tag>_<numCommits>_g<hash> - tag: 가장 가까운 부모태그를 나타낸다. - newCommits: 그 태그가 몇 커밋 멀리 있는가? - hash: 묘사하고 있는 커밋의 해시를 나타낸다. 1. git checkout side C0 (v1) --- C1 --- C3 --- C4 (side*) \___ C2 (main) 2. git tag v2 C# C0 (v1) --- C1 --- C3 (v2) --- C4 (side*) \___ C2 (main) git describe main -> v1_2_gC2 git describe side => v2_l_gc4
Plain Text

5. 고급 문제

여러 브랜치를 리베이스 (rebase)하기

- 여러 브랜치를 main 브랜치에 리베이스 하기. - 모든 커밋들을 순서에 맞게 정렬하기.
Plain Text

부모 선택하기

~<NUM> : 몇 개의 세대를 돌아갈지 정하는 것 ^<NUM> : 병합이 된 커밋에서 어떤 부모를 참조할지 선택할 수 있음. - 병합된 커밋들은 다수의 부모를 가지고 있다. 어떤 부모를 선택할지 예측할 수 없다. - 깃은 보통 병합된 커밋에서 '첫'부모를 따라간다. 하지만 ^ 수식을 숫자와 함께 사용하면 앞의 디폴트 동작대로가 아닌 다른 결과가 나타난다. 1. git checkout main C0 --- C1 --- C3 (main*) \___ C2 ___/ 2. git checkout main^ C0 --- C1 (HEAD) --- C3 (main) \______ C2 ______/ 메인을 수식없이 체크아웃 한다면 병합된 커밋의 첫 부모를 따라 올라간다. 3. git checkout main^2 C0 ------ C1 ------- C3 (main) \___ C2 (HEAD) ___/ 병합된 커밋의 두번째 부모를 따라 올라간다.
Plain Text
git checkout HEAD~ git checkout HEAD^2 git checkout HEAD~2 => git checkout HEAD~^2~2
Plain Text

브랜치 스파게티

- main 브랜치의 몇 번 이전 커밋에 one, two, three 총 3개의 브랜치가 있다. - main 의 최근 커밋 몇 개를 나머지 세개의 브랜치에 반영하려고 한다. - one 브랜치는 순서를 바꾸고 cs 커밋을 삭제하고, two 브랜치는 순서만 바꾸며, three 브랜치는 하나의 커밋만 가져온다. C0 --- C1 (one, two, three) --- C2 --- C3 --- C4 --- C5 (main*) => C0 --- C1 --- C2 (three) --- C3 --- C4 --- C5 (main) \___ C4` ___ C3` ___ C2` (one) \___ C5` ___ C4`` ___ C3`` ___ C2`` (two*)
Plain Text

Remote Git

git Remote = 로컬 저장소의 복사본.
백업의 역할 수행
로컬 데이터를 잃더라도 remote 로 부터 다시 시작할 수 있음.
협업으로의 역할

Push & Pull

1. Clone

- 원격 저장소의 복사본을 로컬에 생성 git clone Remote: C0 --- C1 (main) Local : C0 --- C1 (main*, origin/main)
Plain Text

2. 원격 브랜치 (remote branch)

- 원격 브랜치: git clone 시 로컬 저장소에 생기는 'origin/main' 브랜치, 원격 저장소의 상태를 반영한다. - 원격 브랜치는 특정한 목적을 제공하기 때문에 특별한 속성들이 있다. 원격 브랜치는 체크 아웃을 하게 되면 '분리된 HEAD' 모드로 가게되는 속성이 있다. 로컬상 원격 브랜치에서 직접 작업할 수 없기 때문에 일부로 이렇게 한다. - 원격 브랜치는 로컬에서의 작업과 공개적으로 되고 있는 작업의 차이를 이해하는데 도와준다. 1. git clone Remote: C0 --- C1 (main) Local : C0 --- C1 (main*, origin/main) 2. git checkout origin/main Remote: C0 --- C1 (main) Local : C0 --- C1 (main, origin/main*) 3. git commit Remote: C0 --- C1 (main) Local : C0 --- C1 (main, origin/main) --- C2 *
Plain Text

3. Git Fetch

- Git Fetch: 원격 저장소에서 데이터를 가져오는 방법. (talk with remote) 1. 원격 저장소에는 있지만 로컬에는 없는 커밋을 다운로드 받는다. 2. 원격 브랜치가 가리키는 커밋의 위치를 업데이트 한다. 즉, git fetch 는 본질적으로 로컬에서 나타내는 원격 저장소의 상태를 실제 원격 저장소의 상태와 동기화 반면, 원격 저장소의 상태와 동기화에 필요한 데이터를 다운로드 하지만, 로컬의 상태와 파일 시스템을 바꾸지 않는다.
Plain Text

4. Git pull

Plain Text

5. 가짜 팀워크

6. Git push

7. 엇갈린 히스토리

8. 잠겨버린 main 브랜치

Origin 너머로

1. Push Main

2. 원격 작업과 merge하기

3. 원격 저장소 추적하기

4. git push의 인자들

5. git push의 인자 — 확장판

6. Fetch 의 인자들

7. Source가 없다.

8. pull 인자들