깃&깃허브 정리

Hyun·2023년 11월 24일
0

공부한거 정리

목록 보기
19/20

【한글자막】 Git & Github 실무 활용 완벽 가이드 (Colt Steele 강사님) 강의를 보고

  • 중요하다고 생각되는 내용을 정리하였다.

  • 추가로 프로젝트 하면서 필요했던 부분들도 따로 추가하여 정리하였다.


정리한 Chapter

  • Git 기초

  • Branch

  • Git Diff

  • Git Stash

  • 시간 여행

  • Github 기초

  • Git 협업

  • Git Rebase

  • Git Tag

  • Git Reflog

  • Git Alias

  • Git 동작 원리


Git 기초

  • Git 은 가장 대표적인 VCS 이다.

    • Version Control System

    • 파일의 변화를 추적하고 관리하는 프로그램

      • 프로젝트 파일들의 변경사항을 저장하는 체크포인트를 만들어 개발을 돕는다.

Git 이름, 이메일 설정

$ git config --global user.name "Hyun"
# 이름 설정

$ git config --global user.email "ghkdgus29@naver.com"
# 이메일 설정



Git Repository 생성과 상태 확인

  • git repository 만들기
$ git init

.git 디렉토리가 만들어진다.


  • git repository의 상태 확인하기
$ git status

커밋

  • 커밋은 git repository의 체크포인트 중 하나이다.

  • 의미있는 작업단위를 하나의 커밋으로 묶는것이 좋다.

작업 내용을 Staging Area 에 올리고, Staging Area의 내용물들을 커밋하여 Git Repository 에 저장한다.


  • 파일을 Staging Area 에 올리기

    • 추적되지 않는 파일이나 파일의 변경사항을 Staging Area 에 올리려면 add 명령어를 사용한다.
$ git add 파일이름
  • 파일이 여러개인 경우, 띄어쓰기로 여러개를 추가할 수 있다.
  • 모든 작업 파일들을 올리고 싶다면 파일이름 대신 . 사용

  • 커밋하기
$ git commit

vim 에디터와 같은 편집기로 커밋메시지를 작성한다.


Log 확인하기

  • 자세한 log 보기
$ git log

  • 간단한 log 보기
$ git log --oneline

  • git hist alias 설정하기
$ git config --global alias.hist "log --graph --all --pretty=format:'%C(yellow)[%ad]%C(reset) %C(green)[%h]%C(reset) | %C(white)%s %C(bold red){{%an}}%C(reset) %C(blue)%d%C(reset)' --date=short"


다음과 같이 이쁘게 로그를 볼 수 있다.


바로 직전의 커밋 수정하기

  • 커밋 메시지를 잘못 썼거나 특정 파일을 빼먹고 커밋한 경우와 같이 커밋을 수정해야 하는 경우

  • 바로 직전의 커밋에 대해서만 --amend 명령어를 통해 수정이 가능하다.

  • 까먹은 파일이 있는 경우

$ git add 까먹은 파일이름

까먹은 파일을 Staging Area 에 올린다.


  • 커밋 수정 명령어 실행
$ git commit --amend

직전 커밋 메시지도 변경할 수 있다.


.gitignore

  • 개인정보와 같은 민감한 파일들이나 깃이 관리할 필요 없는 파일들이 Git Repository에 추적 및 저장되지 않도록 하는 설정 파일

.gitignore 파일

  • 깃에서 관리하고 싶지 않은 파일이나 디렉토리를 명시
  • 관례상 프로젝트 최상단에 위치

  • 만약 이미 커밋한 파일을 깃에서 관리하지 않도록 하려면 해당 파일을 untracked 영역으로 내려야 한다.
$ git rm --cached 파일이름
  • git repository 에서 해당 파일을 제거하나, 실제 working directory (로컬 컴퓨터 저장소) 에서는 제거하지 않는다.


  • 다음과 같이 추적되던 파일 (secrets.txt) 을 deleted 함을 확인한 후 변경사항을 커밋한다.

  • 이후의 작업부터는 깃이 secrets.txt 를 추적하지 않는다.

