티스토리 뷰

728x90
반응형

지옥에서 온 Git 강의를 요약한 블로깅 입니다. 헷갈리는 내용만 적어서 강의랑 같이 봐주시면 좋을 것 같습니다.

intro

git init
현재 디렉토리에다가 작업을 진행하겠다.

git status의 Untracked files
이 파일을 깃한테 버전 관리를 시작하라고 하기전까진 git이 무시한다.

git add
git한테 관리하라고 얘기를 해주는 것. 최초로 추적할 때도 add를 사용하고, 파일이 변경되고 난 뒤에도 add를 써야한다.

git commit

  • 버전은 의미있는 변화라고 말 할 수 있다.
  • 현재 버전의 메세지
  • 이 변화가 어떤 변화를 담고 있는지, 이 파일들이 왜 변경되었는지 그 이유를 적는 것이 변경 메세지, 커밋 메세지
  • add를 하면 commit 대기 상태에 들어간다. commit 명령을 실행하면 commit 대기 상태에 있는 파일들만을 포함 시킴. 커밋 대기 상태를 stage area라고 부른다.

git add하기 전 디렉토리를 Working Directory라고 부름
git add를 하고 난 파일들을 index = staging area = cache라고 부름
git commit을 한 파일들을 repository라고 부름

git log -p
키밋과 커밋 사이의 소스 상의 차이점

git diff {commit ID}..{commmit ID}
commit ID 사이의 차이점

.git 디렉토리 구조

git add를 하면

  1. 파일의 내용을 sha-1 해시 함수를 거쳐 해시 값으로 변환함
  2. .git/objects 디렉토리 아래 해시 값으로 된 디렉토리를 만들고 파일의 내용을 저장

image

파일이 서로 달라도 그 내용이 같으면 같은 해시 값을 가지게 되고, .git/objects 디렉토리안에 같은 파일로서 저장이 된다. 이렇게 함으로써 중복된 파일들을 효율적으로 관리할 수 있다.

commit도 내부적으로는 객체이고, commit을 하면 objects 디렉터리 안에 저장되게 된다. commit 객체 관련 파일에는 tree라고 하는 것이 있는데 commit한 파일들이 뭐가 있는지 알려준다.

image

image

commit 객체에서 중요한 정보 2가지

  1. parent: 이전 commit이 뭔지 알려줌
  2. tree: commmit이 일어난 시점에 작업 디렉토리에 있는 파일의 이름과 파일의 내용과 같은 정보

object 디렉토리 정리하자면

  • blob: 파일의 내용
  • tree: blob에 대한 정보
  • commit: parent, tree

git status의 원리

.git 디렉토리의 index 정보와 object 디렉토리의 가장 최신 tree 정보들과 비교해서 status를 알게된다.

코드 수정후 git add를 하기 전의 상황이라면 index 파일 내용의 값과 f2.txt의 현재 내용이 다르면 수정됐음을 알 수 있다.

git add를 하고 나서 index 파일 내용과 commit 최신 tree가 가르키는 내용이 다르다면 git은 index에 add 되어서 commit 대기 상태임을 알 수 있다.

git commit을 하고 나면 실제 파일 내용과 index, tree의 내용이 모두 같으므로 git commit이 다 됐고 clean 하다고 알려준다.

branch

작업이 분기되는 현상을 branch를 만든다라고 한다.

기본적으로 작업을 쭉 진행해왔다면 하나의 branch를 가지고 있다.

svn branch 기능은 불편하고 위험했다. git이 가지고 온 혁신 중 하나는 branch를 쓸만한 수준까지 끌어올렸다.

git log --branches --decorate
모든 브랜치를 다 보여준다. HEAD는 현재 checkout된 브랜치를 의미한다.

git log --branches --decorate --graph
그래프 형태로 고도화 시키기

git log --branches --decorate --graph --oneline
더 간단하게 보기

git log {브랜치1}..{브랜치2}
브랜치1에는 없고 브랜치2에는 있는 것들

git log -p {브랜치1}..{브랜치2}
소스 코드의 diff까지 보여준다.

git diff {브랜치1}..{브랜치2}
diff만 보기

브랜치2를 브랜치1로 merge(exp를 master로 가지고 오기)
브랜치1이 HEAD인 상태에서 git merge {브랜치2}

브랜치 병합을 한 commit은 2개의 부모(아래 그림) commit을 가진다. 원래 가지고 있었던 commit과 병합한 commit.

image

위 사진에서 5번 commit도 exp로 가지고 올려면 = 2번 브랜치가 1번 브랜치랑 완전 같은 상태가 되려면 exp 브랜치에서
git merge master

image

Fast-forward vs 3 Way Merge

https://git-scm.com/book/en/v2/Git-Branching-Basic-Branching-and-Merging

git merge hotfix
Fast-forward(빨리감기)
master 브랜치에서 hotfix가 독립한 이후에 master 브랜치는 어떠한 commit도 새로 만들지 않았음. 이 경우에 master 브랜치로 hotfix를 병합한다라는 것은 master 브랜치가 가르키는 commit을 hotfix가 가르키는 commit으로 빨리 감기를 하면 병합 작업이 끝난다. 별도의 commit을 생성하지 않는다.

git merge iss53
Merge made by the 'recursive' strategy.
지금 상황은 master에 변화가 생겼음. 이것은 Fast-forward merge로는 안된다. 3way merge 사용.

3 way merge

  1. master와 iss53의 공통의 조상을 찾음
  2. 각 브랜치의 HEAD(최신 상태)를 합침
  3. 합쳤다는 커밋 메세지를 만듬

stash

WIP: working in process

git stash: 저장

git stash apply: 적용

