Upload
chanwoo-jeong
View
1.453
Download
1
Embed Size (px)
Citation preview
Advanced GITMerge, Rebase, etc..
정찬우 (@enghqii)GDG SSU
DISCLAIMER
여기서 설명하는 규칙 , 방법은제가 소프트웨어 마에스트로 1 차 프로젝트에서 썼던 것들 입니다 .
무조건적으로 받아 들이실 필요는 없고 , 각자 하실 프로젝트의 규칙 , 방법을 정할때 참고해주시면 좋겠네요 .
Speaker
• 정찬우 (@enghqii)• 숭실대학교 컴퓨터 학부 12 학번• GDG SSU• 소프트웨어 마에스트로 6 기 멘티
게임도 만들고 , 학교 공부도 하고 , 안드로이드도 좀 만지다가 , 스크립트 언어 좀 만들어 보다가… 다시 게임 만듭니다 .
Topic
커밋 병합하기커밋 뜯어 고치기
I suppose that you know …
커밋을 어떻게 하는지 , staging 은 어떻게 하는지 , 브랜치를 어떻게 만드는지 , 나눠진 브랜치를 어떻게 병합하는지 , 원격 브랜치와 로컬 브랜치가 어떻게 진행 되는지 , 코드가 어떻게 / 언제 충돌 나는지 , 충돌난 코드를 어떻게 해결하는지 , 남들이랑 작업하면서 프로젝트가 어떻게 망가지는지 , Pull-Request 가 뭔지 , Pull-Request 를 어떻게 하는지 , 등등…
다른 사람이랑 git 으로 프로젝트를 해봤다고 가정합니다 .
1. Commits
What are commits?
얘는 Kermit
Commit
• ‘git commit’ 하면 생기는 동그라미• 변경점을 가지고 있다• 스냅샷• 기본적인 단위
• Parent 를 가리키는 레퍼런스를 가진다• SHA 해쉬 ID 를 가진다• 절대 지워지지 않는다
47fd8aa
Branch
• 커밋을 가리키는 레퍼런스 mas-ter
HEAD
현재 브랜치 ( 또는 커밋 ) 를 가리킨다HEAD 가 바뀌면 작업공간도 바뀜
HEAD mas-ter
Structure of commits
A B C D
E F
master
chan-woo/
feature
HGsome-body/
feature
^ & ~
• 부모 커밋을 가리키는 연산자• ^ (caret) : 한 세대 앞을 가리키는 연산• HEAD^, HEAD^^, HEAD^^^ …
• ~n (tilde) : n 세대 앞을 가리키는 연산• HEAD~1, HEAD~2, HEAD~3 …
^ & ~
B DCA HEAD
HEAD~1,HEAD^
HEAD~2, HEAD^^
HEAD~3,HEAD^^^
^ & ~
B D
E
CA HEAD
HEAD~1,HEAD^
HEAD~2, HEAD~1^1HEAD~3
HEAD~2, HEAD~1^2
A commit must be …
• 적절한 크기의 하나의 작업만 해야 합니다 잠수함 패치 하면 안됨
• 컴파일 가능해야 합니다 , 빌드 가능해야 합니다 커밋 하나가 완벽해야 합니다
• 커밋 메시지가 잘 쓰여져 있어야 합니다 . 생판 모르는 사람이 ( 미래의 내가 ) 봐도 이해 가능해야
Completeness – Unit Test
• 테스트 결과로 판단가능• 컴파일 , 빌드 되는지• 기존 기능이 여전히 잘 동작하는지
Completeness - CI
• push, pull-request 할때 마다 자동 빌드• ‘ 어 ? 내 머신에선 됐는데 ?’
• 빌드 머신에서 되는지 판단 가능
Commit Message
Tag1: Tag2: Topic sentence
Body …… 50chars
Commit Message
Commit Message
2. Merge
git merge <branch>
병합을 하는 가장 기본적인 명령어( 이름도 merge)
git merge chanwoo/feature
A B C D
E F
master
chan-woo/
featuremaster 에서 chanwoo/feature 를 병합 할껍니다 . (HEAD 는 master)
$ git merge chanwoo/feature
git merge chanwoo/feature
A B C
E
G
F
D
Merge Commit 이 생깁니다 .
git merge chanwoo/feature
A B C
E master
chan-woo/
feature
G
F
D
Merge Commit 이 생깁니다 .
Fast Forward merge
‘ 앞으로 진행한’ 커밋들을 따라잡는 merge.
Merge commit 을 만들어내지 않음 .
git merge chanwoo/feature - FFWD
A B C Dchan-woo/
feature
master
master 에서 chanwoo/feature 를 병합(HEAD 는 master)
git merge chanwoo/feature - FFWD
A B C Dchan-woo/
feature
master
별거 없음 , 끝 .
많이 만들지 않는 것이 좋습니다 .왜 ?
Merge commit
Too many merge commits….
m
m
m
M
m
m
m
m
Too many merge commits….
이런 식으로 많아질 수 있습니다 .
보기에 좋지 않음 .
I don’t want to make merge commits
변경점이 존재하는 한
‘git merge’ 할 때 merge commit 이 생기지 않을 수 없다 .
Merge commit 만들기 싫은데 ?
그래서 준비했습니다 .
3. Rebase
git rebase <branch>
커밋들을 병합하는 또 다른 방법Base 를 다시 정합니다
Rebase
A B C D
E F
master
chan-woo/
feature
Rebase
A B C D
E F
master
chan-woo/
feature
In fact,
이런식으로 base 를 다시 정합니다근데 사실 저렇게 진행되진 않음
git rebase master
A B C D
E F
master
chan-woo/
featurechanwoo/feature 에서 master 를 병합할껍니다 . (HEAD 는 chanwoo/feature)
$ git rebase master
git rebase master
A B C D
E F
master
chan-woo/
feature
git rebase master
A B C D
E F
master
chan-woo/
feature
E’ F’
git rebase master
A B C D
E F
master
chan-woo/
feature
E’ F’
Has upstream?
만약 chanwoo/feature 의 upstream 이 존재한다면 ?
그냥 push 했을경우 reject 당함 ( 충돌나니까 )
현재 이력을 강제로 올려야 합니다 .
$ git push --force
# Be very careful with this command!
Before Rebasing
A B C D
E F
master
chan-woo/
featureorigin/chan-woo
/feature
After Rebasing
A B C D
E F
master
chan-woo/
featureE’ F’
origin/chan-woo
/feature
git push --force
A B C D
E F
master
chan-woo/
featureE’ F’
origin/chan-woo
/feature
Merge vs. Rebase
• Merge• 장점
• 이전 커밋들을 들쑤지진 않음 , ( 이전 커밋들이 ) 잘못될 가능성이 없음 .
• 단점• 다른 브랜치들이 매우 활발하다면 그 때문에 머지 커밋이 많이 발생할 수 있고 , 때문에 커밋 로그들이 지저분해 보일 수 있음 .
Merge vs. Rebase
• Rebase• 장점
• 프로젝트 히스토리가 훨씬 깔끔해질 수 있음 .• 선형적인 커밋 구조를 만들 수 있음 .
• 단점• 이전 커밋들을 들쑤시고 다니기 때문에 , 충돌이 발생하면 merge commit 을 만드는 방법보다 해결이 귀찮음 .• 원격의 , 남이 건드릴 수 있는 브랜치 (public branch) 는 절대 리베이스 하면 안됨 .
Rebasing public remote branch
A B C D
E F
master
chan-woo/
feature
Rebasing public remote branch
A
B C D
E F
master
chan-woo/
feature
B’ C’ D’
Rebasing public remote branch
A
B C D
E F
master
chan-woo/
feature
B’ C’ D’
B != B’B 와 B’ 는 다른 커밋
chanwoo/feature 에서 master 로 rebase 하면 B 도 쌓아 올린다 .
만약 B 같은 커밋이 여러개라면 ?다른 개발자들도 B 에서 브랜치를 쳤다면 ?
C, D 에서도 다른 개발자들이 브랜치를 쳤다면 ?
이런 상황을 전문용어로 개판이라고 한다 .
원격의 , 남이 건드릴 수 있는 브랜치는 절대 리베이스 하면 안됨 !
Discuss with your colleagues
Merge 를 해도 되고 Rebase 를 해도 됩니다 .어떤 방법으로 커밋들을 병합할지는
팀원들과 상의하세요( 아니면 PM 이 까라는대로 까야지 )
Conflict!
• $ git rebase --continue• $ git rebase --skip• $ git rebase --abort
아직 rebase 가 끝난게 아닙니다 .
git rebase --continue
A B C D
E F
master
chan-woo/
feature
E’ F’
F’ 를 쌓아 올릴때Conflict
git rebase --continue
A B C D
E F
master
chan-woo/
feature
E’ F’--continue
Resolve 하고 난 후 ,--continue
git rebase --skip
• 충돌난 상황에서 , 현재 커밋을 쌓아올리길 포기하고 건너뜁니다 .• 잘 안씀 , 커밋 하나하나가 중요하다면 .
• 종종 resolve 다 하고 보니 git add 할게 없을때 사용함 .• sourcetree 의 ‘ resolve with theirs/mine’ 만 사용할때 발생할 수 있음 .
git rebase --abort
• 현재 rebase 세션을 포기하고 아예 없던일로 합니다 .
쌓아올리는 커밋을 하나하나 resolve 하며 --continue 한 두번 하다가 나중에 화나서 --abort 할때 주로 사용함 .
git reset ORIG_HEAD
rebase 를 성공적으로 마치고 난 직후 , ‘ 아 이 리베이스 하면 안됐는데’ 라는 생각이 들때 사용함
HEAD 를 rebase 직전의 커밋을 가리키게 해 준다 .
뭐 이것저것 만졌으면 reflog 찾아봐야지 ..
4. Fix commits
Too many commits
A I
B
C
D
E
F
G
H
Reduce
AB+C+D+
E+F+G+H+
I
똑같은 목적을 가진 커밋들을 한곳에 몰아넣자
git commit --amend
• 마지막 커밋을 고치는 기능• 커밋 로그 , 변경 사항 전부 수정 가능 .
• 커밋하고 나서 , ‘ 아 이거 하나 커밋 안 했는데’ 할때 사용• 같은 역할을 하는 작은 커밋들을 여러개 만들지 않기 위해
쓰이지 않는 헤더파일을 지우는 커밋을 새로 만들었습니다
커밋하고 보니 , 수정할게 하나 더 있었습니다
변경 내역이 하나의 커밋으로 합쳐져 있습니다
git rebase -i
• Interactive• 리베이스 세션을 열고 , 어떻게 할지 다시 물어봅니다• 뭘 어떻게 ?• 원래 순서대로 할건지 , 이 커밋을 사용할건지 , 말건지 , 직전 커밋과 합칠지 , 커밋메세지를 새로 작성할지… . 등등
git rebase –i HEAD~5
A B C D
E Fchan-woo/
featureG H
git rebase –i HEAD~5
pick 781915a I’m hungry (D)pick 23158ce I want to sleep (E)pick c94880e I want to be fixed up (F)pick d173cc0 Hello! (G)pick daf497f I’ll change this commit log later (H)
pick, reword, squash and fixup# Commands:# p, pick = use commit# r, reword = use commit, but edit the commit message# e, edit = use commit, but stop for amending# s, squash = use commit, but meld into previous commit# f, fixup = like "squash", but discard this commit's log message# x, exec = run command (the rest of the line) using shell## These lines can be re-ordered; they are executed from top to bottom.## If you remove a line here THAT COMMIT WILL BE LOST.# However, if you remove everything, the rebase will be aborted.
git rebase –i HEAD~5
pick 781915a I’m hungry (D)squash 23158ce I want to sleep (E)fixup c94880e I want to be fixed up (F)reword daf497f I’ll change this commit log later (H)pick d173cc0 Hello! (G)
Pick D
A B C D
I’m hungry
Squash E
# This is a combination of 2 commits. # The first commit's message is: I’m hungry# This is the 2nd commit message: I want to sleep# Please enter the commit message for your changes. Lines starting # with '#' will be ignored, and an empty message aborts the commit. # Explicit paths specified without -i nor -o; assuming --only paths... # Not currently on any branch. # Changes to be committed:
A B C D+E
I’m hungry and I wanna sleep
Fixup F
A B C D+E+F
I’m hungry and I wanna sleep
Reword H
A B C D+E+F
H
Commit Log Changed!
Pick G
A B C D+E+F
H G
Hello!
Rebase finished
A B C D+E+F
H Gchan-woo/
feature
5. Branch strategy
master is SACRED
master 브랜치는 성역입니다 . 기도하고 checkout 합시다 .
Never Ever commit to master
branch 따와서 작업하고 , pull-request 날립시다
Branch Naming
name/fea-ture
Pull-Request
A B
E F
master
chan-woo/
feature
DCsome-body/
feature
Pull-Request merged
A B
E F
master
chan-woo/
feature
DCsome-body/
feature
G
Somebody: ?!
somebody 가 작업한 C,D 가 auto mergeable 이면 괜찮은데 , E,F 때문에 conflict 가 떠서 자동 머지가 불가능 하다면 ?
somebody 입장에서는 갑자기 다른놈이 훼방하지만 먼저 PR 날리고 merge 된 놈이 승자 .
이 때 somebody 가 할 수 있는 행동은 ?
git rebase master
A B
E F
master
chan-woo/
feature
D’C’some-body/
feature
G
Rules
unit test 는 사전에 미리 통과가 됐었어야 push 를 할 수 있다push 된 커밋들은 Travis 빌드 테스트를 통과해야 pull-request 를 보낼 수 있다
pull-request 가 별 다른 문제점이 없다면 merge 되지만커밋로그가 불충분 하거나 , 풀리퀘 로그가 불충분 하거나 ,
하나의 커밋에 너무 많은 일이 들어가 있거나 , 너무 적은 일이 들어가 있거나 , 쓸모 없는 기능으로 판단된다면 ?
REJECT
Rejected PR
A B
E F
master
chan-woo/
feature
git branch chanwoo/feature-v2
A B
E F
master
chan-woo/
featurechan-woo/
feature-v2
Fix problems, Send PR again.
A B
E F
master
chan-woo/
featurechan-woo/
feature-v2
F’
Summarize
• 하나의 커밋은• 적당한 크기 , 연관성 있는 변경점 , 상세한 커밋 메세지
• 여러개의 커밋은• 삽질은 커밋 로그에 , 하나의 기능은 하나의 커밋으로 줄인다• --amend, rebase -i
• 브랜치는• master 는 건들지 말고 , 기능별로 따 와서 , Pull-Request
6. Tip commands
git reset [--hard | --soft | …]
커밋을 취소하고 브랜치를 이전으로 돌리는 기능 --hard$ git reset --hard HEAD~1
--soft$ git reset --soft HEAD~1
git revert <commit>
• 해당 커밋의 변경점을 상쇄하는 커밋을 새로 생성
A+B
-A-B A B
git clean
• git 에 의해 추적되지 않는 파일들을 지우는 기능 추적되는 파일만 남기는 기능• 빌드시 자동 생성되는 파일들을 지울때 편함 .
$ git clean -xf
git blame
• 어떤 파일의 몇번째 라인부터 몇번째 라인 까지 • 누가 작성했는지 고발
$ git blame -L 12,12 ./src/asdf.cppd5dde9d4 (ChanWoo Jeong 2015-08-27 00:38:31 +0900 12)cout << “Hello world!” << endl;
git cherry-pick <commit>
• 특정 커밋 하나만 따와서 붙이는 기능 .
$ git cherry-pick 7cbce9a
END
References누구나 쉽게 이해할 수 있는 git 입문 – 브랜치 전환 : https://backlogtool.com/git-guide/kr/stepup/stepup1_3.html
Atlassian Tutorial – merging vs. rebasing : https://www.atlassian.com/git/tutorials/merging-vs-rebasing/
Git 브랜치 rebase 하기 : https://git-scm.com/book/ko/v1/Git-%EB%B8%8C%EB%9E%9C%EC%B9%98-Rebase%ED%95%98%EA%B8%B0
Git 도구 히스토리 단장하기 : https://git-scm.com/book/ko/v1/Git-%EB%8F%84%EA%B5%AC-%ED%9E%88%EC%8A%A4%ED%86%A0%EB%A6%AC-%EB%8B%A8%EC%9E%A5%ED%95%98%EA%B8%B0
소마 1 차 프로젝트 : https://github.com/swmaestro06-apus/apus