Branch

  • 각각의 Branch는 독립된 문맥 (context) 을 의미한다.

    • 기본적으로 Branch 에서의 작업은 다른 Branch에게 영향을 주지 않는다.

    • 다른 Branch의 작업을 현재 Branch에 적용시키고 싶다면 병합 (merge) 한다.

    • Branch 포인터는 Branch 내의 가장 최근 커밋을 가리킨다.

      • 커밋을 할 때마다 갱신된다.
  • HEAD 는 현재 내가 읽고 있는 Branch 포인터를 가리킨다.

    • ex) HEAD -> master

Branch 목록 보기

$ git branch

Branch 만들기

$ git branch 생성할 브랜치 이름
  • HEAD 가 가리키는 현재 위치에서 branch 를 만든다.




  • 이때 HEAD는 생성한 브랜치로 이동하지 않고 가만히 있는다.

Branch 전환하기

$ git switch 전환할 브랜치 이름

HEAD 가 가리키는 branch가 바뀐다.


$ git switch -c 생성 및 전환할 브랜치 이름

branch 를 만들고 해당 branch로 이동한다.


  • Branch를 이동할 땐 파일의 변경사항들을 커밋하거나 stash 에 저장한 후 이동해야 한다.

Branch 삭제 및 이름 변경

  • 삭제

    • HEAD 가 삭제할 Branch를 가리키면 삭제할 수 없다.

    • 따라서 다른 Branch로 이동해야 한다.

$ git branch -D 지울 브랜치 이름

branch 병합 여부와 상관없이 해당 branch 를 제거한다.


Merge

  • 다른 브랜치에서의 변경 사항을 나의 브랜치에 반영하는 것

  • Fast-Forward Merge

    • 특별하고 간단한 경우의 merge

      • 현재 브랜치의 변경사항없이 병합 브랜치를 merge 하는 경우
    • 나의 branch 포인터를 병합하는 브랜치의 끝까지 이동시킨다.

$ git merge 병합할 브랜치 이름

만약 fast-forward merge 가 일어나는 상황에서 이를 원하지 않는다면

$ git merge --no-ff 병합할 브랜치 이름


다음과 같이 현재 branch 포인터가 병합 branch 포인터까지 이동한다.


  • 일반적인 merge

    • 병합 커밋이 만들어진다.
$ git merge 병합할 브랜치 이름


NEW COMMIT = 병합 커밋


  • merge conflict

    • 현재 브랜치와 병합할 브랜치의 변경사항의 충돌이 발생한 경우

    • 충돌을 해결한 뒤 commit 해야 한다.


충돌을 제거한 후 변경사항을 staging 에 올리고 커밋한다.


Git Diff

  • 깃에서의 변경사항을 보여주는 명령어

  • Staging 된 파일을 기준으로 working directory 의 변경사항을 확인하려면
$ git diff

staging 된 파일


staging 된 파일 기준 working directory 의 변경사항을 확인할 수 있다.


만약 working directory 의 변경사항을 staging area 에 올리면 git diff 로 변경사항을 확인할 수 없다.


  • 직전 커밋과 비교하여 현재의 변경사항 (working directory + staging area) 을 비교하려면
$ git diff HEAD

staging area 에 올린 파일이더라도 직전 커밋과 내용이 다르면 변경사항을 확인할 수 있다.


  • 방금 생성한 numbers.txt 의 경우 staging area 에 올리면, 변경사항을 확인할 수 있다.
    • untracked 파일의 경우엔 git 에서 아예 관리하지 않으므로 git diff HEAD 로도 변경사항을 확인할 수 없다.
    • 따라서 방금 생성한 파일을 staging area 에 올려야 한다.

  • /dev/null 은 해당 파일이 방금 생성되었음을 의미한다.

  • 특정 파일의 변경사항만 확인하려면
