[이전 포스트]
[Git] 버전 관리의 꽃 3, 기본이자 유용한 전략
Git - 브랜치 워크플로Git은 꼼꼼하게 3-way Merge를 사용하기 때문에 장기간에 걸쳐서 한 브랜치를 다른 브랜치와 여러 번 Merge 하는 것이 쉬운 편이다. 그래서 개발 과정에서 필요한 용도에 따라 브
300-29-1.tistory.com
Git - 리모트 브랜치
“origin” 의 의미 브랜치 이름으로 많이 사용하는 “master” 라는 이름이 괜히 특별한 의미를 가지는 게 아닌 것처럼 “origin” 도 특별한 의미가 있는 것은 아니다. git init 명령이 자동으로 만들
git-scm.com
'깃북 3.5 Git 브랜치 - 원격 브랜치'에 대한 발췌 및 정리입니다.
이번 개념은 어렵습니다.
따라서 먼저 아래 글을 통해 로컬 서버와 원격 서버의 차이를 이해하시면 좋습니다.
“Remote references are references (pointers) in your remote repositories.”
원격 레퍼런스들은 원격 저장소를 가리키는 참조입니다.
원격 저장소, 즉 리모트 저장소에 있는
브랜치, 태그 등을 의미합니다.
지금까지 배웠던 저장소, 브랜치 등이 모두
개인 로컬 저장소에서의 작업이라면
위 개념은 저장소가 로컬이 아닌 원격으로 확장되는 개념입니다.
브랜치가 어떠한 곳을 가리키는 “포인터” 역할을 한다고 했던 것이 기억나시나요?
“포인터”라는 의미에서, remote branch는 결국
원격 저장소의 특정 branch를 가리키는 역할을 한다고 볼 수 있습니다.
그러나 작업하는 곳은 결국 개인의 git 레포지토리이기 때문에,
개인의 git 레포지토리에 등록된 각 원격지의 저장소에 대해 유지하고 있는 레퍼런스 목록은
git ls-remote [remote repository name] 으로 확인할 수 있습니다.
git remote show [remote repository name] 명령은 모든 원격 브랜치와 그 정보를 보여줍니다.
원격 저장소에 대한 레퍼런스들이 존재하기도 하고, 확인할 수 있기도 하나,
보통은 원격 추적 브랜치 즉 리모트 트래킹 브랜치를 통해
원격 저장소와의 상호작용을 진행합니다.
리모트 트래킹 브랜치는
리모트 브랜치를 추적하는 레퍼런스이며 브랜치입니다.
리모트 트래킹 브랜치는 내가 현재 작업하는 로컬에 있지만,
임의로 움직일 수 없습니다.
리모트 서버에 연결할 때마다 리모트의 브랜치 업데이트 내용에 따라서
자동으로 갱신될 뿐입니다.
리모트 트래킹 브랜치는 일종의 북마크라고 할 수 있습니다.
리모트 저장소에 마지막으로 연결했던 순간에
브랜치가 어떤 커밋을 가리키고 있었는지를 나타냅니다.
리모트 트래킹 브랜치의 이름은 보통
<remote>/<branch> 의 형식으로 되어 있습니다.
원격 저장소 origin의 master 브랜치를 보고 싶다면, 로컬에서 origin/master 라는 이름으로 브랜치를 확인하면 됩니다(물론 리모트 저장소를 로컬에 등록해야 합니다).
다른 팀원과 함께, 어떤 이슈를 구현할 때
그 팀원이 iss53 브랜치를 원격 Git 서버로 Push 했고
나도 로컬에 iss53 브랜치가 있다고 생각해봅시다.
이 때 서버의 iss53 브랜치가 가리키는 커밋은,
내 로컬에서 origin/iss53 브랜치가 가리키는 커밋으로 생각할 수 있습니다.
예시
다소 헷갈릴 수 있으니 예제를 좀 더 살펴봅시다.
git.ourcompany.com 이라는 주소를 가지는 원격 저장소, 즉 Git 서버가 원격지에 존재한다고 해봅시다.
해당 Git의 master라는 브랜치 보고 싶다면,
현재 내가 작업중인 로컬 Git에 git.ourcompany.com 서버의 저장소를 하나 Clone해야 합니다.
이러면 Git은 자동으로 origin 이라는 이름을 붙여줍니다.
origin으로부터 저장소 데이터를 모두 내려받고, 원격 저장소의 master 브랜치를 가리키는 포인터를 만듭니다.
이 포인터는 내 로컬에서 origin/master 라는 브랜치로 관리됩니다.
이후, 내 로컬 Git의 master 브랜치가 origin/master를 가리키게 합니다.
이러면! 이 때부터 master 브랜치에서 작업을 시작할 수 있습니다.
(origin에 특별한 의미가 있는 것은 아닙니다. Git을 처음 시작하면 master 브랜치가 기본적으로 생성되는 것처럼, 이 역시 원격 저장소 clone 시 기본적으로 생성되는 remote name입니다.)
이 상황에서,
내(My Computer)가 로컬 저장소에서 어떤 작업을 하면서 로컬에 커밋을 하고 있는데,
다른 팀원이 작업을 끝내서 git.ourcompany.com 서버의 Push하고 master 브랜치를 업데이트 했다고 해봅시다.
그러면 이제 팀원간의 히스토리가 서로 달라집니다.
나는 서버 저장소로부터 어떠한 데이터(혹은 변경사항)도 주고받지 않아,
내 local의 origin/master 포인터는 현재 그대로인 상태입니다.
전체 브랜치들을 한 번 다시 봐볼까요?
현재 원격 저장소의 master는 f4265 커밋을 지나, 현재 190a3 커밋을 가리키고 있습니다.
origin/master 브랜치, 즉 내 컴퓨터의 로컬 저장소에서 유지하는 원격 저장소의 master는
여전히 f4256 커밋에 머물러 있습니다.
내 로컬의 master 브랜치, 즉 순수하게 내 로컬에서 작업중인 master 브랜치는
f4265 커밋에서 시작했지만, 원격 서버의 작업내용과 다른 히스토리를 거쳐
현재 893cf 커밋을 가리키고 있습니다.
로컬의 origin/master 브랜치와
원격 저장소의 master 브랜치는 논리적으로 동일한 대상을 가리키고 있기 때문에,
원격지의 작업에 의한 변경사항을
로컬은 전달받아 동기화해야 합니다.
이 과정을 fetch 라고 합니다.
git fetch 명령은 원격 브랜치 정보를 업데이트합니다.
아래 그림을 봅시다.
이로써
원격 저장소의 190a3 커밋을 가리키는 master 브랜치와 동일하게,
내 로컬 컴퓨터 저장소의 리모트 트래킹 브랜치, origin/master 도 190a3 커밋을 가리키고 있습니다.
( 로컬에서는 원격 저장소 git.ourcompany.com 를 origin 이라는 이름으로 유지하고 있습니다. )
동기화가 완료된 상태입니다.
이러한 리모트 트래킹 브랜치, 즉 원격지의 브랜치를 로컬에서 참조하는 브랜치는
로컬에서 읽기만 가능할 뿐, 직접적인 수정은 불가능합니다.
이 “읽기만 가능”한 조건을 통해 Git은 로컬 작업과 원격 저장소의 상태를 명확히 구분하여
효과적으로 관리할 수 있습니다.
이는 추후 “Push 하기”에서 다루겠습니다.
원격 저장소를 여러 개 운영할 때
teamone 이라는 새로운 원격 저장소를 하나 더 만들어 관리하고 있다고 가정해볼까요?
teamone 이라는 저장소는 주소가 git.team1.ourcompany.com 입니다.
이로써 여러 개의 원격 저장소를 연동한 환경에서
개발하는 상황을 모사해볼 수 있습니다.
이러한 상황에서, teamone 에서 작업한 내용을 확인해보기 위해,
git fetch teamone 명령으로 teamone 서버의 데이터를 내려받는다고 생각해봅시다.
명령을 실행해도 teamone 서버의 데이터는 모두 origin 서버에도 있는 것이라,
당장은 아무것도 내려받지 않습니다.
하지만 이 명령은 원격 트래킹 브랜치 teamone/master를 생성하고,
이를 teamone 서버의 master 브랜치가 가리키는 커밋을 가리키게 지정합니다.
Push 하기
로컬의 브랜치를 서버로 전송하려면,
쓰기 권한이 있는 원격 저장소에 Push해야 합니다.
로컬 저장소의 브랜치는 자동으로 리모트 저장소로 전송되지 않습니다.
사용자가 명시적으로 브랜치를 Push해야 정보가 전송됩니다.
따라서 개인은 리모트 저장소에 전송하지 않고 로컬 브랜치에만 두는
"비공개 브랜치"를 만들 수도 있습니다.
혼자만 사용하던 “serverfix”라는 브랜치를
다른 사람과 공유하기 위해 원격 저장소에 업로드 하는 상황을 생각해봅시다.
serverfix 라는 브랜치를 다른 사람과 공유할 때도
브랜치를 처음 Push 하는 것과 같은 방법으로 Push 합니다.
아래와 같이 git push <remote> <branch> 명령을 사용합니다.
$ git push origin serverfix
Counting objects: 24, done.
Delta compression using up to 8 threads.
Compressing objects: 100% (15/15), done.
Writing objects: 100% (24/24), 1.91 KiB | 0 bytes/s, done.
Total 24 (delta 2), reused 0 (delta 0)
To <https://github.com/schacon/simplegit>
* [new branch] serverfix -> serverfix
( * [new branch], 즉 원격 저장소에 새로운 브랜치를 생성했다는 알림 확인 가능 )
만약 리모트 저장소에 serverfix 라는 이름 대신 다른 이름을 사용하려면
git push origin serverfix:awesomebranch 처럼 사용하면 됩니다.
나중에 다른 사람이 서버에 있는 serverfix 브랜치에 접근하려면,
우선 git fetch origin 명령을 통해 원격 저장소의 변경사항(serverfix 브랜치의 추가)을
로컬에 반영하고,
이후 origin/serverfix 라는 이름으로 접근할 수 있습니다.
$ git fetch origin
remote: Counting objects: 7, done.
remote: Compressing objects: 100% (2/2), done.
remote: Total 3 (delta 0), reused 3 (delta 0)
Unpacking objects: 100% (3/3), done.
From <https://github.com/schacon/simplegit>
* [new branch] serverfix -> origin/serverfix
리모트 트래킹 브랜치는 읽기 전용이다
여기서 짚고 넘어가야 할 게 있습니다.
Fetch 명령으로 리모트 트래킹 브랜치를 내려받는다고 해서,
로컬 저장소에 원격 브랜치를 수정할 수 있는 브랜치가 새로 생기는 것이 아닙니다.
로컬에서 여러 추가 커밋을 찍어 해결했다 하더라도,
서버 저장소에 push한 뒤 서버에서 반영을 완료하면
서버의 브랜치가 옮겨지는데, 이 이후에 이를 추적하는
리모트 트래킹 브랜치도 옮길 수 있는 것이기 때문입니다.
다시 말해 serverfix 라는 브랜치가 그냥 생기는 것이 아니라,
그저 수정 못 하는 origin/serverfix 브랜치 포인터가 생기는 것입니다.
새로 받은 브랜치의 내용을 Merge 하려면 git merge origin/serverfix 명령을 사용하면 되지만,
Merge 하지 않고 리모트 트래킹 브랜치에서 시작하는 새 브랜치를 만들려면
아래와 같은 명령을 사용해야 합니다.
$ git checkout -b serverfix origin/serverfix
Branch serverfix set up to track remote branch serverfix from origin.
Switched to a new branch 'serverfix'
그러면 origin/serverfix 에서 시작하고 수정할 수 있는
serverfix 라는 로컬 브랜치가 만들어집니다.
브랜치 추적, branch tracking
git checkout -b feature origin/feature
위와 같은 명령어로
리모트 트래킹 브랜치 origin/feature를
로컬 브랜치 feature로 checkout 하면,
자동으로 “트래킹 브랜치”가 만들어집니다.
(트래킹 하는 대상 브랜치를 Upstream 브랜치라고 부릅니다.)
다시 말하자면,
위 명령어를 통해
origin/feature 라는 리모트 트래킹 브랜치를 기반으로
로컬 브랜치 feature이 만들어지는데, 이 브랜치는
원격 서버 저장소의 브랜치와 직접적인 연결고리가 있습니다.
따라서 이런 트래킹 브랜치에서 git pull 명령을 내리면,
원격 저장소로부터 데이터를 내려받아
연결된 리모트 브랜치와 자동으로 Merge 합니다.
이렇게 생성된 로컬 브랜치는
원격 브랜치와 자동으로 연결되어있어,
push 및 pull 작업이 더 간단해집니다.
이것이 바로 “트래킹 브랜치”가 만들어진다는 의미입니다.
( 잠깐, checkout이 뭐냐구요?
checkout은 브랜치 간 이동을 의미합니다. )
처음 서버 저장소를 Clone 할 때
서버로부터 저장소를 Clone 하면
Git은 자동으로 origin/master 브랜치를 추적하는
master 브랜치를 만듭니다.
트래킹 브랜치를 직접 만들 수도 있다
Clone 시 처음 자동으로 생성되는 트래킹 브랜치이외에도,
리모트를 origin 이 아닌 다른 리모트로 할 수도 있고,
브랜치도 master 가 아닌 다른 브랜치로 추적하게 할 수 있습니다.
git checkout -b <branch> <remote>/<branch> 명령으로 간단히 트래킹 브랜치를 만들 수 있습니다.
$ git checkout -b sf origin/serverfix
Branch sf set up to track remote branch serverfix from origin.
Switched to a new branch 'sf'
--track 옵션을 사용하여 로컬 브랜치 이름을 자동으로 생성할 수 있습니다.
$ git checkout --track origin/serverfix
Branch serverfix set up to track remote branch serverfix from origin.
Switched to a new branch 'serverfix'
이 명령은 자주 쓰여서 더 생략할 수 있습니다.
입력한 브랜치를 가지고 있는
(a) 리모트가 딱 하나 있고
(b) 로컬에는 없으면
Git은 트래킹 브랜치의 이름을 자동으로 지정해 만들어 줍니다.
$ git checkout serverfix
Branch serverfix set up to track remote branch serverfix from origin.
Switched to a new branch 'serverfix'
이미 로컬에 존재하는 브랜치가
리모트의 특정 브랜치를 추적하게 하고 싶다면,
git branch 명령에 -u 나 --set-upstream-to 옵션을 붙여서 아래와 같이 설정합니다.
$ git branch -u origin/serverfix
Branch serverfix set up to track remote branch serverfix from origin.
브랜치들의 트래킹 정보 확인
현재 트래킹 브랜치가 어떻게 설정되어있는지 확인하려면
git branch 명령에 -vv 옵션을 넣어봅니다.
이 명령을 통해 로컬 브랜치 목록과,
로컬 브랜치가 추적하고 있는 리모트 브랜치도 함께 보여줍니다.
여기에 추가로 리모트 브랜치에 비해
해당 로컬 브랜치가 앞서가는지 뒤쳐가는지에 대한 내용도 보여줍니다!
$ git branch -vv
iss53 7e424c3 [origin/iss53: ahead 2] forgot the brackets
master 1ae2a45 [origin/master] deploying index fix
* serverfix f8674d9 [teamone/server-fix-good: ahead 3, behind 1] this should do it
testing 5ea463a trying something new
하나하나 봐봅시다.
- iss53 브랜치
- 현재 origin 리모트의 iss53을 트래킹하고 있습니다.
- 현재 로컬의 작업물이 2 커밋 앞서있습니다.
- 로컬 브랜치가 커밋 2개 앞서 있습니다(리모트 브랜치에는 없는 커밋이 로컬에는 존재)
- master 브랜치
- origin/master 를 추적하고 있고
- 두 브랜치가 가리키는 내용이 동일한 상태입니다.
- serverfix 브랜치
- *표시는 현재 HEAD가 serverfix를 가리키고 있다는 것입니다.
- teamone/server-fix-good 브랜치를 추적중입니다.
- 현재 로컬에서 커밋 3개가 앞서고 있으며, 서버에서 로컬로 아직 merge하지 않은 커밋이 1개 있다는 내용입니다.
- testing
- 추적하는 브랜치가 없는 상태입니다.
주의점이 있습니다.
명령을 실행했을 때 나타나는 결과는
모두 마지막으로 서버에서 데이터를 가져온(fetch) 시점을 바탕으로 계산합니다.
단순히 이 명령만으로 서버의 최신 데이터를 반영하지 않습니다.
현재 시점에서의 서버 최신 데이터로 추적 상황을 알아보려면,
먼저 서버로부터 최신 데이터를 받아온 후에 추적 상황을 확인해야 합니다.
아래처럼 두 명령을 이어서 사용하는 것이 적당합니다.
$ git fetch --all; git branch -vv
Pull
git fetch 명령을 실행하면
서버에는 존재하지만
로컬에는 아직 없는 데이터를 받아와서 저장합니다.
이 때 워킹 디렉토리의 파일 내용은 변경되지 않고 그대로 남습니다.
서버로부터 데이터를 가져와 저장해두고, 사용자가 Merge하도록 준비만 합니다.
이후 Merge 명령을 통해 서버의 내용을 현재 워킹 디렉토리에 반영하는 것입니다.
git pull은 fetch이후 자동으로 merge 를 수행하는 명령입니다.
git clone 혹은 checkout을 통해
트래킹 브랜치를 설정하면,
이후의 git pull 명령은 단순히 서버로부터 데이터를 가져와
현재 로컬 브랜치와 서버의 추적 브랜치를 Merge하는 일련의 과정입니다.
편리하지만, git pull 의 남용은 좋지 않습니다.
pull 단계에서 오류가 발생했을 때,
단순히 fetch에서 발생한건지 merge에서 발생한 오류인지를 구분하기 위한 점에서도
일반적으로 fetch와 merge 명령을 명시적으로 사용하는 것이
pull 명령으로 한 번에 두 작업을 하는 것보다 좋습니다.
원격 브랜치 삭제
동료와 협업하기 위해 원격 저장소에 브랜치를 하나 생성하고,
지금까지 작업을 진행했습니다.
작업이 종료되고 이후 원격 저장소에 존재하는 브랜치를 삭제하려면
다음처럼 push 명령을 통해 서버로 명령을 보내야 합니다.
git push 명령에 --delete 옵션을 사용하여 리모트 브랜치를 삭제할 수 있습니다.
serverfix 라는 리모트 브랜치를 삭제하려면 아래와 같이 실행합니다.
$ git push origin --delete serverfix
To <https://github.com/schacon/simplegit>
- [deleted] serverfix
위 명령을 실행하면 서버에서 브랜치(즉 커밋을 가리키는 포인터) 하나가 사라집니다.
[다음 포스트]
[Git] 위험한데, 내 커밋 히스토리가 깔끔해져요! - Rebase
Git - Rebase 하기Rebase는 기존의 커밋을 그대로 사용하는 것이 아니라 내용은 같지만 다른 커밋을 새로 만든다. 새 커밋을 서버에 Push 하고 동료 중 누군가가 그 커밋을 Pull 해서 작업을 한다고 하자
300-29-1.tistory.com
Ref.
Git - 리모트 브랜치
“origin” 의 의미 브랜치 이름으로 많이 사용하는 “master” 라는 이름이 괜히 특별한 의미를 가지는 게 아닌 것처럼 “origin” 도 특별한 의미가 있는 것은 아니다. git init 명령이 자동으로 만들
git-scm.com
git remote branches — Key Puncher
Git 8: Remote Branches
www.keypuncher.net
'프로젝트 생산성' 카테고리의 다른 글
[GitHub] 개발자라고? 깃헙 알지? PR 할 줄 알지? - GitHub를 얕게만 아는 사람을 위해 (1) | 2024.09.18 |
---|---|
[Git] 위험한데, 내 커밋 히스토리가 깔끔해져요! - Rebase (0) | 2024.09.18 |
[Git] 버전 관리의 꽃 3, 기본이자 유용한 전략 (0) | 2024.09.14 |
[Git] 버전 관리의 꽃 2, 병합하기 (Merge) (0) | 2024.09.14 |
[Git] 버전 관리의 꽃, 브랜치(branch) (3) | 2024.09.14 |