Critical

  • 커밋 체크아웃
  • 분리된 HEAD

 

Important

  • 변경사항 무시하기
  • git restore(복원)/reset(재설정)/revert(되돌리기)

 

git checkout 명령어로 브랜치를 생성하거나 이동하는것 말고도 이전 커밋을 확인할 수도 있다.

 

git checkout <commit-hash>

HEAD를 해당 커밋으로 이동시킨다. 명령어 실행 시 HEAD가 분리된 상태라는 메시지가 출력된다.

브랜치는 언제나 해당 브랜치의 최근 커밋을 가리키고 HEAD는 그 브랜치를 가리키게 된다. 일반적으로 HEAD는 커밋이 아닌 특정 브랜치를 참조하게 된다.

하지만 해당 명령어를 통해서 HEAD가 특정 커밋을 참조하도록 바꾼다. 원래 브랜치를 참조하던것이 커밋을 참조하게 되었으므로 분리된 상태가 된 것이다.

이를 통해 이전 커밋을 참조할 수 있다.

다시 브랜치로 돌아가려면 switch 명령어로 돌아가면 된다. "git switch -" 입력 시 현재 브랜치의 최상단으로 이동한다.

 

정상적인 상태
HEAD가 분리된 상태

HEAD가 분리된 상태에서도 브랜치를 새로 생성시킬 수 있다.

 

과거의 커밋으로 돌아가서 프로토타입 작성 등의 새로운 작업을 시작할 때 매우 유용하게 사용할 수 있을 것 같다.

 

 

git checkout HEAD <file-name>

커밋 참조를 이용해서 작업 영역의 변경 사항을 한번에 초기화 하는 방법이다.

무언가 열심히 작업을 하다가 문제가 생기거나 마음에 안들어서 초기화 할때 사용하면 된다.

파일 이름을 적어주면 해당 파일만 마지막 커밋 내용으로 덮어씌워진다.

HEAD 대신 -- 을 입력해도 된다.

 

 

git restore

 

git restore 명령어의 두 가지 목적

  • 작업 영역의 변경사항 되돌리기
  • 언스테이징

 

checkout이 너무 많은 기능을 수행하기 때문에 독립시켜 만든 명령어이다.

git checkout HEAD <file-name> == git restore <file-name> 이다.

git restore --source <commit-hash> <file-name> : 특정 커밋의 파일로 변경한다.

git restore --staged <file-name> : 스테이지에 등록된 파일을 다시 작업 영역으로 되돌린다.

git restore 명령어는 git status에서 사용법을 알려주기도 한다.

 

 

 

git reset

저장소를 특정 커밋으로 재설정한다.

일반 재설정과 하드 재설정이 존재한다.

 

일반 재설정 / git reset <commit-hash>

커밋 삭제 전
커밋 삭제 후

위와 같이 잘못된 커밋이 존재할 경우 해당 명령어로 커밋만 삭제할 수 있다.

"커밋만" 삭제한다는 점을 주의해야한다. 변경된 사항은 여전히 작업 영역에 남아있다.

HEAD부터 <commit-hash> 직전까지의 범위를 모두 삭제한다.

 

커밋된 작업이 작업 영역으로 돌아왔다

잘못된 브랜치에서 커밋을 했을 때 유용하게 사용할 수 있다.

커밋을 삭제하고 남아있는 변경사항을 정상적인 브랜치에서 다시 커밋을 하면 된다.

 

 

하드 재설정 / git reset --hard <commit-hash>

--hard 플래그 하나가 추가된 형태이다. 커밋을 삭제하는것은 동일하지만 작업의 변경사항까지 모두 삭제한다.

일반 재설정 이후 restore로 작업 영역의 변경사항을 취소한것과 마찬가지이다.

 

reset은 브랜치 기준으로 작동한다.

 

 

git revert <commit-hash>

reset과 기능이 매우 유사하다. reset은 커밋을 제거하고 브랜치 포인터를 뒤로 이동시키는 반면에 revert는 새로운 커밋을 만들어서 이전 커밋의 변경 사항을 취소한다.

결과적으로 커밋을 취소(되돌리는것)하는것은 동일하지만 커밋을 삭제하느냐 남겨두느냐의 차이가 있다.

병합 커밋을 실행할때처럼 명령어 실행 시 충돌을 처리해야 할 수도 있다.

 

reset과 다르게 커밋이 삭제되지 않고 남아있다

revert를 사용하는 이유는 협업 때문이다.

설령 잘못된 커밋이더라도 다른 사람들이 작업하고 있는 커밋이라면 reset으로 커밋을 제거했을 때, 다른 사람들이 가지고 있는 기록을 취소하는 것이기 때문에 심각한 문제가 발생될 수 있다.

커밋 실수를 했을 때 다른 사람들과 공유되지 않았다는 것이 확실할때는 reset을 사용하는 것이 좋고 다른 사람들과 공유중인것이 확인됐을 때는 revert를 사용해야 한다.

 

HEAD를 기준으로 이전 커밋들을 참조할 수도 있다.

HEAD~[N] 으로 HEAD 기준으로 N개 이전 커밋을 참조한다.

 