git stash list
명시적으로 삭제하지 않는 이상 항상 여기에 쌓여있고, 살아있음

git reset --hard HEADgit stash apply 다시 stash 내용이 apply됨

최신 stash가 아닌 더 뒤쪽의 stash까지 적용하고 싶다면, git stash drop으로 가장 최근 stash 삭제

git stash apply + git stash drop = git stash pop

git stash는 버전 관리가 되고 있는 파일(add를 한번은 한 파일)에 대해서만 stash apply를 한다. Untracked files에 대해서는 stash apply를 안함

branch 원리

git init
.git/HEAD가 만들어짐. 여기에는 refs/heads/master가 적혀있다.

git add, git commit
.git/refs/heads/master 이것은 commit을 가리키게된다. 다시 또 commit을 하면 그 commit을 가리키게 된다.


.git/refs/heads/에 브랜치명으로 폴더가 생긴다.


git checkout
.git/HEAD 파일에 정보가 변경된 브랜치로 바뀌게된다.

branch 충돌 해결

# branch exp
function a(){
}

# branch master
git merge exp

# branch master
function b(){
}
function a(){
}

# branch exp
function a(){
}
function c(){
}

# branch master
git merge exp

# branch master
function b(){
}
function a(){
}
function c(){
}

같은 파일이더라도 각 브랜치에서 서로 수정한 위치가 다르다면 자동으로 합친다.

# branch exp
git merge master

# branch exp
function b(){
}
function a(){
}
function c(){
}

# branch master
function b(){
}
function a(master){
}
function c(){
}

# branch exp
function b(){
}
function a(exp){
}
function c(){
}

# branch master
git merge exp

충돌이 발생하게된다.

# branch master
function b(){
}
<<<<<<< HEAD
function a(master){
}
=======
function a(exp){
}
>>>>>>> exp
function c(){
}

======= 구분선 기준으로 위, 아래로 충돌난 내용이 적혀있다. 적절히 수정

# branch master
function b(){
}
function a(master,exp){
}
function c(){
}

git add {}
git commit

reset

git reset --hard {HEAD가 아닌, 가려고 하는 위치의 commit ID}
해당 commit으로 가고, 그 위의 commit들은 지워진다.

master 브랜치에서 git reset을 하면 .git/refs/heads/master(어떤 커밋을 최신 커밋으로 가지고 있는지에 대한 정보)파일이 바뀐다.

.git/ORIG_HEAD: 삭제된 commit을 가리키고 있다.

.git/logs/refs/heads/master: commit이 어디에서 어디로 바꼈는지에 대한 기록들이 적혀있다. master브랜치에서 일어난 사건, 역사들을 저장하는 곳

git reset --hard ORIG_HEAD
ORIG_HEAD를 reset해서 hard 옵션의 reset도 복구할 수 있다.

git reflog
.git/logs/refs/를 볼 수 있는 명령어

working directory, index, repository 3가지의 구조, reset의 옵션들에 따라 이 3가지를 reset함

working directory = working tree = working copy
작업을 진행하는 곳

index=staging area = cache
git add

repository = history = tree
git commit

--soft는 repository까지, --mixed는 index까지, --hard는 working directory까지 reset한다.

image

git log -p
commit 수준에서 소스 상의 차이점. repository를 확인할 때, soft 옵션 reset의 적용을 확인할 때 사용

git diff
working copy, index의 내용을 비교하는 명령

checkout

git checkout {commit ID}
checkout을 할 때 commit ID를 직접 적을 수 있다. .git/HEAD가 바뀌게 되는데 직접 commit을 바라보고 있음을 알 수 있다. 즉 어떤 브랜치를 가르키지 않고, commit을 직접 가르키고 있음을 알 수 있다. detached 되어 있는 상태이다. 실제로 브랜치가 생기는 것은 아니다.

3 way merge

충돌이 일어났을 때 .git/index에 공통으로 적혀 있었던 것 각 브랜치에 수정한 것 총 3개의 정보가 있게 된다.

2 way merge
base를 보지 않고, 브랜치 2개의 차이점만 비교해서 병합을 하는 방식

3 way merge
base를 참고해서 병합하는 방식

image

pull vs fetch

fetch
원격 저장소에서 가져오기만 함.

pull
fetch + merge. 원격 저장소에서 가져와서 원격 저장소에서 로컬 저장소로 병합

git tag

branch와 똑같이 tag도 어떤 특정한 commit id를 가리키지만 tag는 언제나 똑같은 commit id를 가리키고, branch는 계속 바뀐다.

git tag {1.0.0} {적지 않거나, commit id, 브랜치 이름}
commit id를 적지 않으면 현재 HEAD로 tag를 만들고 commit id를 적으면 commit id에 대한 tag, 브랜치의 이름을 적어도 된다.

git checkout {tag name}
그 태그로 돌아가기

annotated tag
좀 더 자세한 내용을 추가하는 태그

git tag -a 1.1.0 -m "bugfix" {안적거나, branch name, commit id}
annotated tag 하는 예시

git tag -v {tag name}
tag 자세히 확인

git push 할 때 --tags 옵션을 추가해서 원격 업로드하면 원격 저장소(GitHub)에 ui로 잘 보인다.

git tag -d {tag name}
태그 지우기

rebase

image

feature 입장에서 base는 공통으로 가지고 있는 commit 지점이 base이다.

feature가 rebase를 한다는 것은 base를 바꾼다는 것인데 master branch의 최신 commit으로 base를 바꾼다는 것. 그리고 그 뒤에 feature의 commit들을 병합한다.

728x90
반응형
댓글
반응형
250x250
글 보관함
최근에 달린 댓글
«   2024/04   »
1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30
Total
Today
Yesterday
링크