'Branch'에 해당하는 글 6건

git branch & merge

Tool/Git 2017. 2. 2. 21:36

브랜치 작업을 하거나 충돌날 때마다 도움을 요청하는 중생들을 줄이고자, git 세미나를 준비하면서 정리한 내용들이다.


* 목표

- 쫄지말고 브랜치(branch) 사용하기.

- 충돌(conflict)이 나더라도 쫄지 않기.


(기본적인 push, pull 정도는 할 줄 안다는 가정하에 불필요한 내용은 생략한다.)



1. 우리는 이럴 때 branch 를 사용한다.


다음 케이스를 보자.

master 브랜치 하나만 가지고 있으면서 이 작업물로 운영서버에 배포를 한다.

이 프로젝트에 [기능] 추가 요청이 들어왔고 팀원들과 협업이 필요하다.

협업이 필요하기 때문에 원격 저장소에 소스를 공유해야 한다.

기능 추가 작업중에 심각한 [버그] 를 발견하여 수정하고 다시 배포를 해야 한다면, 아직 완료되지 않은 [기능] 추가 작업이 같이 배포되어 버린다.

이를 방지하기 위해 필요한 것이 바로 branch 이다.


2. branch 란?


현재 브랜치(예를 들어 master) 에서 해오던 작업은 branch 를 추가하는 순간 별도의 공간에서 추가적으로 개발할 수 있다.

branch 는 이름 그대로 나뭇가지 처럼 작업을 분리시키는 것이다.

master iss53 이라는 브랜치가 있다면 master 에서 작업하는 내용은 iss53 에 영향을 미치지 않으며, iss53 에서 작업하는 내용 역시 master 에 영향을 미치지 않는다.


위 케이스에서 [기능] 추가 작업시 iss53 이라는 브랜치를 새로 생성해서 작업한다면,

또 [버그] 수정 역시 hotfix 라는 브랜치를 새로 생성해서 작업한다면, master 에서 bugfix 를 merge 하고 배포하면 끝이다.

다시 iss53 브랜치를 checkout 하여 [기능] 추가 작업을 계속 하면 된다.


3. merge 란?


branch 가 작업을 분리시키는 명령이라면, 반대로 분리한 작업을 다시 합쳐주는 명령이 바로 merge 이다.

우리는 이미 pull 을 수도 없이 사용하면서 자동 merge 를 사용해 왔다. (pull 명령은 fetch + merge 를 한번에 실행해 주는 명령이다.)

master 브랜치에서 git merge hotfix 명령으로 수정된 버그를 해결하고, git merge testing 명령으로 기능까지 추가한다면,

master 브랜치는 최신 상태의 소스가 되고 배포할 준비가 된다.


branch 와 merge 는 이게 끝이다.


이제 실제로 위 케이스를 실행해 보자.


최종적으로 위와 유사한 결과를 도출할 수 있어야 한다.


[기능] 추가 요청에 대한 iss53 이라는 브랜치 생성.


$ git checkout -b iss53
cs


위 명령은 아래 두개의 명령을 한번해 실행해 줌.


$ git branch iss53
$ git checkout iss53
cs


작업 및 커밋진행


$ git commit -m 'description'
cs


도중에 [버그] 수정 요청에 대한 hotfix 라는 브랜치 생성.

master 에 기반한 브랜치를 생성해야 하므로 master 브랜치를 이동하여 브랜치를 생성.


$ git checkout master
$ git checkout -b hotfix
cs


버그를 수정한 후 커밋을 진행.


$ git commit -m 'description'
cs


수정한 버그를 master 에 합치기 위해 master 브랜치로 이동하여 merge 실행


$ git checkout master
$ git merge hotfix
cs


master 브랜치는 hotfix 브랜치를 생성한 이후에 커밋을 진행하고 있지 않았으므로 단순히 브랜치 포인터만 hotfix 의 최신 커밋으로 이동함. (fast-forward 방식)

다시 iss53 으로 이동하여 [기능] 추가 작업 마무리 하고 커밋하고 master 와 합치기 위해 merge 실행.


$ git checkout iss53
$ git commit -m 'description'
$ git checkout master
$ git merge iss53
cs


master 브랜치는 iss53 브랜치를 생성한(조상) 이후에 커밋이 진행되었으므로 그림처럼 두개의 브랜치가 합쳐지는 3-way merge 처리.

