현재 HEAD는 -> premium 로컬브랜치, origin/premium 원격브랜치를 가리키고 있다.

 

브랜치는 코드를 관리하는 하나의 흐름

즉, 어떤 커밋을 가리키는 존재-> 포인터라고 할 수 있는데,

커밋을 할 때 마다 브랜치는 가장 최근의 커밋을 가리키게 된다.

물론 커밋을 계속 추적해왔기 때문에 과거의 커밋을 가리켜서 변경사항을 확인 할 수도 있다.

그래서 브랜치가 '코드 관리 흐름' 이라는 개념이 성립할 수 있는거!

 

 

그렇다면 헤드(HEAD)는?

어떤 커밋을 가리키는 존재->포인터 란 개념 확장으로

헤드가 가리키는 커밋의 내용대로 working directory의 내용물이 바뀐다는 특징이 있지만

 

사실 헤드는 커밋을 직접 가리키지는 않는다. 커밋은 브랜치를 통해 간접적으로 커밋을 가리킨다.

여기서 premiup 브랜치를 만들면?

아래와 같은 그림이 되고 $git checkout premium을 해야만 

HEAD는 이제 premium 브랜치를 향하게 된다.

 

다시 main 브랜치로 checkout을 하게 되면

HEAD는 메인 브랜치를 향하게 되고

헤드가 가리키는 커밋의 내용대로 working directory의 내용물이 바뀐다.

이를 '분기한다' 라고 한다.

여기서 merge를 하게 되면? ($git merge premium)

즉 HEAD가 main브랜치를 가리킨 상태에서 premium브랜치를 merge하게 되면?

main브랜치의 커밋내용에 premium브랜치가 가리키던 커밋내용이 합쳐져서

새로운 커밋내용이 만들어지게 된다.

이를 merge커밋이라고 한다.

즉, 머지커밋은 헤드가 가리키던 커밋에 다른 브랜치가 가치리던 커밋을 합쳐서

새로운 커밋을 만드는 작업이다.

 

결국 git을 사용한 협업이라는 것은 이렇게 완성된다.

 

 

 

++git reset 커맨드의 동작 원리

더보기

1. git reset을 할 때 HEAD의 변화는?

지금 총 4개의 커밋을 한 아래와 같은 상황이라고 가정합시다.

현재 각 박스 안에 있는 텍스트는 각 커밋의 커밋 아이디 앞 부분입니다.

이 상태에서

git reset [--hard 또는 --soft 또는 --mixed] 9033

을 실행한다면 어떻게 될까요? 이전에 git reset을 배울 때를 떠올려보면 HEAD가 9033.. 커밋을 가리키게 되겠죠? 그럼 정확히 어떤 모습으로 가리키게 되는 건지 보여드리겠습니다. 어떤 옵션을 쓰든 아래 그림과 같은 결과가 됩니다.

지금 HEAD는 여전히 master 브랜치를 가리킵니다. 대신 master 브랜치가 가리키던 커밋이 바뀌었네요. 그래서 결과적으로 HEAD가 9033.. 커밋을 가리키게 된 겁니다.

방금 발생한 일을 정리하면 다음과 같습니다. git reset 커맨드를 사용하면

  1. HEAD는 여전히 같은 브랜치를 가리키고, 
  2. HEAD가 가리키는 브랜치가 다른 특정 커밋을 가리키게 됩니다.
  3. 이 때문에 결국 HEAD가 간접적으로 가리키던 커밋도 바뀌게 되는 겁니다.

git reset을 했을 때 HEAD가 가리키던 커밋이 바뀐다는 말이 정확히 무슨 뜻인지, 이제 아시겠죠? 바로 이런 원리가 있었던 겁니다. 그리고 이전에 배운대로 각 옵션(--soft/--mixed/--hard)에 따라 과거의 커밋처럼 working directory나 staging area도 리셋되는지가 결정되는 거구요.

하지만 한 가지 더 알아야할 git reset의 비밀이 있는데요.

2. git reset을 한다고 그 이후의 커밋이 사라지는 건 아닙니다.

git reset을 한다고 하면 그 이후의 커밋이 삭제되는 것으로 착각하기 쉽습니다. 그러니까 위 상황에서 네 번째 커밋인 43kf.. 커밋이 사라진다고 오해하실 수도 있는데요. 전혀 그렇지 않습니다. 43kf.. 커밋은 계속 남아있습니다.

그리고 git reset은 꼭 과거의 커밋으로만 할 수 있는 것도 아닙니다. 현재 HEAD가 가리키고 있는 커밋 이후의 커밋으로도 리셋할 수 있죠.

  • 지금처럼 HEAD가 3번째 커밋인 9033.. 커밋을 가리키고 있는 상태에서 
git reset 43kf

를 실행하면 master 브랜치가 다시 43kf.. 커밋을 가리키게 됩니다. 아래 그림처럼요.

그러니까 git reset에 관해서 분명하게 아셔야할 게

  1. 과거의 커밋으로 git reset을 한다고 그 이후의 커밋들이 삭제되는 게 절대 아닙니다. 계속 남아있습니다. 
  2. git reset은 과거의 커밋뿐만 아니라 현재 HEAD가 가리키는 커밋 이후의 커밋으로도 할 수 있습니다. 

이 사실을 확실히 알고 나면 앞으로 git reset을 사용해서 커밋 사이를 자유자재로 이동할 수 있을 겁니다.

 

++git reset 과 git checkout 의 차이점

더보기

1. 이전 노트의 내용(git reset) 복습

