이전 포스트를 작성하면서 궁금한 점이 생겨서 곧바로 찾아보았다.
원격 브랜치를 업데이트하는 방법에 다룬 포스트인데, 참고한 스택오버플로우 답변글에서는 원격 저장소 브랜치를 찾지 못할 때,
git remote update
git fetch
git checkout --track origin/<BRANCH-NAME>
위의 순서로 명령어를 입력하면 해결된다고 나와있다.
일단 저렇게 하면 해결되긴 하는데, git remote update와 git fetch의 차이가 뭔지 궁금해져서 찾아보았다.
한글로 작성된 개발 블로그에서는 하나같이 git remote update와 git fetch의 차이를 이렇게 설명한다.
git remote update는 모든 원격 브랜치를 업데이트하지만, git fetch는 "현재 위치하고 있는 원격 브랜치만" 업데이트 한다고.
출처가 어딘지 궁금해져서 찾아보니, 아래 스택오버플로우 글이 출처인 듯 하다.
하지만 답변글의 달린 댓글들을 보면, git fetch가 현재 위치한 브랜치만 업데이트한다는 설명이 잘못돼었다고 한다.
이미지 속 참고 링크 와 깃 메뉴얼 을 찾아본 후, 실제로 테스트를 해보았다.
직접 테스트를 해보니 모호했던 부분을 좀 더 정확히 이해할 수 있었다.
1. git fetch 명령어는 흔히 알려진 것처럼, "현재 위치하고 있는 원격 브랜치만 업데이트" 한다는 것은 확실히 틀렸다. 모든 remote tracking branch를 다 업데이트한다.
정확히 말하면, 현재 로컬에서 위치한 브랜치(tracking branch)가 참조하는 remote tracking branch가 속해있는 원격 저장소 내의 모든 브랜치 정보를 업데이트한다.
2. git fetch에 --all 옵션을 주면, 모든 원격 저장소의 모든 remote tracking branch를 업데이트한다.
git fetch --all 은 git remote update와 같은 역할을 수행한다고 볼 수 있다.
예를 들어, github의 프로젝트 A를 clone 받았다고 하자. 그러면 git은 자동으로 이 원격 저장소의 이름을 origin이라고 지정한다. 그러나 원격 저장소는 여러 개를 가질 수 있다. github이 마음에 들지 않아, gitlab의 저장소를 쓰려고 git remote add gitlab <git-url> 명령어를 통해 새로운 원격 저장소 gitlab을 추가했다. 이제 원격 저장소는 origin과 gitlab 두 개를 가진다.
그 후, 로컬 저장소의 커서를 gitlab/master로 옮겨서 작업하다가 새 브랜치를 생성할 필요성이 생겨, gitlab홈페이지에서 dev 브랜치(remote branch)를 생성했다.
곧바로 로컬 터미널에서 git checkout dev를 치면 dev라는 remote branch의 remote tracking branch를 찾을 수 없어서 에러가 뜬다. 이때, git fetch를 입력하면 dev라는 remote branch의 remote tracking branch를 만들고 그 정보를 업데이트시킨다.
이제 git checkout dev를 입력하면, dev라는 이름의 remote tracking branch를 가져오고, 이를 참조(추적)하는 tracking branch를 만들고 위치시킨다.
(이때, 만약 origin과 gitlab에 각각 dev라는 브랜치명이 중복되어 있을 시, git checkout --track origin/<name> 라는 형식으로 저장소 이름을 명시하라고 hint 메세지를 띄워준다.)
이 시점에서, upstream 저장소는 gitlab인 상태이다. 여기서 아까처럼 다시 github 홈페이지에서 production 브랜치를 생성하고 똑같이 git fetch를 하고 checkout하려고 하면 제대로 fetch가 되지 않아서 에러가 날 것이다. 바로 저장소가 다르기 때문에 git fetch를 입력했을 때 gitlab의 변경내용만 업데이트 했기 떄문이다. 이럴 땐, git fetch --all 또는, git remote update로 전체 원격저장소의 변경사항을 업데이트 해줘야한다.
이같은 오해는, remote branch와 remote tracking branch, 그리고 tracking branch를 혼동해서 생긴 결과인 것 같다. 잘못된 답변을 다시 번역하면서 원격브랜치, 로컬 브랜치 등으로 용어가 제대로 정리되지 않아서 더욱 혼동이 생긴 것 같다. 참고 링크
Remote branch는 원격저장소의 브랜치이다. github, gitlab같은 다른 원격 저장소에 존재하는 브랜치를 뜻한다.
Remote Tracking branch는 origin/master 와 같은 원격저장소의 브랜치를 참조하는 브랜치를 말한다. 원격 브랜치의 복사본 같은 개념이다. 로컬 저장소에 위치한다.
Tracking branch는 로컬 브랜치 중에서 리모트 브랜치를 Tracking(추적)하는 브랜치이다.
그러니까, 우리가
git checkout <목적지 commit hash>
로 브랜치 내 특정 커밋을 가르키도록 조작할 떄, 우리는 로컬의 Tracking 브랜치를 수정하는 것이다.
Remote Tracking branch와 Tracking branch에 대한 자세한 내용은 새로운 포스트로 정리하겠다.
돌고돌아 포스트 제목과 일치하는 내용만 요약하자면,
1. git remote update : 등록된 모든 원격 저장소의 정보를 최신 상태로 업데이트 한다.
2. git fetch : 현재 위치한 브랜치를 부모로 가지는 원격저장소의 정보만 업데이트 한다. --all 옵션으로 모든 원격 저장소를 업데이트 할 수 있다.( 이 때, git remote update와 같은 역할을 함)
3. git pull : git fetch + git merge. ( 원격 저장소 내용을 업데이트하고 이를 바탕으로 로컬 저장소에서 변동사항을 병합한다.)
모르는 부분을 계속 파고들다보니, 포스트가 너무 길어졌고, 주제가 다소 산만해졌다.
하지만 잘못된 정보를 그대로 받아들인채 넘어가지않고, 나 스스로 이해할 때 까지 삽질(?)을 했기에, git의 working flow를 일부분이나마 확실히 이해할 수 있게 되었다.
배워가면서 쓴 포스트라 틀린 부분이 있을 수도 있습니다. 혹시나 틀린 부분이 있다면 지적해주면 감사하겠습니다.
'Git' 카테고리의 다른 글
Windows 환경에서 Github pages와 jekyll 를 활용해 나만의 블로그 웹호스팅하기 (0) | 2022.06.01 |
---|---|
[git] 새로 만든 원격 브랜치로 checkout이 안될 때. - error: pathspec did not match any file(s) known to git 해결법 (1) | 2022.01.08 |
Detached Head (6) | 2021.11.16 |