$ git diff 파일이름

HEAD 옵션도 사용가능하다.


  • 두 브랜치간의 차이점을 확인하려면
$ git diff 브랜치1..브랜치2

브랜치1이 -, 브랜치2가 + 부호가 된다.


Git Stash

  • 만약 현재 작업중인 브랜치에서

  • 커밋하기엔 애매한 미완성의 작업물들이 있는 상황에

  • 다른 브랜치로 이동하고 싶은 경우 stash에 미완성 작업물들을 임시 저장하고 이동할 수 있다.


  • stash 에 작업물 저장하기
$ git stash
  • git stash save 를 축약한 명령어
  • 모든 작업물들이 stash에 저장된다.

  • stash에서 작업물을 꺼내 적용하기
$ git stash pop

가장 최근에 stash에 저장한 작업물들을 꺼내 working directory 에 적용한다.


  • stash의 작업물 적용하기
$ git stash apply
  • pop 은 stash 에서 저장한 작업물을 꺼내며 working directory 에 작업물을 적용한다.
  • apply 는 stash 에서 저장한 작업물을 꺼내지 않고 working directory 에 작업물을 적용한다.
    • 여러 영역에서 stash에 저장한 작업물을 적용해야 할 경우 사용한다.

  • stash의 작업물들 제거하기
$ git stash list
  • stash 에 임시저장된 작업물들을 보여준다.
  • 여기서 삭제하고 싶은 작업물의 이름을 확인한다.

$ git stash drop stash@{n}

stash의 n번째에 위치한 작업물을 제거한다.


$ git stash clear

stash의 모든 작업물들을 제거한다.


시간 여행


Git Checkout

  • 특정 커밋으로 이동하기 위해 사용한다.

  • Branch 포인터를 가리키는 HEAD가 특정 커밋을 가리키게 된다.

    • detached HEAD 상태

    • switch 명령어를 사용해 HEAD가 다시 Branch 포인터를 가리키도록 할 수 있다.

$ git checkout 커밋해시

  • 현재 HEAD가 가리키는 위치를 기준으로 이전 커밋으로 이동할 수도 있다.
$ git checkout HEAD~n
  • HEAD~1 은 HEAD의 바로 직전 커밋을 의미한다.
  • HEAD~n 은 HEAD 이전 n 번째 커밋을 의미한다.

  • 현재 작업이 마음에 들지 않아 날리고 싶은 경우 가장 최근 커밋으로 checkout 한다.
$ git checkout HEAD 파일이름
  • git checkout -- 파일이름 으로도 같은 작업을 수행할 수 있다.

  • 만약 특정 파일을 이전 커밋의 내용으로 바꾸고 싶은 경우엔 다음처럼 이동하고 싶은 커밋을 지정한다.
$ git checkout HEAD~n 파일이름

Git Reset

  • 특정 커밋까지 되돌아가기 위해 사용하며 mixed reset (default) 과 hard reset 이 있다.

  • mixed reset (default)

    • 이동하는 커밋 이후의 커밋 기록들은 모두 제거된다.

    • 이동하는 커밋 이후의 커밋에서의 작업들은 제거되지 않고 staging 된다.

$ git reset 커밋해시

  • hard reset

    • 이동하는 커밋 이후의 커밋 기록들은 모두 제거된다.

    • 이동하는 커밋 이후의 커밋에서의 작업들도 모두 제거된다.

$ git reset --hard 커밋해시

Git Revert

  • 특정 커밋의 변경사항을 취소하는것은 reset 과 유사하나 커밋기록을 제거하지 않는다.

  • 다른 사람과의 협업을 위해 사용한다.

    • 다른 사람과 공유된 커밋기록을 reset 하면 문제가 발생한다.

Git Reset

  • 커밋 기록이 제거된다.

