tools & libs/git

Eclipse에서의 Git 활용 - 5 : branch

  • -

branch

이번 시리즈의 처음 포스트에서 밝혔듯이 branch는 git의 매우 중요한 장점이다.

실제로 우리가 개발하는 SW는 단순히 개발 --> 사용의 단계를 거치지 않고 디버깅, 개선 작업, 배포 등 매우 다양한 과정을 거친다.  이런 단계들은 순서대로 발생하지 않으며 병렬로 진행되므로 서로에게 영향을 주어서는 안 된다. 

이런 경우 branch를 사용하면 리소스들은 각각의 branch에서 관리되기 때문에 서로 간의 충돌 없이 작업할 수 있게 된다.

또한 여러 팀원과의 협업에서도 팀원 간의 독립적인 작업 공간을 확보하기 위해 branch는 필요하다

 

branch 생성과 사용

 

branch 생성

기존의 master branch는 코드를 통합해서 관리하는 역할을 하고 두 명의 개발자를 의미하는 dev1, dev2 branch를 생성해보자.

[Team] -> [Switch To] -> [New Branch]로 dev1, dev2 branch를 생성할 수 있다.

branch name에 dev1을 입력하고 [Finish]를 클릭하면 branch가 생성된다. 특정 branch를 사용하기 위해서는 checkout 명령을 사용하는데 하단의 [Check out new branch]를 선택하면 branch 생성과 동시에 해당 branch를 사용하게 된다.

이때 프로젝트를 보면 master에서 dev1으로 branch 정보가 바뀐 것을 알 수 있다. 동일한 방법으로 dev2 branch도 생성해 보자.

현재 상태는 dev1, dev2, master가 모두 동일한 버전을 참조하고 있고 현재 dev2를 사용하고 있음(굵은 글씨)을 알 수 있다.

