블로그 이미지
윤영식
Full Stacker, Application Architecter, KnowHow Dispenser and Bike Rider

Publication

Category

Recent Post

2013. 1. 16. 10:53 Git, GitHub/Git Lec02

Git 에서 한 브랜치에서 다른 브랜치로 합치는 방법은 Merge와 Rebase가 있다. Rebase 사용시 좋은 점과 사용하지 말아야 할 때에 대해서 알아보자 (ch 3.6)


1) Rebase 기초 

  - 일반적으로 3 way merge로 브랜치 합치기를 함    

    


  - Rebase는 한 브랜치에서 변경된 사항을 다른 브랜치에 적용한다 

    + Rebase할 브랜치를(B) checkout한 브랜치가 가르키는 커밋까지 diff하여 다른 내용을 임시로 저장해 놓음 (temp)

    + temp에 저장한 변경사항을 차례로 적용하여 Rebse될 브랜치(A)에 새로운 commit을 만든다 

    + Rebase될 브랜치(A)는 가장 최신 commit 개체가 되고 브랜치의 포인터는 fast-forward 된다 

    + 즉, Rebase는 기존 commit을 사용하는 것이 아니라 새로운 commit을 만들어 합치는 것이다

  -  Rebase가 merge 보다 좀 더 깔끔한 히스토리를 만든다. 일이 병렬로 하다 rebase 하면 선형적으로 된다 

  - 보통 리모트 브랜치에 커밋을 깔끔하게 적용하고 싶을 때 사용한다 (메인 프로젝트에 패치를 보낼 때)

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


2) Rebase 위험성 

  - 이미 공개 저장소에 Push 한 커밋을 Rebase 하지 마라 : 동료와 협업시 commit 객체 내용이 삭제되어 버린다 (p. 78)

  - 즉, 로컬에서 작업진행한 내 commit 개체만 Rebase하고 리모트에 있는 commit 개체의 rebase는 불허!!!

  - Push 하기 전에 정리하려고 Rebase하는 것은 괜찮다 


<사용법>

  - http://mobicon.tistory.com/165  : 리모트 저장소에서 pull하고 conflict 날 경우

  - http://mobicon.tistory.com/164  : 로컬 저장소에서 conflict 날 경우 

'Git, GitHub > Git Lec02' 카테고리의 다른 글

[Pro Git] 커밋 가이드라인  (0) 2013.01.25
[Pro Git] 협업 Workflow  (0) 2013.01.25
[Pro Git] Branch 사용하기  (0) 2013.01.16
[Pro Git] Git Alias 사용하기  (0) 2013.01.08
[Pro Git] Tag 사용하기  (0) 2013.01.08
posted by 윤영식
2013. 1. 14. 00:39 Git, GitHub

Remote 저장소인 GitHub과 Local 저장소의 commit 내역이 일치하지 않을 경우 rebase로 어떻게 해결하는지 알아보자. Local 저장소내에서 rebase를 사용하는 것과 약간의 차이점이 존재한다. (참조)


1. Remote 저장소 merge conflict 조건

  - GitHub에 이미 다른 Commit이 존재한다 (분홍색)

  - Local 저장소에 변경된 commit이 존재한다

  - git push 를 수행할 경우 merge conflict가 발생한다

  - 기존에 push후 conflict 발생시 pull 하고 문제 해결하고 다시 push 한다 (해결하기)

  



2. 이제 1)번의 경우 말고 fetch 와 rebase 사용

  - git fetch 를 통하여 local 저장소로 merge 하지 않고 origin/master의 별도 브랜치를 local 저장소로 복사하자 

    


  - git rebase를 수행한다. 이때 다음의 3단계로 진행이 된다. 

    + 브랜칭 된 이후의 master commit 내역을 temporary area로 이동시킨다-origin/master가 아니라- (초록색)

     


    + origin/master를 master 브랜치로 commit 한다. (분홍색)

       


    + temporary area에 있는 master commit 내역을 다시 master로 commit 한다. 

     



3. local과 remote의 같은 파일을 commit 하였을 때 rebase 하는 방법

  - master 브랜치에서 rebase하고 있음에 주의한다 

////////////////////////////////////////////////////////////////////////////

// remote 저장소와 commit 내역을 맞추고 확인해 보자 

$ git log --pretty=oneline

bbeb691d80512e17279764312f60416ebf28dd86 add content in rebase of local repo


// rebase.html 파일의 내용 


////////////////////////////////////////////////////////////////////////////

// 로컬에서도 rebase.html 파일을 변경하고 push를 시도하지만 reject 된다.

// 즉, remote 저장소의 rebase.html과 local 저장소의 rebase.html 내역이 틀리다.

$ git push

Username for 'https://github.com':

Password for 'https://ysyun@yuwin.co.kr@github.com':

To https://github.com/ysyun/pro_git.git

 ! [rejected]        master -> master (non-fast-forward)

error: failed to push some refs to 'https://github.com/ysyun/pro_git.git'