Git Revert

  • 커밋기록이 제거되지 않는다.
  • 이전 커밋의 작업들을 무효화하는 커밋이 만들어진다.

git revert HEAD

직전 커밋을 무효화하는 Revert 커밋을 만든다.


git revert 돌아가고 싶은 커밋해시..HEAD

돌아가고 싶은 커밋의 이후 커밋들을 모두 무효화하는 Revert 커밋들을 만든다.


Github 기초

  • 로컬에 있는 깃 저장소를 클라우드에 호스팅할 수 있는 플랫폼

    • 즉 Github 는 Git 을 위한 웹서비스이다.
  • 이를 통해 다른 사람들과 쉽게 협업할 수 있다.


Git Clone

  • 클라우드에 호스팅 된 원격 깃 저장소를 복제하여 내 로컬 저장소에 가져온다.

  • 아무런 권한이 없어도 어떤 public 원격 저장소든지 clone 할 수 있다.

$ git clone 원격저장소 URL

Git Remote

  • 비어있는 github 저장소를 만든 후 로컬의 git 저장소를 클라우드 (github) 의 원격 깃 저장소 와 연결한다.

  • 원격 저장소 목록 확인
$ git remote -v

로컬 깃 저장소와 연결된 원격 깃 저장소의 목록을 보여준다.


  • 원격 저장소 연결
$ git remote add origin 원격저장소 URL
  • 원격 깃 저장소와 로컬 깃 저장소를 연결한다
  • 원격 깃 저장소의 이름을 origin 대신 다른 이름을 사용해도 되지만, 관용적으로 origin 을 사용한다.

  • 원격 저장소 이름 변경
$ git remote rename 과거이름 변경할이름

  • 원격 저장소 연결 끊기
$ git remote remove 원격저장소 이름

Git Push

  • 로컬 깃 저장소의 특정 브랜치의 커밋기록을 원격 깃 저장소에 업로드한다.
$ git push origin 브랜치이름

master 브랜치를 Github 원격 저장소에 push 하는것보단 관용적으로 main 브랜치로 이름을 바꿔 push 하는것이 낫다.

$ git branch -M main
  • 브랜치 이름 변경 명령어

  • branch의 upstream 설정하기
$ git push -u origin 브랜치이름
  • 특정 브랜치에 대한 upstream 을 설정하며 push 한다.
    • 원격 깃 저장소의 브랜치와 로컬 깃 저장소의 브랜치가 연결된다.
  • 이후의 pushgit push 만 입력해도 된다.

  • 원격 브랜치 삭제하기
$ git push origin -d 삭제할 원격 브랜치이름

원격 브랜치를 삭제하면 로컬과 Github에서 브랜치를 볼 수 없게 된다.


원격 저장소에서 커밋들 가져오기

  • 원격 저장소의 브랜치 목록 확인하기
$ git branch -r

origin/원격 브랜치 이름 들을 확인할 수 있다.


  • 원격 저장소를 로컬로 가져오는 clone 을 하였더라도 main 브랜치를 제외한 다른 브랜치 정보는 로컬로 가져오지 않는다.

  • 따라서 원격 저장소의 다른 브랜치를 가져오고 싶다면 git switch 원격 브랜치 이름 을 사용한다.

    • origin/ 은 붙이지 않는다.

    • 이 경우 로컬에 새로 생성된 로컬 브랜치와 원격 브랜치는 자동으로 연결된다.

  • 원격 저장소의 변경사항들을 로컬 저장소로 가져오려면 fetch 를 사용한다.

    • 원격 저장소의 변경사항들을 working directory 에 적용시키는 것은 아니다.

    • 원격 저장소의 변경사항들을 로컬 저장소로 가져오면 origin/브랜치이름 의 커밋들에 checkout 할 수 있다.

  • git checkout origin/master 를 사용해 원격의 작업물을 볼 수 있다.
  • 이는 로컬에 존재하지 않는 브랜치로 이동하는 것이므로 detached HEAD 상태가 된다.