요약

  • git restore : 작업 영역의 수정 사항이나 스테이징을 취소한다.
  • git reset : 커밋을 취소한다. (커밋 삭제)
  • git revert : 커밋을 복구한다. (새로운 커밋 생성)

 

reset과 revert는 결과는 동일하지만 과정이 다르다.

Important

  • 스태시의 기초
  • git status save/pop

 

Nice To Have

  • git stash 적용
  • 스태시 삭제
  • 여러개의 스태시로 작업하기

 

스태시는 유용한 기능이지만 반드시 사용해야 하는 상황은 발생하지 않는다.

대부분 save와 pop을 사용한다.

 

브랜치에서 작업을 하다가 완료되지 않은 상태라서 커밋을 하지 않고 다른 브랜치로 이동해야 하는 경우에는 상황에 따라 해당 작업이 이동하는 브랜치로 따라오거나 깃에서 브랜치를 이동하지 못하도록 막는(병합 커밋 발생 예상시) 두가지 옵션이 존재한다.

이 때 스태시를 사용한다.

 

 

git stash (=git stash save)

커밋되지 않은 변경사항을 저장하고 변경사항들을 모두 초기화시킨다.

내용이 삭제되는것이 아니라 스태시에 저장된 상태이다.

 

 

git stash pop

스태시에 저장된 가장 최근 목록을 가져오고 삭제한다.

 

 

git stash apply

방식은 pop과 동일하다. 단, 스태시가 삭제되지 않고 남기때문에 여러 브랜치에서 동일한 내용을 적용할 수 있다.

 

 

git stash list

스태시는 여러개 등록이 가능하다.

 

한 브랜치에서 여러번의 스태시는 흔한 일은 아니다

스태시 아이디를 통해서 특정 스태시를 적용시킬 수 있다.

 

스태시를 적용하고 바로 다른 스태시를 적용하려고 하면 위와 같이 에러가 발생한다.

작업 내용이 덮어씌워지기 때문에 에러가 발생하고 병합 되기전에 커밋이나 스태시를 하라고 한다.

 

 

git stash drop

특정 스태시를 삭제시킬 수 있다.

 

 

git stash clear

모든 스태시를 삭제한다.

Critical

  • git diff 명령어 실행 결과 읽기
  • git diff 명령어의 기본적인 사용 방법

 

Important

  • 브랜치, 커밋, 특정 파일의 비교
  • git diff --stage

 

git diff는 깃에서의 변경 사항들을 보여주는 명령어이다.

git status나 git log처럼 저장소에 아무런 영향을 미치지 않는 명령어이다.

 

git diff

스테이지에 등록되지 않은 작업 영역의 변경사항을 모두 나열한다.

 

아직 스테이지에 올라가지 않은 상태
작업 영역 파일의 변경사항을 알려준다
각 라인을 해석하면 위와 같다

a는 커밋된 파일, b는 작업 영역의 파일이다.

 

 

git diff HEAD

마지막 커밋이 실행된 이후의 변경사항을 모두 나열한다.

마지막 커밋 이후 변경 사항을 스테이지에 올리지 않은 상태라면 git diff, git diff HEAD 둘다 같은 결과를 출력한다.

하지만 변경 사항을 스테이지에 올린다면 git diff는 아무것도 출력되지 않지만 git diff HEAD는 결과가 출력된다.

 

 

git diff --staged (--cached)

스테이지에 등록된 변경사항만을 나열한다.

 

 

git diff branch1 branch2 (branch1..branch2)

두 브랜치를 비교하여 변경사항을 모두 나열한다.

a, b는 브랜치 입력 순서에 따라 매칭된다. 위와 같은 경우는 a는 branch1, b는 branch2이다.

 

 

git diff commit1 commit2 (commit1..commit2)

두 커밋을 비교하여 변경사항을 모두 나열한다.

마찬가지로 a, b는 커밋 입력 순서에 따라 매칭된다.

* HEAD는 단순히 마지막 커밋을 가리키는 레퍼런스이다. 그래서 git diff HEAD HEAD~1 실행시 마지막 커밋과 그 부모커밋을 비교하는 명령어가 된다.

 

git log --oneline
커밋 해시값을 입력한다

 

git diff <file-name1> <file-name2> <..>
git diff --staged <file-name>
git diff HEAD <file-name>
git diff branch1..branch2 <file-name>
git diff commit1..commit2 <file-name>

 

위와 같이 특정 파일에 대한 변경사항만 확인할 수도 있다. 동시에 여러 개의 파일도 가능하다.

 

-, +를 b에 비교해서 없는 내용, 있는 내용으로 구분지어서 생각하기 보다는 -는 a에만 있는 내용, +는 b에만 있는 내용이라고 생각하는게 이해하기 조금 더 쉽다.

 

 

GUI 툴을 사용하면 매번 상황에 따라 명령어를 작성하던것을 원클릭으로 볼 수 있어서 훨씬 편하다.

Critical

  • Fast-Forward(빨리 감기) 병합
  • git merge & merge commits
  • 병합 충돌과 해결 방법

 

Nice To Have

  • VS Code 사용을 통한 충돌 해결 방법

 