3-way merge 의 결과로 별도의 커밋이 만들어진다.


추가적으로 브랜치를 변경할 때는 기존의 staged 를 깨끗하게 정리하는 것이 좋다. 

commit 이나 staged 를 사용하여 충돌을 체크 및 예방한다.




WRITTEN BY
손가락귀신
정신 못차리면, 벌 받는다.

,

merge scenario

Tool/Git 2013. 3. 24. 00:17

Fast-forward

 

  1. A branch 에서 B branch 생성
  2. checkout B
  3. B branch commit
  4. checkout A
  5. A merge B

 

이 경우 A branch로부터 생성된 B branch가 commit 을 실행하면서 A branch 보다 앞서갑니다.
A branch 는 변경된 것이 없습니다.
A branch 가 B branch 를 병합하면서 A branch 의 포인터(HEAD)는 B branch 로 이동하게 됩니다.
합쳐진다기 보다 포인터(HEAD)만 B branch 의 최근 commit 위치로 이동하는 것입니다.
이 때 Fast-forward 방식의 merge 라고 메시지가 나타납니다.
Fast-forward 란 병합(merge)할 branch 의 최근 commit 이 현재 branch 보다 앞서 있다는 뜻입니다.

 

 

이번에는 A branch도 commit해 보겠습니다.

 

 

 

3-way Merge

 

  1. A branch 에서 B branch 생성
  2. checkout B
  3. B branch commit
  4. checkout A
  5. A branch commit
  6. A merge B

 

이 경우 A, B 모두 branch 생성 후에 변경점(commit)이 생성 되었기 때문에 포인터(HEAD)의 이동만으로는 병합될 수 없습니다.
이 경우에는 병합시 A가 자동으로 하나의 commit 을 더 생성하며(3-way Merge) B와의 내용물을 병합하게 됩니다.
이 때 recursive 방식의 merge 라고 메시지가 나타납니다.
Fast-forward 방식의 경우는 A와 B의 포인터가 모두 마지막 commit을 가리키지만,
recursive 방식의 경우 B는 여전히 자신의 마지막 commit을 가리키고 있고,
A는 B와 병합하여 새로 생성된 마지막 commit을 가리키게 됩니다.
새로운 commit이 생성되었으므로 자동으로 편집기가 열리며 자동으로 commit 메시지가 담겨 있습니다.
Merge branch 'B' into A

 

 


WRITTEN BY
손가락귀신
정신 못차리면, 벌 받는다.

,

git branch

Tool/Git 2013. 3. 23. 00:30

master branch 에서 HEAD 상태에 놓은 작업물들을 원격 저장소에 적용하기 전에,
branch 란 것에 대해서 조금 더 알아보겠습니다.

 

지금까지는 첫번째 commit 후에 master branch가 생성되었고, 현재도 master에서 작업 중입니다.
이 쯤에서 기존의 파일을 디버깅한다던지, 기능을 추가한다던지 하는 이슈가 생겼을 때,
현재 작업해 놓은 master 에서 가지(branch)를 쳐서 새로운 branch를 생성하여,
기존 master는 보존하고, 새로운 branch에서 이슈를 해결할 수 있습니다.
이렇게 한 개 이상의 branch가 생성되었을 때 각각의 branch에서 독립적으로 작업을 진행할 수 있으며,
작업을 완료하고 나서는 새로 생성한 branch와 master를 병합(merge)할 수 있습니다.

 

 

 

git branch 명령은 현재 보유중인 branch 들을 모두 출력하며,
현재 작업 중인 branch를 (*) 마크로 표시합니다.
새로운 branch를 생성하려면 git branch <new branch> 라고 명령합니다.

 

지금까지 작업한 master에서 commit 로그를 살펴보겠습니다.

 

$ git branch
* master
$ git log
commit 3e9f5ffc4fea440b2f23830e395797a5c571a99b
Author: ggamzzak <ggamzzak@test.com>
Date:   Tue Mar 19 11:15:12 2013 +0900

 

    modify file1 2nd

 

commit 449512a3e4e10093e0631af0733b493147c3eee2
Author: ggamzzak <ggamzzak@test.com>
Date:   Tue Mar 19 11:09:09 2013 +0900

 

    modify file1

 

commit 28713cea1fe5722c24caaa605e6810caf094d955
Author: ggamzzak <ggamzzak@test.com>
Date:   Tue Mar 19 10:35:55 2013 +0900

 

    first file added

 

 