$ git fetch
  • git fetch origin 을 줄인 명령어
  • 만약 다른 이름의 원격 저장소에서 가져오고 싶다면 origin 대신 다른 이름을 사용한다.

  • 원격 저장소의 변경사항들을 working directory 로 가져오려면 pull 을 사용한다.

    • fetch + merge
$ git pull origin 가져올 브랜치 이름
  • 로컬의 현재 브랜치로 원격 저장소의 브랜치 커밋들을 가져온다.
  • 만약 로컬 브랜치와 원격 브랜치가 연결된 상태라면 git pull 만 사용해도 된다.

Git 작업 요약


Git 협업


Pull Requests

  • feature 브랜치를 main 브랜치에 merge 하기 위한 방법 중 하나이다.

  • PR을 보고 팀원들은 코드리뷰를 통해 merge 여부를 결정할 수 있다.

  • PR은 Github 에서 만들 수 있다.



  • PR merge 시 충돌이 발생할 수 있다.

    • 이 경우 Github에서 해결하거나 IDE로 가져와 해결할 수 있다.


  • Github 에서 충돌 해결하기
  • 충돌파일이 적은 경우 편하다.

로컬에서 충돌 해결하기

$ git switch main

$ git pull

$ git switch foo

$ git merge main
  • IDE 를 열어 충돌을 해결한다.
$ git add .

$ git commit

$ git push


Fork

  • push 권한이 없는 원격 리포지토리 (upstream) 에 PR을 날리고 싶을때 사용한다.

  • push 권한이 없는 리포지토리를 fork 하여 내가 작업할 수 있는 리포지토리 (origin) 를 내 계정에 만든다.

    • 내 계정에 생긴 원격 리포지토리를 로컬로 clone 하여 작업한다.

    • 내 계정에 생긴 원격 리포지토리 (origin) 의 작업들을 push 권한이 없는 원격 리포지토리 (upstream) 에 PR로 날릴 수 있다.

    • 오픈 소스 프로젝트와 같이 많은 사람들이 협력할 때 필요하다.


  • 로컬의 작업을 바탕으로 upstream 에 PR을 날리는 workflow

로컬의 작업을 origin 에 push


origin 의 변경사항을 upstream 에 PR



  • upstream 의 변경사항을 local 과 origin 에 적용시키는 workflow

upstream 의 변경사항을 local 로 pull


local 에 적용된 변경사항을 origin 으로 push


Git Rebase

  • 깃의 커밋기록들을 재작성하는 명령어

    • 같은 작업내용과 커밋메시지를 가지는 새로운 커밋들이 새로 만들어진다.

    • 커밋해시가 다르다.

  • 크게 2가지 용도로 사용된다.

    • merge 대신 사용

    • 커밋 기록들을 깔끔하게 정리하기 위해 사용


merge 대신 rebase

  • feature 브랜치의 베이스 (시작지점) 를 새로 설정한다.

  • 상단의 그림처럼 Feature 브랜치가 Master 브랜치의 변경사항을 적용하기 위해서 merge 를 여러번하게 되면
    • Feature 브랜치와는 상관없는 merge 커밋들이 지저분하게 섞인다.

  • rebase 를 사용하면 하단의 그림처럼 Master 브랜치의 끝 부분을 베이스로하는 Feature 브랜치를 새로 만든다.
    • Feature 브랜치와는 상관없는 merge 커밋들이 사라진다.

$ git switch feature

$ git rebase master

  • rebase 역시 충돌이 발생할 수 있다.

    • 충돌이 발생한 커밋에서 rebase 가 일시정지된다.

    • 충돌을 해결한 뒤 파일을 Staging Area 에 올리고 git rebase --continuerebase 를 재개한다.


