git

Pro Git - 브랜치 워크플로, 브랜치 관리, 브랜치 추적

MasterOfAI 2021. 2. 22. 14:03

브랜치 워크플로

 

배포했거나 배포할 코드만 master 브랜치에 Merge 해서 안정 버전의 코드만 master 브랜치에 둔다.

 

개발을 진행하고 안정화하는 브랜치는 develop 이나 next 라는 이름으로 추가로 만들어 사용한다. 이 브랜치는 언젠가 안정 상태가 되겠지만, 항상 안정 상태를 유지해야 하는 것이 아니다. 테스트를 거쳐서 안정적이라고 판단되면 master 브랜치에 Merge 한다. 

 

토픽 브랜치 (issue 같이 짧은 호흡 브랜치) 에도 적용할 수 있는데, 해당 토픽을 처리하고 테스트해서 버그도 없고 안정적이면 그 때 머지 한다. 토픽 브랜치는 어떤 한가지 주제나 작업을 위해 만든 짧은 호흡의 브랜치다. 

 

 

 

iss91 은 버리고, dumbidea 와 iss91v2 를 master 에 merge 한 경우 아래와 같이 된다. 

 

이러한 작업은 모두 local 에서만 처리 한다는 것을 꼭 기억하자. Local 저장소에서만 브랜치를 만들고 Merge 했으며 서버와 통신을 주고 받는 일은 없었다. 

 

 

브랜치 관리 

 

git branch 명령은 단수히 브랜치를 만들고 삭제하는 것이 아니다. 아무런 옵션 없이 실행하면 브랜치의 목록을 보여 준다. 

* 기호가 붙어 있는 master 브랜치는 현재 Checkout 해서 작업하는 브랜치를 나타낸다. 즉, 지금 수정한 내용을 commit 하면 master 브랜치에 commit 되고 pointer 가 앞으로 한 단계 나아 간다. 

git branch -v 명령을 실행하면 브랜치마다 마지막 커밋 메시지도 함께 보여 준다. 

git branch --merged 각 브랜치가 지금 어떤 상태인지 확인하기에 좋은 옵션도 있다. 현재 Checkout한 브랜치를 기준으로 --merged 와 ,--no-merged 옵션을 사용하여 Merge 된 브랜치인지 그렇지 않은지 필터링 해 볼 수 있다. 

 

 

리모트 브랜치

 

git log --branches --decorate --graph --oneline 

을 한 후 처음 상태는 Figure-1 과 같다. 

Figure-1

master : local 의 master branch 가 가리키는 가장 최신 commit

origin/master : remote 의 master branch 가 가리키는 가장 최신 commit (리모트 트래킹 브랜치)

origin/abc : remote 의 abc branch 가 가리키는 가장 최신 commit (리모트 트래킹 브랜치)

origin/HEAD : remote 이 가르키는 branch

HEAD : local 이 가르키는 branch

 

local 에서 file을 하나 추가한 후 Commit 한 다음의 상태는 아래 Figure-2 와 같다. 

 

Figure-2

이제 해당 remote 를 또다른 곳에 clone 하고, file3.txt, file4.txt 를 commit 하고 push 해 해보면 Figure-3 처럼 되는 것이다. 

Figure-3

 

처음 local 에서 ..

git ls-remote origin 으로 모든 리모트 Refs(리모트 저장소에 있는 브랜치, 태그 등을 의미) 를 회한다. 

Local 이 아닌 origin/HEAD 의 값을 보여준다 

git remote show [remote] 모든 리모트 브랜치와 그 정보를 보여준다. 

 

리모트 트래킹 브랜치(예: origin/master) 리모트 브랜치를 추적하는 브랜치이다. 이 브랜치는 로컬에 있지만 움직일 수 없다. 리모트 서버에 연결할 때마다 리모트 브랜치에 따라서 자동으로 움직일 뿐이다. 리모트 트래킹 브랜치는 일종의 북마크라고 할 수 있다. 리모트 저장소에 마지막으로 연결했던 순간에 브랜치가 무슨 커밋을 가리키고 있었는지를 나타낸다. 

위에서 본것처럼 로컬 저장소에서 어떤 작업을 하고 있는데 동시에 다른 팀원이 서버에 push를 하고 master 브랜치를 업데이트 한다. 그러면 이제 팀원간의 히스토리는 서로 달라진다.  서버 저장소로부터 어떤 데이터도 주고 받지 않아서 origin/master 포인터는 그대로 이다. 

 

처음 clone dir에서 , 리모트 서버로부터 저장소 정보를 동기화 하려면 다음 명령중 하나를 사용하면 된다.

git fetch origin master 

 

 

명령을 실행하면 우선 "origin" 서버의 주소정보를 찾아서, 현재 로컬의 저장소가 갖고 있지 않은 새로운 정보가 있으면 모두 내려받고, 받은 데이터를 로컬 저장소에 엡데이트하고 나서, origin/master 포인터의 위치를 최신 커밋으로 이동 시킨다. 

 

 

git pull origin master 

서버로 부터 최신 정보를 내려 받고 , 자동으로 Merge 한 후 Merge commit을 만든다. 

 

브랜치 추적

 

리모트 트래킹 브랜치를 로컬 브랜치로 Checkout 하면 자동으로 "트래킹 브랜치가" 만들어 진다. 

트래킹 하는 대상 브랜치를 Upstream 브랜치 라고 부른다. 

Tracking branch는 리모트 branch 와 직접적인 연결 고리가 있는 local 브랜치 이다. 