이번에는 testing 이란 새로운 branch를 만들고,
포인트 개념의 HEAD가 testing 을 가리키도록 checkout 명령을 사용합니다.

git branch B, git checkout B 의 명령을 -b(branch) 옵션을 사용하여 git checkout -b B 라고 한번에 명령할 수 있습니다.
병합 후 필요없는 branch는 -d(delete) 옵션으로 삭제합니다. git branch -d B

 

$ git branch testing
$ git branch
* master
  testing

$ git checkout testing
Switched to branch 'testing'
$ git branch
  master
* testing

$ git log
commit 3e9f5ffc4fea440b2f23830e395797a5c571a99b
Author: ggamzzak <ggamzzak@test.com>
Date:   Tue Mar 19 11:15:12 2013 +0900

 

    modify file1 2nd

 

commit 449512a3e4e10093e0631af0733b493147c3eee2
Author: ggamzzak <ggamzzak@test.com>
Date:   Tue Mar 19 11:09:09 2013 +0900

 

    modify file1

 

commit 28713cea1fe5722c24caaa605e6810caf094d955
Author: ggamzzak <ggamzzak@test.com>
Date:   Tue Mar 19 10:35:55 2013 +0900

 

    first file added

 

(*)은 현재 작업 중인 branch라고 했습니다.
checkout 명령으로 작업 중인 branch를 변경할 수 있었습니다.
새로 생성된 testing의 log를 보면 master의 commit 히스토리가 그대로 복제되었습니다.
이제 이 두 branch는 독립적으로 작업할 수 있습니다.
master에서 commit을 해도 testing에 적용되지 않으며,
testing에서 commit을 해도 master에는 적용되지 않습니다.

 

이렇게 testing 에서 이슈를 완료하면 merge 명령을 사용하여 master와 병합하고,
필요에 따라 testing 을 삭제하면 됩니다.

 

 

 

위의 예와 비슷한 그림입니다.
master 브런치에서 세번의 commit을 실행했고,
testing 브런치를 생성한 뒤에 testing 브런치에서 한번의 commit 을 실행한 것을 나타낸 그림입니다.

 

checkout 명령을 사용해서 branch 간 이동할 때 유의할 점은, 커밋 직전(Staged)의 파일이 이동할 branch 파일과 충돌한다면 branch를 변경할 수 없습니다. 브랜치를 변경할 때에는 status로 확인하여 Working Directory를 정리하는 것이 좋습니다.

 

$ git checkout master
error: Your local changes to the following files would be overwritten by checkout:
        file1.txt
Please, commit your changes or stash them before you can switch branches.
Aborting


WRITTEN BY
손가락귀신
정신 못차리면, 벌 받는다.

,

git commit

Tool/Git 2013. 3. 22. 01:09

4. commit 후의 status

 

상태(status) 확인 후 원하는 작업물이 Staged 상태가 되었는지 확인이 되었으면,
commit 명령을 사용하여 작업물을 Staged -> HEAD 상태로 놓습니다.
-m(message) 옵션을 사용하여 인라인 메시지를 작성할 수 있습니다.

 

$ git commit -m 'first file added'
[master (root-commit) 28713ce] first file added
 1 file changed, 1 insertion(+)
 create mode 100644 file1.txt
$ git branch
* master
$ git status
# On branch master
nothing to commit, working directory clean

 

master branch에 커밋이 되었고 작업 현황을 보여줍니다.
그리고 현재의 branch가 master로 출력되었습니다. 첫번째 커밋과 동시에 master branch가 생성이 되었습니다.
commit 후에 status를 확인해 보니, commit 할 것이 아무것도 없다는 메시지가 출력됩니다.

 

 

 

5. tracked file 수정

 

commit 할 것이 없는 상태에서 다시 파일을 생성하던지, 기존 파일을 수정하면 다시 상태가 바뀌게 됩니다.
파일 생성은 실행해 보았으니 tracked(버전 관리 대상)된 기존 파일을 수정해 보겠습니다.

 

$ cat >> file1.txt
test
$ git status
# On branch master
# Changes not staged for commit:
#   (use "git add <file>..." to update what will be committed)
#   (use "git checkout -- <file>..." to discard changes in working directory)
#
#       modified:   file1.txt
#
no changes added to commit (use "git add" and/or "git commit -a")

 

