Git&Github

25. [Git] pull, fetch 차이점

drizzle0925 2021. 8. 28. 17:40
728x90

협업을 해서 작업을 할 때의 흐림은 pull -> 작업 -> add -> commit -> push의 반복으로 이루어집니다.

근데 여기서 pull 대신에 fetch -> merge FETCH_HEAD -> 작업 -> add -> commit -> push로도 작업하는 것이 가능합니다. 이번에는 pull과 fetch가 어떻게 다른지에 대해서 알아보겠습니다.

 

pull

  • 원격 저장소로부터 필요한 파일을 다운+병합
  • 지역 브랜치와 원격 저장소 origin/master가 같은 위치를 가리킨다.

fetch

  • 원격 저장소로부터 필요한 파일을 다운 (병합은 따로 해야 함)
  • 지역 브랜치는 원래 가지고 있던 지역 저장소의 최근 커밋 위치를 가리키고, 원격 저장소 origin/master는 가져온 최신 커밋을 가리킨다.
  • 신중할 때 사용한다.
  • 사용하는 이유?

    원래 내용과 바뀐 내용과의 차이를 알 수 있다. (git diff HEAD origin/master)

    commit이 얼마나 됐는지 알 수 있다(git log --decorate -all --oneline)

    이런 세부 내용 확인 후 git merge origin/master 하면 git pull 상태와 같아진다. (병합까지 완료)

 

 

실제 화면을 보면서 비교해보도록 하겠습니다.

왼쪽이 철수, 오른쪽이 영희라고 가정하고 설명하겠습니다.

 

1. 철수는 work.txt를 수정하고 commit을 합니다.

 

2. 철수의 로그를 확인해 보겠습니다.

$ git log

HEAD -> master가 origin/master보다 앞서 있다는 걸 확인할 수 있습니다.

HEAD -> master는 현재 작업 중이 로컬 저장소의 master 브랜치를 의미하고 origin/master는 원격 저장소의 master 브랜치를 의미합니다. 즉, 원격 저장소의 master 브랜치보다 버전이 앞서 있다는 걸 뜻합니다.

 

3. 이번에는 git status로 현재 어떤 상태인지 확인해 보겠습니다.

$ git status

Your branch is ahead of 'origin/master' by 1 commit.

당신의 브랜치는 origin/master보다 버전이 하나 앞서있다고 메시지가 나옵니다.

git log로 확인했던 것처럼 현재 원격 저장소보다 버전이 하나 앞서 있어서 이런 메시지가 출력되는 것입니다.

 

 

4. commit 내용을 push 합니다.

 

$ git log

로그를 확인하면 HEAD -> master와 origin/master가 같은 버전을 가리키고 있습니다.

즉, 같은 버전을 뜻합니다.

 

$ git status

아까 출력되었던 ahead 메시지는 사라지고 브랜치는 origin/master 브랜치와 같이 최신이라는 메시지가 나옵니다.

 

이것을 왜 설명했는가 하면 fetch랑 연관이 있기 때문입니다.

이번에는 git-collaboration2로 이동하여 영희가 작업했을 때를 알아보겠습니다.

 

일단 pull과 fetch의 차이를 설명하기 위해 동일 조건에서 pull과 fetch를 사용해서 비교해보도록 하겠습니다.

(협업 작업을 할 때는 commit, push, pull 자주 해주면 트러블이 생기는 일을 줄일 수 있습니다.)

그래도 동일 작업이 생기는 어쩔 수 없는 상황들이 꽤 자주 있을 거라 생각합니다.

 

이번 상황은 철수와 영희가 최신 버전에서 작업하다가 철수가 먼저 commit 하고 push를 한 상황을 예시로 들어보겠습니다. 왼쪽이 철수, 오른쪽이 영희입니다.

 

현재 원격 저장소(repository)는 철수의 work 2 commit이 최신 버전으로 된 상태입니다.

여기서 영희도 work.txt 파일을 수정해서 업로드해보겠습니다. 파일을 수정하고 commit을 했습니다.

 

 

그럼 나중에 영희가 push를 할 때는 로컬 저장소와 원격 저장소의 사이에 버전이 달라 reject 되는 현상이 발생하게 됩니다.

이러면 git pull 명령어를 이용해서 최신 버전을 받아오도록 합니다.

 

git pull 명령어를 이용해서 최신 버전을 받아오면 merge라고 나오면서 병합이 필요한 상황이 됩니다.

(같은 work.txt의 동일한 부분을 수정해서 MERGING 상태가 되었습니다. 다른 파일을 생성했거나 수정 장소가 다른 경우 안 나올 수도 있습니다.)

 

cat 명령어를 이용해서 확인하니 아래와 같습니다.

 

<<<<<<<HEAD는 저의 로컬 저장소이고

>>>>>>>commit id는 원격 저장소의 내용입니다.

아래와 같이 수정해서 add 하고 commit 합니다.

 

로그를 확인해보면 철수의 커밋과 영희 커밋 그리고 merge작업을 진행 커밋으로 총 3개의 커밋이 추가된 것을 확인할 수 있습니다. pull 이용해서 작업할 경우는 이대로 push 해서 원격 저장소에 업로드하면 됩니다.

 

그러면 이번에는 fetch를 이용해서 같은 작업을 진행해 보겠습니다.

철수는 0a013c0에서 새로운 버전을 만들어서 원격 저장소에 업로드했습니다.

영희는 이 사실을 모르고 0a013c0인 채로 파일을 수정해서 push를 해보겠습니다.

 

다시 파일을 수정하고 commit까지 진행하고 로그를 확인해봅니다.

 

다시 push를 입력하면 reject이라고 나오면서 push가 되지 않습니다.

 

이번에는 pull 말고 fetch를 이용해보겠습니다.

아래 명령어를 입력합니다.

$ git fetch

 

fetch 명령어 사용 후 work.txt 파일 내용을 확인해보겠습니다.

work.txt 파일에 철수가 원격 저장소(repository)에 업로드한 내용이 반영되어 있지 않습니다.

 

그러고 나서 git log와 git status 정보를 확인해보겠습니다.

git log --oneline

아까는 보였던 origin/master와 origin/HEAD가 안 보입니다.

 

아래 명령어를 입력합니다.

# 같은 명령어 입니다.
$ git log --oneline --all
$ git log --oneline -a

철수 work 3가 영희 work3보다 아래에 있습니다.

fetch 명령어를 통해 원격 저장소(repository)에서 최신 버전을 가져온 것입니다.

 

 

$ git status

상태를 확인하는 명령어를 입력하면 origin/master와 로컬(HEAD)이 다른 커밋을 각각 하나씩 가지고 있다는 메시지가 나옵니다.

1. 원격 저장소에 올라간 철수 work 3

2. 로컬 저장소에서 생성한 영희 work 3

을 의미합니다.

 

git fetch 명령어를 사용하면 FETCH_HEAD라는 branch가 생성되며 checkout FETCH_HEAD로 fetch 내용을 확인할 수 있습니다.

git checkout FETCH_HEAD

 

파일을 합치고 싶다면 git merge를 사용합니다.

fetch를 할 때마다 최신 버전의 FETCH_HEAD 생성되므로 아래 명령어를 추천합니다. 

# 같은 명령어 입니다.
git merge origin/master
git merge FETCH_HEAD

 

충돌을 해결 주고 업로드하면 됩니다.

 

원격 저장소에 push 된 모습입니다. 

728x90