병합의 2가지 원칙

  • 특정 커밋이 아닌 브랜치를 병합한다.
  • 항상 현재 HEAD 브랜치에 병합한다.

 

* Fast-Forward(빨리 감기) 병합

  1. 목적지(병합하려는) 브랜치로 이동한다. (B를 A에 합치고 싶다면 A로 이동)
  2. git merge B 실행
  3. A의 브랜치가 B의 브랜치를 따라잡게 된다.

 

병합을 하더라도 병합 대상의 내용들이 브랜치에 추가되는 것은 한 순간이고 동기화가 계속 이뤄지는것은 아니다. 여전히 별개의 브랜치로 존재한다.

 

그리고 모든 병합이 빨리 감기 병합은 아니다.

예를 들어 main에서 브랜치를 새로 만들어서 작업 후 main 브랜치에 병합하려고 하는데 그 사이 다른 팀원들에 의해 main 브랜치에서 커밋이 이뤄졌다면 현재 나의 브랜치에는 없는 새로운 정보들이 main 브랜치에 존재하게 된다.

이 때 병합을 하게되면 빨리 감기 병합이 아닌 merge commit(병합 커밋)이 이뤄지고 해당 커밋은 2개의 부모를 가지게 된다.

 

main브랜치의 커밋이 늘어난 상태

 

merge commit이 일어났다

 

위와 같은 병합 커밋은 서로 다른 파일로 작업을 진행했기 때문에 충돌 없이 자동으로 병합이 이뤄진다.

병합하려는 브랜치의 파일이 삭제되거나 동일한 파일을 수정해서 충돌이 발생하는 경우 깃은 충돌이 발생한 파일을 알려주게 된다.

이 때 충돌이 발생한 파일을 열어서 직접 해결하면 된다.

대부분의 경우 병합 커밋이 완료되면 병합 대상의 브랜치는 더 이상 필요 없으므로 삭제하는 편이다.

 

* 병합 충돌이 발생한 경우

  1. 충돌이 발생한 파일 열기
  2. 파일 수정
  3. 충돌 표시 제거
  4. 커밋

 

 

상단의 Accept~~를 이용한다

VS Code를 이용하면 병합 커밋을 조금 더 편하게 할 수 있다.

상단의 Accept 메뉴를 클릭하면 한쪽 내용만을 적용하거나 양쪽 다 적용하는 등 단순 작업을 더 편하게 할 수 있다.

Critical

  • 브랜치는 무엇이고 왜 사용하는가?
  • HEAD에 대한 이해
  • 명령어 git branch/switch/checkout

 

Important

  • 브랜치 삭제와 이름 변경
  • 브랜치 이름 (master vs main)

 

Nice To Have

  • HEAD & Refs behind the scenes

 

브랜치도 커밋처럼 매일 또는 자주 다루게 될 것이다.

 

커밋은 고유의 해시를 가지고 부모 커밋 하나를 참조하고 있다.

 

어떤 팀에서 각각 진행하는 작업의 내용이 진척도가 서로 다르고 작업 내용이 추후 적용된다고 했을 때, 순차적인 커밋은 불가능하다고 볼 수 있다.

이 때, 브랜치로 작업을 분기시켜서 별도로 진행하다가 추후 합칠 수 있다.

 

작업은 항상 브랜치 위에 존재한다.

 

master(main) 브랜치는 실제로 특별한것은 없지만 많은 팀과 사람들이 프로젝트 코드 베이스의 원본처럼 취급한다.

 

어떤 브랜치에서 작업한 내용은 다른 브랜치에 영향을 미치지 않는다.

 

 

HEAD

 

브랜치 생성에 앞서 알아야 할 개념.

각 브랜치는 브랜치 레퍼런스를 가지고 있으며 HEAD는 이 브랜치 레퍼런스를 가리키면서 전환하게 된다. 일종의 포인터이다.

 

git branch

저장소에 존재하는 브랜치 목록을 보여준다.

-d, --delete : 브랜치를 삭제한다. checkout했거나 현재 보고있는 브랜치는 삭제가 안되므로 다른 브랜치로 이동해서 삭제해야 한다.

-m, --move : 브랜치의 이름을 재설정한다. 이름을 변경하려는 브랜치로 이동해야 한다.

 

git branch <branch-name>

HEAD가 현재 가리키는 브랜치에 새 브랜치를 생성한다.

 

git switch

브랜치 간에 이동을 한다. (HEAD가 가리키는 레퍼런스 전환)

-c : 브랜치 생성과 이동을 동시에 한다.

 

git checkout

브랜치 간에 이동하거나 작업 트리를 복구시키기 위해 사용된다.

# 둘은 서로 동일하다
git switch -c main
git checkout -b main

 

* 스테이징 되지 않은 변경사항으로 브랜치 전환

커밋되지 않은 내용이 있는 상태에서 브랜치 변경시 내용이 사라진다. 그렇기 때문에 변경 시도시 커밋하거나 임시로 백업(스태시) 하라고 알려준다.

가급적 변경사항을 만들 때마다 브랜치 이동 전에 항상 커밋할 것을 권장한다.

 

+ Recent posts