전체 branch 가 다 보이지 않을 때는 Ref Filters 메뉴를 이용하여 refs/heads/** 가 필터에 추가되도록 하자.(클릭하면 토글 됨)

 

command line

더보기

command line에서 branch를 만들기 위해서는 git branch <branch_name>을 사용한다. 위의 예처럼 생성한 branch를 생성 후 바로 checkout 까지 하기 위해서는 git checkout -b <branch_name>을 사용한다.

❯ git checkout -b dev1
Switched to a new branch 'dev1'

이미 생성된 branch로 변경만 하는 경우는 checkout 명령만 사용하면 된다.

❯ git branch dev2
❯ git checkout dev2
Switched to branch 'dev2'

 

branch 별 작업

dev2 branch가 선택된 상태에서 코드를 수정하고 commit 해보자.

package gittest;

public class Test {
    String first = "first";
    String second = "second";
    String third = "third";
    String branch = "dev2";
}

이제 dev2의 버전이 하나 더 높아졌음을 알 수 있다.

이 상태에서 [Team] -> [Switch To] -> [dev1]을 선택해 보자. dev1은 third commit을 참조하고 있기 때문에 Test 클래스는 third의 내용까지만 가지고 있게 된다.

dev1 branch에서 다시 코드를 수정하고 commit을 수행해 보자.

package gittest;

public class Test {
    String first = "first";
    String second = "second";
    String third = "third";
    String branch = "dev1";
}

드디어 나뭇가지처럼 트리가 분기되는 것을 확인할 수 있다.

이처럼 branch는 각각 독립된 버전으로 리소스를 관리할 수 있게 한다.

 

merge를 통한 branch 통합

dev1과 dev2가 개별 작업을 마무리하고 master branch로 통합시켜 보자. 이때는 merge 명령을 사용한다.

먼저 통합본을 가질 master branch로 이동해 보자. 현재 가장 낮은 버전의 리소스를 참조하고 있다.

이제 [Team]-[Merge]를 선택 후 통합할 branch인 dev1을 선택한다.

더보기

dev1과 dev2가 있을 때 dev1이 dev2의 최신 커밋을 포함하고 있는 상태에서 Fast Forward 병합이 가능하다. Fast Forward 병합 시 단지 dev2를 dev1의 branch pointer까지 전진시켜 같은 commit을 참조하게 할 수 있고(옵션 1 - 기본) 새로운 merge commit을 만들 수도 있다.(옵션 2) 만약 command line에서 처리한다면 --no-ff 옵션을 추가하면 된다.

 

이제 Test.java를 살펴보면 dev1에서 작업했던 내용이 잘 반영되어 있음을 알 수 있다. 신기하게도 master의 Test.java에 dev1 개발자가 작업한 String branch="dev1"이라는 부분이 통합되어 있다.

package gittest;

public class Test {
    String first = "first";
    String second = "second";
    String third = "third";
    String branch = "dev1";
}

물론 history를 살펴보면 dev와 같은 commit을 master가 참조하고 있다.

 

command line

더보기

command line에서 병합을 처리하기 위해서는 git merge <병합할 branch>를 사용한다.

❯ git merge master
Updating 26da322..52a5f82
Fast-forward
 src/gittest/Test.java | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

 

conflict 상황과 해결

이제 dev2까지 통합시켜 보자.

그런데 여기서 잠깐 고민해 볼 내용이 있다.  master에서 dev1을 merge 할 때 dev1에 있던 String branch = "dev1"이라는 부분이 master의 Test.java에 통합되는 것을 확인했다.  그런데 dev2의 Test.java에는 동일한 위치에 String branch="dev2"라고 작성되어 있다.

즉 동일한 위치에서 다른 내용이 있는 것이다. 과연 git은 이 코드를 어떻게 통합할까?

dev2와의 merge를 진행해 보면 소위 충돌(conflict)이 발생한다.

conflict 상황은 코드를 병합하는 과정에서 어떤 코드가 사용돼야 하는지 git을 결정하지 못하기 때문에 사용자에게 결정을 요청하는 상황이다. 

Test.java를 살펴보면 어디에서 문제가 발생해서 통합에 실패했는지 잘 표현해 준다.

package gittest;

public class Test {
    String first = "first";
    String second = "second";
    String third = "third";
<<<<<<< HEAD                         : 현재 branch의 head가 가지는 내용
    String branch = "dev1";
=======                              : 통합될 코드가 가지는 내용
    String branch = "dev2";
>>>>>>> refs/heads/dev2
}

즉 현재 head가 가지고 있는 내용과 dev2의 head가 가지고 있는 내용이 충돌하는데 어떤 코드를 사용할 것인지 묻는 것이다. 이런 경우는 dev1 개발자와 dev2 개발자가 상의하여 올바른 코드를 결정하고 그 코드로 반영해 주면 된다.

아래와 같이 코드를 변경하고 다시 commit 해주자.

package gittest;

public class Test {
    String first = "first";
    String second = "second";
    String third = "third";

    String branch = "dev1 & dev2";
}

commit 과정에서는 어떤 branch를 통합하다가 어떤 리소스에서 충돌이 발생했는지가 자동으로 commit message에 적용된다.

이제 git history를 살펴보면 master가 가장 윗자리를 차지하고 있다.

비로소 두 개발자의 작업이 master로 잘 통합되었다.

 

checkout

이제 통합이 완료되었고 다시 dev1과 dev2 branch로 이동해 보자.

branch를 변경할 때 [Team] -> [Switch To] 메뉴 외에 history view에서 대상 branch를 선택 후 context menu에서 [checkout]을 선택해도 동일한 결과를 얻는다.

 

다시 각각의 작업 진행

이제 master의 Test가 변경되었고 다시 dev1과 dev2는 master에 적용된 최종 버전을 이용해서 각자의 작업을 이어나가면 된다. 

가장 일반적인 방법은 각각의 sub branch로 checkout 한 후 거꾸로 master branch를 merge 하는 일이다.

또는 dev1으로 checkout 한 후 master의 commit으로 reset 처리해 주자.

dev2역시 동일한 절차를 가장 최신의 commit으로 변경해 보자.

 

branch 더 배워보기

여기까지 branch에 대한 개념을 배웠다면 branch를 사용하는데 큰 문제가 없다.

좀 더 git에 대해 연습해보고 싶다면 Learn Git Branching 를 이용해 보자.

 

 

Learn Git Branching

An interactive Git visualization tool to educate and challenge!

learngitbranching.js.org

 

Contents

포스팅 주소를 복사했습니다

이 글이 도움이 되었다면 공감 부탁드립니다.