커밋 기록들을 깔끔하게 정리하기 위한 Interactive Rebase

  • 현재 작업중인 브랜치의 커밋 이력들을 재구성하거나, 커밋 메시지를 편집할 수 있는 명령어
$ git rebase -i HEAD~n
  • HEAD로부터 n번째 이전의 커밋을 기준으로, 그 이후의 커밋들을 모두 편집한다.
    • 즉 n 번째 이전의 커밋이 base 커밋이 되고, 해당 커밋은 새로 만들어지지 않고 그대로 사용한다.


git rebase -i HEAD~9 명령어 입력시 열리는 에디터

  • 9 번째 전의 커밋인 initial commit 은 포함되지 않는다.
  • 아래에 있을수록 최신 커밋이다.
    • git log 와 반대순서

  • 특정 커밋의 커밋 메시지만 변경하기

  • pick: 해당 커밋을 그대로 사용한다.
  • reword: 해당 커밋의 내용은 유지하되 커밋 메시지만 변경한다.
  • 편집 내용을 저장하고 닫는다.

커밋 메시지를 변경하기 위한 에디터

  • 편집 내용을 저장하고 닫는다.

결과

  • 커밋 메시지가 변경되었음을 볼 수 있다.
  • 커밋해시가 이전과 전부 다른걸 확인할 수 있다.

  • 특정 커밋들을 하나로 합치기

    • 하나의 작업을 완료하고 커밋을 해버렸는데 빼먹은 작업이 있어 추가적인 커밋을 한 경우

    • 하나의 작업단위가 지저분하게 여러개의 커밋들로 표현된다.

    • 이 경우 추가적인 커밋들을 원래 작업 커밋 안으로 넣을 수 있다.

fixup: 해당 커밋 기록을 제거하고 커밋의 작업 내용을 과거 커밋과 합친다.


결과

  • fixup 한 커밋들은 기록에서 제거된다.

  • 특정 커밋 제거하기

    • 실수로 올린 잘못된 커밋을 제거할 수 있다.

    • 커밋 기록, 작업 내용 모두 제거한다.

drop: 해당 커밋을 제거한다.


결과

  • drop 한 커밋이 기록에서 제거된다.

rebase 주의점

  • rebase 를 하는 순간 기존에 작성된 커밋들은 같은 내용의 다른 커밋해시를 가진 새로운 커밋들로 대체된다.

  • 따라서 다른 사람들이 공유하고 있는 커밋 기록, 브랜치는 절대로 rebase 해서는 안된다.

    • 나의 로컬에만 있는 feature 브랜치를 rebase 하는 것은 괜찮다.

    • 다른 사람들의 로컬에도 있는 main 브랜치를 rebase 하는 것은 위험하다.


Git Tag

  • 특정 커밋에 붙이는 일종의 라벨

    • 브랜치 포인터는 커밋이 추가되면 추가된 끝부분을 가리키도록 이동한다.

    • 태그는 커밋의 추가여부와 상관없이 특정 커밋만을 가리킨다.

  • 주로 프로젝트 릴리즈 버전을 나타내는 용도로 사용된다.

  • lightweight tag와 annotated tag로 나뉜다.


Semantic Versioning

  • 소프트웨어의 버전 번호를 매기는 규칙

  • 태그에 많이 사용된다.

  • 의미있는 세가지의 숫자로 구성된다.

  • Patch Release
    • 작은 업데이트들을 의미하며 단순한 버그 수정이나 미미한 기능 추가시 숫자가 올라간다.

  • Minor Release
    • 새로운 기능이 추가되는 경우 숫자가 올라간다.
    • Minor Release 배포 시 Patch Release 번호는 항상 0으로 초기화해야 한다.

  • Major Release
    • 기능이 완전히 삭제되거나 대규모 기능 개편이 있는 경우 숫자가 올라간다.
    • Major Release 번호가 다른 경우 제대로 동작하지 않을 수 있다.
      • 하위 호환성이 보장되지 않는다.
      • Patch Release 번호나 Minor Release 번호는 다르더라도 잘 동작해야 한다.
    • Major Release 배포 시 Patch Release 번호와 Minor Release 번호는 항상 0으로 초기화해야 한다.

  • 일반적으로 최초 배포하는 릴리즈 버전은 1.0.0 이다.