hint: Updates were rejected because a pushed branch tip is behind its remote

hint: counterpart. If you did not intend to push that branch, you may want to

hint: specify branches to push or set the 'push.default' configuration

hint: variable to 'current' or 'upstream' to push only the current branch.


////////////////////////////////////////////////////////////////////////////

// origin/master를 local 저장소로 가지고 온다. 

$ git fetch

remote: Counting objects: 5, done.

remote: Compressing objects: 100% (3/3), done.

remote: Total 3 (delta 1), reused 0 (delta 0)

Unpacking objects: 100% (3/3), done.

From https://github.com/ysyun/pro_git

   d895a7e..9274820  master     -> origin/master


////////////////////////////////////////////////////////////////////////////

// rebase를 위하여 master로 이동한다 

$ git branch

* (no branch)

  master


$ git checkout master

Warning: you are leaving 1 commit behind, not connected to

any of your branches:


  bbeb691 add content in rebase of local repo


If you want to keep them by creating a new branch, this may be a good time

to do so with:


 git branch new_branch_name bbeb691d80512e17279764312f60416ebf28dd86


Switched to branch 'master'

Your branch and 'origin/master' have diverged,

and have 1 and 3 different commits each, respectively.


$ git  branch

* master


////////////////////////////////////////////////////////////////////////////

// rebase를 수행한다. 

// rebase.html 파일 내역에서 conflict가 나온다고 메시지를 출력한다 

$ git rebase

First, rewinding head to replay your work on top of it...

Applying: updating rebase in local repo.

Using index info to reconstruct a base tree...

M       rebase.html

Falling back to patching base and 3-way merge...

Auto-merging rebase.html

CONFLICT (content): Merge conflict in rebase.html

Failed to merge in the changes.

Patch failed at 0001 updating rebase in local repo.


When you have resolved this problem run "git rebase --continue".

If you would prefer to skip this patch, instead run "git rebase --skip".

To check out the original branch and stop rebasing run "git rebase --abort".


$ git status

# Not currently on any branch.

# Unmerged paths:

#   (use "git reset HEAD <file>..." to unstage)

#   (use "git add/rm <file>..." as appropriate to mark resolution)

#

#       both modified:      rebase.html

#

no changes added to commit (use "git add" and/or "git commit -a")


////////////////////////////////////////////////////////////////////////////

// rebase.html 파일 내역을 보고 적절히 수정한다 

$ cat rebase.html

 this is rebase html file ok

<<<<<<< HEAD

     updating rebase in remote repo. again

     add content in remote repo.

=======

    updating rebase in local repo.

>>>>>>> updating rebase in local repo.


$ vi rebase.html

$ cat rebase.html

 this is rebase html file ok

     updating rebase in remote repo. again

     add content in remote repo.

    updating rebase in local repo.


////////////////////////////////////////////////////////////////////////////

// rebase.html 을 staging area로 add 한다. 

$ git add rebase.html


////////////////////////////////////////////////////////////////////////////

// rebase를 계속 진행한다 

$ git rebase --continue

Applying: updating rebase in local repo.


////////////////////////////////////////////////////////////////////////////

// commit log를 확인해 보면 rebase가 되어서 remote commit 내역이 local 저장소에 

// 복사되었다. 

$ git log --pretty=oneline

30d42e6785e441c3b515a4f4181dbfa051ad400a updating rebase in local repo.

9274820a9f62b2e08411ffb34d808508c7a74f93 add content in rebase of remote repo

d895a7e83d85d05f2c81585232f9c3e22426383a updating rebase again in remote repo

8c7c04b40d9fce0a1ae5a52b45b438fa14ea95e1 Update rebase.html


////////////////////////////////////////////////////////////////////////////

// 다시 push를 하면 정상적으로 remote 저장소로 push 가 된다 

$ git push

Username for 'https://github.com':

Password for 'https://ysyun@yuwin.co.kr@github.com':

Counting objects: 5, done.

Delta compression using up to 2 threads.

Compressing objects: 100% (3/3), done.

Writing objects: 100% (3/3), 323 bytes, done.

Total 3 (delta 2), reused 0 (delta 0)

To https://github.com/ysyun/pro_git.git

   9274820..30d42e6  master -> master


// remote에 local에서 직접 수정한 내역이 commit 됨 


// local repo(파란색, 30d42e6785)의 SHA 값이 가장 상위에 그 다음 remote repo 의 SHA(927480a9f...)가 밑에 있다. 


posted by 윤영식
2013. 1. 13. 22:00 Git, GitHub

git에서 merge conflict가 발생할 경우 좀 더 쉽게 하고 싶다면 rebase를 사용할 수 있다. rebase의 동작 순서와 언제 사용할지 알아보자. 