이전 노트에서는 아래 그림과 같은 상태에서

git reset 9033

를 실행하면 

이 그림과 같은 결과가 된다고 했습니다. 이렇게 HEAD는 보통 본인이 직접 커밋을 가리키는 게 아니라 브랜치를 통해서 간접적으로 커밋을 가리킵니다.

2. git checkout이 하는 일

하지만 HEAD 자체가 가리키던 것을 바꿀 수도 있습니다. 사실 HEAD가 아예 커밋을 직접적으로 가리키게 하는 것도 가능한데요.

바로 git checkout 커맨드를 쓰면 됩니다.

원래의 이 상태에서

git checkout 9033

를 실행하면 아래 그림처럼 바뀝니다. 

이 그림을 자세히 보세요. 이제 HEAD가 master 브랜치를 가리키는 게 아니라 본인이 직접 9033.. 커밋을 가리키고 있죠?

이렇게 브랜치를 통해서 커밋을 가리키는 게 아니라 본인이 직접 커밋을 가리키고 있는 상태의 HEAD를 특별히 가리키는 말이 있습니다.

바로 Detached HEAD입니다. Detached는 우리말로 ‘~로부터 떨어진, 분리된’이라는 뜻을 갖는데요. 브랜치로부터 떨어진 상태이기 때문에 이렇게 부르는 겁니다. 

이렇게 HEAD가 특정 커밋을 직접 가리키게 하는 이유는 여러가지가 있을 수 있는데요.

그 중에서 주된 이유 한 가지는 바로 과거의 특정 커밋에서 새로운 브랜치를 만들고 싶을 때입니다. 

예를 들어 지금 위의 그림과 같이 Detached HEAD인 상태에서

git branch premium

으로 premium 브랜치를 새로 만들면 아래 그림과 같은 결과가 됩니다. 

  1. 지금 premium이라는 브랜치가 새로 생성되었고
  2. premium 브랜치는 HEAD가 가리키던 커밋을 똑같이 가리키게 됩니다. 

자, 그리고 여기서 새로운 사실을 하나 알려드릴게요.

git checkout 커맨드로는

  • HEAD가 커밋을 직접적으로 가리키게 할 수도 있을 뿐만 아니라
  • 브랜치를 직접 가리키게 만들 수도 있습니다.

HEAD가 브랜치를 가리키도록 해볼게요. 이렇게 쓰면

git checkout premium

HEAD가 premium 브랜치를 가리키게 됩니다.

그러니까 아래 그림과 같이 이제 HEAD가 premium 브랜치를 가리키게 되는 겁니다. 그리고 이것은 곧 Detached HEAD 상태에서 벗어나 HEAD가 브랜치를 가리키는 정상적인 상태로 돌아오는 거죠.

그리고 이렇게 HEAD가 premium 브랜치를 가리키는 상태일 때 새 커밋을 하면

이제 premium 브랜치로 master 브랜치와 다른 새로운 코드 관리 흐름을 가져갈 수 있게 되는 겁니다.

방금 한 것처럼 특정 커밋을 시작점으로 하는 새로운 브랜치를 만들고 싶을 때 HEAD를 잠시 Detached HEAD 상태로 두는 경우가 많습니다.

이 내용을 정리하면

  • git checkout 커맨드로는 HEAD가 직접적으로 가리키는 것을 바꿀 수 있고
  • git checkout 뒤에는 커밋 아이디 또는 브랜치의 이름을 줘서
  • HEAD가 직접 커밋을 가리키거나, 브랜치를 가리키도록 할 수 있다는 뜻입니다.

그런데 사실 git checkout 뒤에 브랜치의 이름이 오는 경우는 이미 우리가 배웠습니다. 우리가 어떤 브랜치로 가고 싶을 때

git checkout [가고 싶은 브랜치 이름]

형식의 커맨드를 쓴다고 배웠죠?

이제 이 커맨드가 좀 새로운 시각에서 느껴지지 않나요? 자, 그림으로 바로 보여드릴게요.

지금 위 그림과 같은 상태에서

git checkout master 

를 실행하면

이렇게 HEAD가 master 브랜치를 가리키게 됩니다. 바로 이게 우리가 이전에 git checkout 커맨드를 사용해서 다른 브랜치로 이동할 때 벌어지는 일이었던 겁니다.

이렇게

  • HEAD가 다른 브랜치가 가리키던 커밋을 가리키게 되면
  • 그에 맞게 working directory 내부도 바뀌게 되고,
  • 그 결과 우리는 브랜치가 변경되었다는 걸 실감할 수 있었던 겁니다.

이해하기 쉽게 다시 한번 풀어서 말하자면

git checkout master

이 커맨드의 뜻은 다음과 같이 해석됩니다.

= master 브랜치로 이동하라

= HEAD가 master 브랜치를 가리키도록 하라

= HEAD가 master 브랜치가 가리키던 커밋을 간접적으로 가리키게 됨으로써

= working directory의 내부도 그 커밋에 맞게 변함으로써

= master 브랜치로 이동한 것을 사용자는 실감하게 됨

이렇게 되는 거죠.

자, git checkout의 비밀을 이제 알겠죠?

'EDU > codeIt' 카테고리의 다른 글

깃 blame  (0) 2021.10.10
git push와 git pull, merge, fetch  (0) 2021.10.09
깃 브랜치 push  (0) 2021.10.09
깃 브랜치 merge CONFLICT!  (0) 2021.10.09
깃 브랜치 기초(생성, 삭제, 체크아웃, merge), 심화 링크  (0) 2021.10.09

+ Recent posts