Critical! | Important | Nice To Have |
---|---|---|
Remote Tracking Branches | ||
Git Fetch | ||
Git Pull |
이 섹션은 깃허브에서 컴퓨터로 코드를 다운받는 것을 다룬다.
이게 중요한 이유는, 다른 사람들과 협업하면, 다른 사람들이 우리의 저장소를 변경하기 때문이다. (즉, 타인이 푸쉬를 하고 커밋을 한 다는 거다.)
그럼 이것을 어떻게 다운받을까?
Fetch와 Pull을 다루기 전에, repo Cloning과 Remoting이 어떻게 작동하는지 이해해야 한다.
저장소를 클론할 때는, 저장소가 무엇이든, 내가 만든 것이든 리액트를 클론하든 또는 어떤 인기 있는 오픈 소스 저장소를 클론하든, 처음에는 내 컴퓨터에는 아무 것도 없다.
△ git clone이 URL로 클론하면, 저장소에서 온 모든 파일과 세 개의 커밋과 저장소, master branch가 생긴다.
- My computer를 보면, 브랜치 참조가 master와 origin master 두 개가 보인다.
△ 표준 마스터 브랜치 참조, 즉 평범한 브랜치 참조이다.
혹시 이름이 master나 main이 아니어도 default branch는 클론 했을 때 시작점이 된다.
△ 이것은 "remote tracking branch" 라 부른다.
복잡하게 들리지만, 기본적으로 포인터이다.
하지만, 이 포인터는 움직이지 않는다. 내가 직접 움직이는 것도 아니다.
origin remote에서 master branch의 가장 마지막으로 알려진 커밋을 가르킨다.
Remote Tracking Branches
책갈피 또는 마지막으로 원격 저장소와 통신한 시간을 기억하는 포인터로, master/main branch가 origin 깃허브 저장소에서 가리키는 곳이다.
(remote)/(branch-name)패턴을 따른다.
이런 원격 추적 브랜치를 실제로 볼 수 있는다.
git branch -r
- 이 명령어를 사용하면 그 브랜치 참조를 볼 수 있다.
실습을 하기 위해 새 저장소를 만든다.
△ creating a new file을 클릭하여 새 파일을 만든다.
△ 밑에 Commit new file을 만들어 커밋을 한다.
△ 하나의 커밋이 생겼다.
△ 이제 URL을 복사한 다음, 내 컴퓨터에서 볼 수 있도록 빈 폴더를 만든다.
△ 저장소가 존재하지 않는 폴더이다.
△ animals디렉토리가 생긴 것을 볼 수 있다.
△ 메인 브랜치만 존재하는 것을 볼 수 있다.
△ remote -v를 통해, 어디에 연결 되어있는지 볼 수 있고,
git branch -r을 통해서,
origin/main이 Remote Tracking Branch인 것을 볼 수 있다.
Remote Tracking Branch가 어렵다면 참고
△ 세 개의 커밋이 있는 저장소를 클론했다고 가정해보자.
△ 마스터 브랜치에서 새 커밋을 만들면 이렇게 master포인터는 업데이트가 된다.
△ 한 가지 커밋을 더 업데이트 해서 두 개의 새 커밋이 생겨도, remote tracking branch는 업데이트 되지 않은 것을 볼 수 있다.
- Remote Tracking Branch는 origin/master의 마지막으로 알려진 지점에 남아있다.
△ pets.txt를 수정하고 add, commit한 뒤에, push를 하지 안하게 된다면, local에만 저장되고 Github에는 저장되지 않는다.
△ Your branch is ahead of 'origin/main' by 1 commit.
(use "git push" to publish your local commits)
- 이 뜻은, 내 master branch가 Remote Tracking Branch인 'origin/master'이 위치한 곳에서 1커밋 앞에 있다는 뜻이다.
또 한번, 커밋을 진행하면
△ Your branch is ahead of 'origin/main' by 2 commit.
(use "git push" to publish your local commits)
- 이 뜻은, 내 master branch가 Remote Tracking Branch인 'origin/master'이 위치한 곳에서 2커밋 앞에 있다는 뜻이다.
origin/master 또는 origin/main가 위치한 commit의 버전으로 되돌려서 현재 작성한 코드와 비교하려면 다음과 같은 명령을 내려라.
△ git checkout origin/main을 입력하면 깃허브와 마지막으로 통신했던 commit을 불러올 수 있다.
- 이 상태에서, 새 브랜치를 만들고 작업을 하거나, 실행을 취소하거나, 작업을 끝내고 메인으로 돌아갈 수 있다.
만약 다시 원래 상태로 돌아가고 싶다면 다음과 같이 입력해라.
△ 원래대로 돌아 온 것을 볼 수 있다.
△ 푸쉬를 한 뒤에 status를 보면, Remote Tracking Branch가 Main Branch와 위치가 동일해 진 것을 알 수 있다. (최신 상태에 있다.)
이제 remote branch로 작업하는 방법에 대해 다뤄본다.
예를 들어 클론하거나 작업하려는 깃허브 저장소에 브랜치가 여러 개 있다면 로컬에서 해당 브랜치들로 작업하려면 어떻게 해야 할까?
실습을 위해 아래 링크에 들어간다.
△ 기본 브랜치인 메인 브랜치에는, 파일이 두 개 있다.
△ 클론을 한다.
△ 최신 상태에 있는 것을 볼 수 있다.
default branch는 main인 것을 알 수 있다.
△ 브랜치도 하나 인 것을 볼 수 있다.
△ 위 세 브랜치에서 어떻게 작업을 할까?
△ 이 슬라이드를 보면, 기본 브랜치인 master branch와 puppies branch가 있는 것을 볼 수 있다.
△ 프로젝트를 Clone할 때는 모든 기록과 모든 데이터를 갖게 된다.
하지만 그것들이 한 번에 내 작업 공간으로 온다는 뜻은 아니다.
git branch를 입력할 때 보았듯이, 메인 또는 마스터 branch만 표시된다.
다른 branch들 보이지 않는다.
위에서 하던 실습에서 git branch -r을 입력하면 다음과 같이 나타난다.
△ 즉 내 로컬 저장소는 모든 브랜치에 대해 알고 있으며, 원격 추적 참조(Remote Tracking Reference)가 있어서 각 브랜치가 어디에 있는지 알려줄 수 있다.
그런데 내 저장소는 그것들을 알고 있지만, 나는 완전한 브랜치를 보지 못한다.
어떻게 하면 볼 수 있을까?
완전한 브랜치와 원격 추적 브랜치 사이의 관계에 대해 얘기할 필요가 있다.
기본적으로 저장소를 클론할 때 (이 그림에서는 master branch), 이 master branch는 자동으로 추적된다. 이것은 원격 브랜치 origin/master와 연결되어 있다. 둘 다 마스터로 같은 이름이다.
뭔가를 클론하면, 자동적으로 연결된다.
그럼 여기에서, Workspace에서 만든 브랜치를 origin/puppies와 연결하려면 어떻게 해야할까?
만약 checkout을 사용하면 아래 예제와 같이 작동한다.
main이 아닌 임시 branch로 바뀌었다.
하지만 우리가 원하는 것은, 단순히 origin/puppies와 연결되어 작업할 수 있는 branch이다.
그렇게 하기 위해서는, 위와 같은 명령어를 입력한다. 이것은, 정확히 같은 이름을 가진 브랜치로 스위치한다.
우리가 퍼피라는 브랜치를 만들고, 퍼피라는 원격 브랜치가 이미 있는것을 감지하면 깃은 우리가 퍼피에 연결되기를 원한다고 감지한다.
git switch puppies
깃은 퍼피라는 로컬 브랜치를 만들고 자동으로 remote branch origin/puppies를 추적하도록 설정한다.
△ 위와 같이 퍼피라는 브랜치를 갖게 되고, 이건 origin/puppies를 가리키거나 연결된다.
△ main branch로 돌아온 뒤, git switch movies를 입력하면 오리진에서 원격 브랜치 무비를 추적하도록 설정된다.
△ 브랜치 목록은 main과 movies가 있다.
△ food로 한 번 더 연습.
로컬에는 없고 깃허브 repo에만 있는 브랜치에서 작업하려면 과거에는 위와 같은 이런 명령어를 사용했다.
△ 로컬 저장소를 클론해오고, 깃허브에 있는 모든 항목이 완전히 최신 상태라 해보자.
마스타 브랜치 포언티와 오리진/마스터 둘 다 최신 커밋을 참조한다.
△ 로컬에서 커밋을 한다.
내가 노란색부분에서 작업을 하고 있을 때,
△ 다른 동업자가 초록색으로 표시된 새 커밋 3개를 추가했다고 가정하자.
이것들은 깃허브의 마스터 브랜치에 있고, 지금 내 로컷에는 존재하지 않는다.
이럴 경우 어떻게 처리해야 할 까?
여기서 페칭과 풀링에 대해 얘기하겠다.
git fetch, git pull 명령이 필요하다.
△ git fetch, git pull은 원격 저장소에 새 커밋을 가져온다.
git fetch
페칭은 remote repo의 변경 사항을 가져온다.
깃허브 저장소에서 항목들을 로컬 저장소로 가져온다.
페칭을 사용하면 원격 저장소에서 변경 사항을 다운로드할 수 있지만, 이러한 변경 사항은 우리의 작업 파일과 통합되지 않는다.
최신 변경 사항을 가져와서 컴퓨터에서 접근할 수 있게 하는 거다. 하지만 그것들을 실제 로컬 워킹 디렉토리에 병합할 필요는 없다. 왜냐하면 파일을 엉망으로 만들 필요가 없다.
사진에 마지막 문장을 보면 "깃허브에서 최신 정보를 가져와라, 하지만 현재 작업 중인 것을 망치지는 말아줘"
즉, 이 git fetch 명령을 사용하여 접근할 수 있다.
△ git fetch {remote}
그냥 git fetch만 해도 되지만, git fetch origin이라고 하면, 오리진을 가져온다. (default는 origin이다.)
△ 위와 같은 명령을 사용하면, 하나의 브랜치만 Fetching할 수 있다.
△ 따라서, 위의 상황을 해결하려면
△ 위와 같이 되고, origin/master가 업데이트 된다.
하지만 로컬의 마스터 브랜치는 전혀 변하지 않는다.
△ 즉, 변경 사항을 다운로드 했지만, 그걸 워킹 디렉토리에 통합하지는 않은 거다.
Git fetch는 원격 저장소에서 변경된 커밋들을 로컬 저장소로 가져오는 명령어입니다. 다른 개발자들이 원격 저장소에 업로드한 코드 변경 사항이 있을 때, 이를 로컬 저장소로 가져오기 위해 사용됩니다.
Git pull 명령어와 비교하여, Git fetch는 로컬 저장소의 현재 작업 중인 브랜치에 영향을 주지 않습니다. 다시 말해, Git fetch는 원격 저장소에서 변경된 사항을 로컬 저장소로 가져오는 것이지, 로컬 저장소의 코드를 원격 저장소의 변경된 코드로 업데이트하는 것은 아닙니다. 이후 Git merge나 Git rebase 명령어와 함께 사용하여 원격 저장소에서 변경된 내용을 로컬 작업 중인 브랜치에 반영할 수 있습니다.
따라서, 다른 개발자들이 원격 저장소에 업로드한 코드 변경 사항을 로컬 저장소로 가져와서 로컬 작업 중인 브랜치에 반영하기 전에, Git fetch 명령어를 사용하여 변경 사항을 확인하는 것이 좋습니다.
△ 실습으로 사용 할 예제
여기에서, 다른 사람이 다른 브랜치를 추가 했다고 해보자.
△ 이 명령으로 패치를 해도 되고.
△ 이 명령을 쓰면 한 브랜치만 패치 할 수 있다.
△ 새 브랜치를 만들어도... 패치해도 뭐가 없네...
△ master브랜치에 새로운 커밋을 추가하고 패치를 해보자.
△ 깃헙에 있던 zero파일이 들어왔다.
△ 브랜치 이름도 바뀌었다.
△ 브랜치도 바꿀 수 있다.
△ second브랜치에 새로운 브랜치를 추가해본다.
△ 새로운 파일 4.txt를 추가해준다.
△ remote브랜치에서 보이지 않는다. 하지만 다시 fetch를 하면
△ 새로운 브랜치 second-add -> origin/second-add 가 나온다.
△ git branch -r을 하면 추가된 브랜치가 보인다.
git pull에 대해 알아보자.
git pull은 fetch와 비슷하다. 둘 다 원격에서 파일들을 가져온다.
fetch와 가장 큰 차이점은 풀은 헤드 브랜치를 업데이트한다는 것이다.
"깃, 깃허브에 가서 최신 업데이트를 가져오고 내 WorkingDirectory에 바로 반영해줘" 라고 명령을 하는 것이다.
Git pull 명령어는 원격 저장소에서 변경된 내용을 가져와서 로컬 작업 중인 브랜치에 반영하는 명령어입니다.
Git pull은 다음과 같은 두 가지 작업을 수행합니다.
Git fetch: 원격 저장소에서 변경된 내용을 가져옵니다.
Git merge 또는 Git rebase: 가져온 내용을 로컬 작업 중인 브랜치에 반영합니다.
기본적으로 Git pull은 Git merge를 실행합니다. 이는 원격 저장소와 로컬 저장소 간의 변경 내용이 충돌하지 않는다는 것을 가정합니다. 만약 충돌이 발생한다면, 충돌을 해결하고 나서 다시 commit을 해야 합니다.
△ git pull 원격이름 브랜치이름
중요한 것은, 내가 어디서 풀링을 하느냐 이다.
내가 어떤 브랜치에 있든, 내가 풀링 다운하는 곳으로 변경 사항은 병합된다.
예를 들어, 내가 마스터 브랜치에 있고, git pull origin master를 실행하면 오리진 마스터의 변경사항을 Fetching해와서, 내가 현재 있는 브랜치에 병합한다.
내가 마스터 있으면, 마스터에 병합한다.
단, 패치를 하고 병합하기 때문에, 다른 병합들처럼 가끔 병합 충돌이 일어날 수 있다.
그럴 땐, 일반적인 병합처럼 해결하면 된다.
먼저, 충돌이 일어나지 않는 예시를 살펴보기 위해, 위해서 했던 패치 예시를 가져오겠다.
먼저, master브랜치를 살펴보겠다. origin master는 zero.txt가 포함되어 있지만 로컬 브랜치에는 포함되어있지 않다.
△ 파일 zero.txt가 마스터브랜치에 포함 된 것을 볼 수 있다.
앞에서 몇 번 말했듯이, 풀은 충돌을 일으킬 수 있다.
master 브랜치에 PullMerge.txt란 파일을 만들고, 충돌이 일어나게끔 제작해본다.
로컬에서는 파일을 추가한다음 add, commit까지 해준다.
△ 로컬과 원격의 내용이 다른 것을 볼 수 있다.
△ 풀 실패. CONFLICT가 발생한다.
△ 위는 로컬에서 저장되 있는 것이고, 아래는 깃헙에서 온 것이다.
△ 수정한 파일.
△ add, commit을 해준다.
이제 깃허브로 푸쉬할 수 있고, 충돌이 발생하지 않는다. (누군가 깃허브에 새로운 커밋을 추가해서 변경하지 않는다면...)
△ 푸쉬를 하면, 깃허브에도 반영이 된다.
△ second 브랜치에서 파생된 브랜치인 second-add브랜치를 pull해도 second-add브랜치가 생기진 않는구나...
△ 테스트를 위해 PullTest.txt파일을 추가한다.
upstream추가를 하고, git pull을 하면 간편하게 pull이 된다.