수정할 파일을 HEAD 단계에 놓으려면 처음처럼 add 명령으로 Staged 상태에 놓은 후 commit 하면 됩니다.
수정한 파일을 add 명령으로 Staged 상태에 놓은 뒤 커밋 전에 다시 그 파일을 수정하면 어떻게 될까요?
그 상태로 commit을 한다면 Staged 상태였던 파일의 내용이 그대로 HEAD로 올라가고,
두 번째 수정한 내용은 아무 곳에도 반영되지 않습니다.
add 후에 파일을 다시 수정했다면 add 명령을 다시 실행하여 Stage area에 반영해야 합니다.
tracked 파일에 한해서 commit -a 옵션을 사용하면 git add, git commit 을 한 번에 실행해 줍니다.

 

 

지금까지는 모두 로컬 저장소(Local Repository) 안에서의 작업이었습니다.
아직 원격 저장소(Remote Repository)는 변한게 없다는 사실...


WRITTEN BY
손가락귀신
정신 못차리면, 벌 받는다.

,

git init

Tool/Git 2013. 3. 20. 00:32

clone 이란 명령으로 원격 저장소의 모든 소스를 로컬 저장소로 복제할 수 있었습니다.
그 방법 외에도 로컬 저장소를 생성하는 방법으로 init 명령을 사용할 수 있습니다.
어느 디렉토리에서든 init 명령 하나로 해당 디렉토리에 .git 디렉토리를 생성하고 로컬 저장소가 될 수 있습니다.

 

$ pwd
/home/oops4u/dev2
$ git init
Initialized empty Git repository in /home/oops4u/dev2/.git/

 

init 란 명령으로 간단하게 로컬 저장소가 생성되었습니다.
이 로컬 저장소에 이미 기존 작업물이 존재하거나 새로 작업물을 만들어서 원격 저장소에 보내려 한다면,
우선적으로 로컬 저장소 상에서 버전 관리에 대한 준비를 마쳐야 합니다.(commit)

 

 

* git 의 로컬 저장소 구조는 다음과 같습니다.

 

 

  1. Working directory : 실제 파일 디렉토리(unstaging area)
  2. Index : 준비 영역(staging area)
  3. HEAD : 최종 확정본(commit)

 

Working directory 에서 버전 관리 하려는 파일들을 add 명령을 사용하여 Index 영역에 등록시키고,
commit 명령으로 HEAD 상태로 만들면 원격 저장소로 보낼 수 있는 준비가 완료된 것입니다.

 

빈 디렉토리에서 하나의 파일을 생성하고 commit하여 HEAD에 반영하기 까지의 상태(status)를 순차적으로 확인해 보겠습니다.

 

 

 

1. init 후 status

 

$ git init
Initialized empty Git repository in /home/oops4u/dev3/.git/
$ git branch
$ git status
# On branch master
#
# Initial commit
#
nothing to commit (create/copy files and use "git add" to track)

 

branch 명령은 현재 작업중인 branch를 나타내는데 아직 branch가 생성되지 않았습니다.
branch 란 것은 말 그대로 나뭇가지처럼 프로젝트를 분리해서 작업할 수 있게 합니다.
기본적으로 master란 branch가 생성되며, 언제 생성되는지는 두고 보겠습니다.

 

status 명령은 현재 프로젝트의 버전 관리 상태를 나타내 주는 것입니다.
현재 branch(master)를 나타내고 있고, commit 할 수 있는 것이 아무것도 없다고 나타내고 있습니다.

 

 

2. file 생성 후 status

 

$ cat > file1.php
test
$ git branch
$ git status
# On branch master
#
# Initial commit
#
# Untracked files:
#   (use "git add <file>..." to include in what will be committed)
#
#       file1.php
nothing added to commit but untracked files present (use "git add" to track)

 

file1.php란 파일을 생성했고 branch는 여전히 생성되지 않았습니다.
status에서 Untracked 는 버전 관리 대상이 아니라는 뜻입니다. tracked 는 반대로 버전 관리 대상이란 뜻이구요.
버전 관리 하려면 git add 명령으로 추가하라고 친절히 나타나 있으며, 여전히 commit 할 수 있는 것은 없다고 나타납니다.
앞으로 계속해서 사용될 단어입니다.
tracked, untracked, modified, unmodified...

 


WRITTEN BY
손가락귀신
정신 못차리면, 벌 받는다.

,