저장소를 클론할 때는 일어나는 일에 대해 먼저 알아보자. 처음에는 내 컴퓨터에는 아무것도 없는데 git clone을 하면 저장소에서 온 모든 파일과 세 개의 커밋이 생긴다. 그런데 그림을 보면 브랜치 참조가 두 개가 있는 것을 알 수 있다.

평범한 master 브랜치 레퍼런스(일반 브랜치 참조)가 있고, 그리고 origin/master라는 것을 볼 수 있다. 이것은 원격 추적 브랜치 참조(remote tracking branch)라고 한다. 이 remote tracking branch(pointer)는 움직지 않는다. 이것은 오리진 원격에서 마스터 브랜치의 가장 마지막으로 알려진 커밋을 가리킨다(It's reference to the state of the master branch on the remote). 즉 마지막으로 원격 저장소와 통신한 상태를 기억하는 포인터로 생각하면 된다. 만약 로컬에서 작업을 더 한다면 일반 레퍼런스 포인터(master)와 remote tracking branch는 멀어지게 된다. 이러한 원격 추적 브랜치를 실제로 볼 수도 있는데, git branch -r 명령어를 쓰면 된다.
원격 브랜치를 확인하기 위해 로컬에서 원격으로 clone 한 후에 작업을 한번더 한 후에 git status를 하니 다음과 같이 나온다.

이 상황은 다음과 같은 상황이라는 것이다. 아래의 그림을 확인하자.

처음에 레포지토리를 클론할 때 프로젝트가 어떤 모습이었는지 궁금하면 origin/master를 확인(checkout)하면 된다(git checkout origin/master). git checkouot을 하면 다음과 같이 나오고 git branch -r을 하면 리모트 브랜치를 알 수 있다.

그리고 git checkout origin/master를 하면(git switch origin/master로는 불가능하다.) HEAD가 master 브랜치 레퍼런스를 가리키다가 origin/master 를 가리키게 되어 detached HEAD 상태가 된다.
예를 들어 클론하거나 작업하려는 깃허브 저장소에 브랜치가 여러개 있다면, 로컬에서 해당 브랜치들로 작업하려면 어떻게 해야 할까?
다음의 경우를 살펴보자.

위의 사진처럼 깃허브에서는 브랜치가 많지만, git branch를 하면 main 브랜치만 화면에 나온다.

대신에 git branch -r을 하면 다음과 같은 결과가 나온다.

처음에는(default) 로컬 마스터 브랜치가 원격 origin/master 를 추적한다. 아래의 그림을 확인하자.

이러한 경우에 어떻게 원격에 있는 origin/puppies와 로컬에 있는 puppies를 연결할 수 있을까? 이때 git switch puppies를 하면 정확히 같은 이름을 가진 브랜치를 만들고 그리고 puppies와 origin/puppies를 이어준다. 아래의 그림을 확인하자.

git fetch를 설명하기 위해서 다음과 같은 상황을 설정해보자. 우선 깃허브 원격 저장소에서 클론을 하여 로컬 저장소와 원격 저장소가 동기화가 되어있었는데, 로컬에서도 작업을 하고 깃허브에 팀원이 푸쉬를 해서 커밋이 진행되었다고 하자. 아래의 그림의 상황이다.

이러한 상황일 때, 변경 사항을 어떻게 얻을 수 있을까? 여기서 페칭과 풀링에 대한 개념이 나온다. 아래의 그림은 깃과 깃허브의 전체적인 상호작용을 보여준다.

위의 그림에서 알 수 있듯이, git fetch는 원격 레포지토리에서 로컬 레포지토리로 항목들을 가져온다. 그러나 이러한 변경 사항은 우리의 워킹 디렉토리로 오는 것은 아니다. 즉 "가서 깃허브에서 최신 정보를 가져오렴 그러나 현재 작업 중인 것은 망치지 말아줘" 라는 뜻으로 해석할 수 있다. 명령어는 다음과 같다. git fetch <remote> default가 origin으로 되어있기 때문에 git fetch이라고 하면 origin에서 가져올 것이다. 만약 git fetch <remote> <branch>라고 한다면, 특정 브랜치만 fetch 할 수 있다. 만약 앞선 예에서 git fetch origin master를 한다면, 아래의 그림과 같은 상황이 일어난다.

위의 그림을 보면 origin/master 브랜치가 깃허브와 똑같이 로컬 컴퓨터에 동기화(업데이트)된 것을 확인할 수 있다. 여기서 중요한 점은 origin/master만 새로 생긴 커밋을 표시하지 master는 가만히 있게 된다.
git pull 은 git fetch와 비슷하지만, 둘 다 원격 저장소에서 변경 사항을 가져오는 데 사용된다. 그러나 가장 큰 차이점은 git pull은 헤드 브랜치를 업데이트 한다는 것이다. 그리고 워킹 디렉토리를 업데이트 한다. 따라서 "깃 , 깃허브에서 가장 최근 데이터를 다운받아서 내 로컬 레포지토리에 업데이트해줘" 라고 말하는 것과 같다. git pull=git fetch +git merge 이라고 생각할 수도 있다.
git pull <remote> <branch>
예를 들어, 현재 마스터 브랜치에 있고, git pull origin master를 실행하면 origin's master 브랜치의 최신 정보를 현재 지금 우리가 있는 브랜치(마스터 브랜치)에 fetch 하고 병합시킨다.
가끔 깃허브에 없는 로컬 작업을 할 때가 있고, 깃허브에는 로컬에는 없는 커밋이 있을 수 있다. 예를 들어 마스터 브랜치에서 작업을 하다가, 새로운 커밋을 만들었다고 해보자. 동시에 공동 작업자가 3개의 녹색 커밋을 작성하여 깃허브에 푸시를 했다고 하자. 아래의 그림과 같은 상황이다.

이 새 커밋들을 풀다운하기 위해 git pull origin master를 하면, 충돌이 일어날 수 있다. 예를 들어 동일한 파일을 로컬에서 변경하고, 깃허브에서 변경하였을 때, 충돌이 일어날 수 있다.
** 깃허브에 무언가를 푸시하기 전에, 풀다운하여 변경 사항을 확인하는 것이 좋다.
git pull을 사용할 때 더 짧은 구문을 써도 된다. 여기서 git pull에서 아무것도 지정을 하지 않으면 기본값은 origin이 되고, 브랜치도 현재 브랜치에 맞는 원격의 브랜치로 업데이트 해준다. 앞서 말한 것처럼(git switch) 시에 원격 브랜치에 대한 추적 참조가 자동으로 된 것 처럼 단순히 git pull 을 한다면 이름을 매칭해서(예를 들어 master는 ㅐorigin/master와 연결) 원격 브랜치에 있는 업데이트 사항을 현재 로컬 브랜치에 업데이트 해준다. 아래의 그림을 보면 이해가 잘된다.