트래킹 브랜치에서 git pull 명령을 내리면 리모트 저장소로 부터 데이터를 내려 받아 연결된 리모트 브랜치와 자동으로 머지 한다 

 

Server 로부터 저장소를 Clone하면 Git은 자동으로 master 브랜치를 origin/master 브랜치의 트래킹 브랜치로 만든다. 트래킹 브랜치를 직접 만들 수 있는데 리모트를 origin 이 아닌 다른 리모트로 할 수도 있고, 브랜치도 master 가 아닌 다른 브랜치로 추적하게 할 수 있다. --track 옵션을 사용하여 로컬 브랜치 이름을 자동으로 생성할 수도 있다. 

 

git checkout --track origing/feature/krg_chambercontrol

Upstream 브랜치 : krg_chambercontrol

이 명령은 매우 자주 쓰여서 더 생략할 수 있다. 

git checkout release/ph_fx6_101

이미 로컬에 존재하는 브랜치가 리모트의 특정 브랜치를 추적하게 하려면 

git branch -u [--set-upstream-to] origin/feature/krg_chambercontrol 

 

추적 브랜치가 현재 어떻게 설정되어 있는지 확인하려면 

git branch -vv

"ahead 2" : 리모트 브랜치에 없는 commit 2개가 local branch에 존재한다. 

"behind 1" : 리모트 브랜치에는 있는 commit 1개가 local branch에는 존재하지 않는다.  서버의 브랜치에서 아직 로컬 브랜치로 머지 하지 않은 커밋이 1개 있다. 

 

여기서 중요한 점은 명령을 실행했을 때 나타나는 결과는 모두 마지막으로 서버에서 데이터를 가져온(fetch) 시점을 바탕으로 계산한다는 점이다. 단순히 이 명령만으로는 서버의 최신 데이터를 반영하지 않으며 로컬에 저장된 서버의 캐시 데이터를 사용한다. 현재 시점에서 진자 최신 데이터로 추적 상황을 알아보려면 먼저 서버로부터 최신 데이터를 받아온 후에 추적 상황을 확인해야 한다. 

 

git fetch --aa; git branch -vv

 

git fetch 명령을 실행하면 서버에는 존재하지만, 로컬에는 아직 없는 데이터를 받아와서 저장한다. 이 때 Working directory의 파일 내용은 변경되지 않고 그대로 남는다. 서버로부터 데이터를 가져와서 저장해두고 사용자가 Merge 하도록 준비만 해둔다 간단히 말하면 git pull 명령은 대부분 git fetch 명령을 실행하고 나서 자동으로 git merge 명령을 수행하는 것 뿐이다. Clone 이나 checkout 명령을 실행하여 추적 브랜치가 설정되면 git pull 명령은 서버로부터 데이터를 가져와서 현재 로컬 브랜치와 서버의 추적 브랜치를 Merge 한다. 일반적으로 fetch 와 merge 명령을 명시적으로 사용하는 것이 pull 명령으로 한번에 두 작업을 하는 것 보다 낫다. 

 

리모트 브랜치 삭제하기 

git push origin --delete iss72

 

git fetch --aa; git branch -vv

iss72 라는 브랜치가 local 에는 있으나, Remot에는 이미 사라진 경우 

 

Rebase

 

언제 사용하는가?

두 브랜치의 마지막 커밋 두 개 (C3, C4) 와 공통 조상 (C2) 를 사용하는 3-way Merge로 새로운 커밋 (C5)를 만들어 낸다.

 

C3에서 변경된 사항을 Patch로 만들고, 이를 다시 C4에 적용시키는 방법이 있다. Git 에서는 이런 방식을 rebase 라고 한다. 

git checkout experiment

git rebase master

실제로 일어나는 일을 설명하자면 일단 두 브랜치가 나뉘기 전인 공통 커밋으로 이동하고(C2) 나서 그 커밋부터 지금 checkout한 브랜치가 가리키는 커밋까지(C4) diff를 차례로 만들어 어딘가에 임시로 저장해 놓는다. Rebase 할 브랜치(Experiment) 가 합칠 브랜치 (master)가 가리키는 커밋을 가리키게 하고 아까 저장해 놓았던 병경 사항을 차례대로 적용한다. 

 

그리고 나서 master 브랜치를 Fast-forward 시킨다. 

git checkout master

git merge experiment

C4로 표히된 commit에서 내용은 merge 예제에서 살펴본 C5 커밋에서 내용과 같을 것이다. Merge 이든 Rebase 든 둘 다 합치는 관점에서는 서로 다를 게 없다. 하지만 Rebase가 좀 더 깨끗한 히스토리를 만든다. Rebase 한 브랜치의 log를 살펴보면 히스토리가 선형이다. 일을 병렬로 동시에 진행해도 Rebase 하고 나면 모든 작업이 차례대로 수행된 것처럼 보인다. 

 

Rebase는 보통 리모트 브랜치에 커밋을 깔끔하게 적용하고 싶을 때 사용한다. Rebase를 하든지, Merge를 하든지 최종 결과물은 같고 커밋 히스토리만 다르다는 것이 중요하다. 

Rebase의 경우는 브랜치의 변경사항을 순서대로 다른 브랜치에 적용하면서 합치고 Merge의 경우는 두 브랜치의 최종 결과만을 가지고 합친다. 

 

 

'git' 카테고리의 다른 글

신규 branch 생성  (0) 2021.05.03
git public key 생성  (0) 2021.03.26
Git 필수 명령어 요약  (0) 2021.02.16
[책] Pro Git 2판, review [5] - branch  (0) 2021.02.15
[책] Pro Git 2판, review [3]  (0) 2021.02.15