1) local rebase 명령 전제 조건

  - master로 부터 현재 commit 내용으로 신규 branch인 admin을 만든다

  - master로 새로운 commit 내용이 있고, 신규 branch(admin)도 새로운 commit이 존재한다 

  - admin 브랜치의 내역을 그대로 master 브랜치로 merge하지 않고 add 하고 싶을 경우 

  


  - git checkout admin : admin 브랜치로 checkout 한다 

  - git rebase master : master의 commit 내역을 admin 브랜치에 add 한다   

  


  - git checkout master : 다시 master로 돌아 온다

  - git merge admin : master에 admin을 merge 한다. 이럴 경우 admin 브랜치로 갈라진 이후 master의 신규 commit이 admin 브랜치에 들어 있으므로 fast-forward merge가 가능해 진다. 

////////////////////////////////////////////////////

// admin 브랜치를 신규로 만들고 checkout 하기 

$ git checkout -b admin

Switched to a new branch 'admin'


$ git branch

* admin

  master


////////////////////////////////////////////////////

// rebase.html 파일을 신규로 만들고 commit 2번 하기 

$ touch rebase.html

$ git add rebase.html

$ git commit -m "add rebase html"

[admin d375a11] add rebase html

 1 file changed, 1 insertion(+)

 create mode 100644 rebase.html


$ vi rebase.html  <- 내용 변경 

$ git commit -am "update rebase html"

[admin 22bbd02] update rebase html

 1 file changed, 1 insertion(+), 1 deletion(-)


////////////////////////////////////////////////////

// master 에서도 신규 파일을 생성하고 두번 commit 하기

$ git checkout master

Switched to branch 'master'


$ touch dowon.js

$ vi dowon.js

$ git add dowon.js

$ git commit -m "add dowon javascript file"

[master cc77217] add dowon javascript file

 1 file changed, 1 insertion(+)

 create mode 100644 dowon.js


$ vi dowon.js

$ git commit -am "add dowon javascript file"

[master 841c14f] add dowon javascript file

 1 file changed, 1 insertion(+), 1 deletion(-)


////////////////////////////////////////////////////

// admin 브랜치로 이동하여 master의 신규 commit 2 개를

// admin 브랜치로 복사하기 

$ git checkout admin

Switched to branch 'admin'


// admin 브랜치의 commit 내역 확인 

$ git log --pretty=oneline

22bbd02cf7c49a96efb5eb4d38768e67d0c120da update rebase html

d375a1105a24ccc69895ef74d041329bc947d204 add rebase html

f42a865365aa53a6071887237057f593b75d236a Merge branch 'master' of https://github.com/ysyun/pro_git

fbf93820f62f1bc1035f2ba38e941fcae6212fb9 change README.md

c917ae5f7787844b63826a460d82a998bad08a7f Update README.md


// admin 브랜치로 갈라진 이후 master에 추가된 commit 내역을 admin 브랜치로 복사하기 

$ git rebase master

First, rewinding head to replay your work on top of it...

Applying: add rebase html

Applying: update rebase html


// commit 내역 확인 

// 녹색 부분 : master의 commit 내역이 admin 브랜치로 복사되었다. 단, admin commit 내역 밑으로 복사됨 

$ git log --pretty=oneline

3166e4c833705ffc74295b8cc1465a9131b53ef9 update rebase html

d40464af367bdfddb6303feda754937e228e8d57 add rebase html

841c14fb69239bda408aee262e2aea09fb0b83ca add dowon javascript file

cc772174619fa2989c0b3728144f0b885c7faca8 add dowon javascript file

f42a865365aa53a6071887237057f593b75d236a Merge branch 'master' of https://github.com/ysyun/pro_git

fbf93820f62f1bc1035f2ba38e941fcae6212fb9 change README.md

c917ae5f7787844b63826a460d82a998bad08a7f Update README.md


////////////////////////////////////////////////////

// master 브랜치로 다시 이동하여 admin 브랜치와 merge

$ git checkout master

Switched to branch 'master'

Your branch is ahead of 'origin/master' by 2 commits.


// fast-forward merge를 수행했다. 

$ git merge admin

Updating 841c14f..3166e4c

Fast-forward

 rebase.html | 1 +

 1 file changed, 1 insertion(+)

 create mode 100644 rebase.html


$ git branch

  admin

* master


$ git log --pretty=oneline

3166e4c833705ffc74295b8cc1465a9131b53ef9 update rebase html

d40464af367bdfddb6303feda754937e228e8d57 add rebase html

841c14fb69239bda408aee262e2aea09fb0b83ca add dowon javascript file

cc772174619fa2989c0b3728144f0b885c7faca8 add dowon javascript file

f42a865365aa53a6071887237057f593b75d236a Merge branch 'master' of https://github.com/ysyun/pro_git

fbf93820f62f1bc1035f2ba38e941fcae6212fb9 change README.md

c917ae5f7787844b63826a460d82a998bad08a7f Update README.md


  - Local 저장소에서의 rebase 명령 :master 브랜치로 분기된 이후 신규 branch에서 master 브랜치의 commit 내역을 복사 하고 싶을 경우 사용한다  

posted by 윤영식
prev 1 next