tag 사용하기

  • 태그 목록 확인하기
$ git tag

git tag -l "정규식" 을 사용해 검색조건을 걸 수 있다.


  • 태그 커밋으로 이동하기
$ git checkout 태그이름

detached HEAD 상태가 된다.


  • 태그간의 작업내용 차이보기
$ git diff 태그1 태그2

  • lightweight tag 생성하기

    • 이름으로만 이루어지는 태그를 생성한다.
$ git tag 태그이름

현재 HEAD 가 가리키는 커밋에 태그를 만들어 붙인다.


  • annotated tag 생성하기

    • 작성자, 이메일, 날짜, 태그 메시지와 같은 메타 데이터를 담는 태그를 생성한다.
$ git tag -a 태그이름

현재 HEAD가 가리키는 커밋에 태그를 만들어 붙인다.


$ git show 태그이름

annotated tag 의 자세한 정보를 확인할 수 있다.


  • 태그의 위치 변경하기

    • 일반적으로 태그는 재사용할 수 없다.

    • 따라서 이미 사용한 태그명을 다시 사용할 수 없다.

    • 이를 이용하여 태그의 위치를 변경할 수 있다.

$ git tag -f 이동시킬 태그이름

이미 존재하는 태그를 옮기고 싶은 위치에서 강제로 다시 붙이면 이전 위치의 태그는 삭제된다.


  • 태그 삭제하기
$ git tag -d 태그이름

  • 태그 push 하기

    • 태그가 붙은 커밋이 원격으로 push 되어도 태그는 push 되지 않는다.

    • 따라서 태그는 따로 push 해야 한다.

$ git push --tags

모든 태그를 원격으로 push


$ git push origin 태그이름

특정 태그만 원격으로 push


Git Reflog


Reflog

  • Git에서 관리하는 HEAD의 참조 로그이다.

    • HEAD 가 가리키는 곳이 바뀔때마다 reflog에 기록된다.

    • 어떤 명령어를 사용해서, 어떤 브랜치나 커밋에서 어떤 브랜치나 커밋으로 이동하였는지 기록한다.

  • 지역적인 기록으로 나의 로컬에서의 참조 기록들만 저장된다.

  • 오랜시간 참조되지 않은 기록들은 제거된다.

$ git reflog
  • git reflog show HEAD 를 줄인 명령어
  • 만약 특정 브랜치의 reflog 만 보고싶다면 git reflog show 브랜치이름 을 사용한다.

  • 시간 기반 한정자 사용하기

    • 특정 시간 전의 reflog 를 확인할 수 있다.
$ git reflog show HEAD@{2.days.ago}

2일전까지의 모든 reflog 확인


$ git reflog show HEAD@{yesterday}

어제까지의 모든 reflog 확인


$ git reflog show HEAD@{one.minute.ago}

1분전까지의 모든 reflog 확인


사라진 커밋 복구하기

  • reset 이나 rebase 등으로 커밋 기록을 변경하는 작업은 실제로 커밋을 제거하지 않는다.

    • 커밋은 그대로 있지만 브랜치가 해당 커밋의 참조를 잃을 뿐이다.
  • 따라서 커밋 기록을 복구하고 싶을 때 reflog 를 뒤져 커밋해시를 찾아 복구하고 싶은 시점의 커밋에 checkout 할 수 있다. (detached HEAD 상태)

    • 해당 커밋에서 hard reset 을 하거나 branch를 붙여주어 원하는 상태로 복구할 수 있다.


실수로 feat 브랜치를 삭제하여 feat 브랜치 관련 커밋기록들을 잃어버렸다.


reflog 를 뒤져 feat 브랜치 포인터가 가리키던 커밋을 찾아내 checkout 한다.


브랜치를 생성한 뒤 feat 브랜치로 switch 하여 feat 브랜치를 복구한다.



rebase 를 잘못하여 되돌리고 싶은 상황이라면


feat 브랜치의 reflog 를 뒤져 돌아가고 싶은 커밋해시값을 찾는다.


feat 브랜치에서 git reset --hard 돌아가고 싶은 커밋해시 명령어를 사용하여 rebase 이전으로 복구할 수 있다.


Git Alias

  • 각각의 깃 저장소에 적용되는 지역 설정 파일은 .git/config 이다.

  • 로컬의 모든 깃 저장소에 적용되는 전역 설정파일은 ~/.gitconfig 이다.

  • git config --global A.aa 는 전역 설정 파일의 A 항목에 aa 필드의 값을 반환한다.
  • git config --global A.aa 넣고싶은값 은 전역 설정 파일의 A 항목에 aa 필드의 값을 넣고싶은값으로 변경한다.

  • Git Alias 는 사용자설정 깃 단축키이다.

    • 전역 설정파일의 alias 항목에 단축키와 수행할 깃 명령어들을 적는다.

    • 내가 설정한 git hist alias 설정 방법은 다음과 같다.

$ git config --global alias.hist "log --graph --all --pretty=format:'%C(yellow)[%ad]%C(reset) %C(green)[%h]%C(reset) | %C(white)%s %C(bold red){{%an}}%C(reset) %C(blue)%d%C(reset)' --date=short"

이를 통해 로그를 이쁘게 볼 수 있다.


Git 동작 원리


.git 디렉토리

  • git init 을 하면 만들어지는 디렉토리로 깃이 저장하고 조작하는 대부분의 것들이 존재한다.

  • config 파일
    • 해당 깃 저장소에만 적용되는 지역 설정 파일


  • refs 디렉토리
    • 브랜치 포인터나 태그와 같은 참조 (포인터) 값이 저장된다.
    • 포인터 파일은 커밋 해시값을 갖는다.


  • HEAD 파일
    • 현재 HEAD가 가리키는 브랜치나 특정 커밋해시값 (detached HEAD 상태의 경우) 을 갖는다.


  • objects 디렉토리
    • Git 객체 4가지를 저장한다.
      • commit
      • blob
      • tree
      • annotated tag

Key-Value data store

  • 깃은 해시값을 key로 사용한다.

  • key 에 대응되는 value는 깃 객체들이다.

  • objects 디렉토리 내부에 해시값의 앞 두글자를 따 디렉토리를 만들고 그 안에 나머지 해시값을 이름으로 하는 깃 객체를 만든다.

git cat-file -p 해시값 을 통해 해당 객체가 커밋 객체임을 확인할 수 있다.


  • blob 은 파일 내용을 저장하는 객체이다.

    • 파일 이름은 갖고있지 않다.

      • 파일 이름은 tree 가 관리한다.
    • 파일의 변경사항이 있는 경우에만 새로운 blob 객체가 만들어진다.


  • tree 는 파일들의 관계, 디렉토리 내용을 저장하는 객체이다.

    • blobtree 를 가리키는 포인터들을 가지고 있다.

blob 해쉬값은 commit 해쉬값과는 다르다.


git cat-file -p 해시값 결과


  • committree, 부모 commit 해시, 작성자와 커밋 메시지를 저장하는 객체이다.

    • 특정 커밋으로 이동하면 commit 객체가 가리키는 tree 객체를 바탕으로 working directory 를 재구성한다.


출처

Udemy 【한글자막】 Git & Github 실무 활용 완벽 가이드 강의 (Colt Steele 강사님)
https://www.udemy.com/course/best-git-github/?kw=git+github&src=sac

0개의 댓글