I suppose thatyou know …
커밋을 어떻게 하는지, staging은 어떻게 하는지, 브랜치를 어
떻게 만드는지, 나눠진 브랜치를 어떻게 병합하는지, 원격 브랜
치와 로컬 브랜치가 어떻게 진행 되는지, 코드가 어떻게/언제
충돌 나는지, 충돌난 코드를 어떻게 해결하는지, 남들이랑 작업
하면서 프로젝트가 어떻게 망가지는지, Pull-Request가 뭔지,
Pull-Request를 어떻게 하는지, 등등…
다른 사람이랑 git으로 프로젝트를 해봤다고 가정합니다.
^ & ~
BD
E
CA HEAD
HEAD~1,
HEAD^
HEAD~2,
HEAD~1^1
HEAD~3
HEAD~2,
HEAD~1^2
15.
A commit mustbe …
• 적절한 크기의 하나의 작업만 해야 합니다
잠수함 패치 하면 안됨
• 컴파일 가능해야 합니다 ,빌드 가능해야 합니다
커밋 하나가 완벽해야 합니다
• 커밋 메시지가 잘 쓰여져 있어야 합니다.
생판 모르는 사람이(미래의 내가) 봐도 이해 가능해야
Has upstream?
만약 chanwoo/feature의upstream이 존재한다면?
그냥 push 했을경우 reject당함 (충돌나니까)
현재 이력을 강제로 올려야 합니다.
$ git push --force
# Be very careful with this command!
After Rebasing
A BC D
E F
master
chanwoo
/featureE’ F’
origin
/chanwoo
/feature
45.
git push --force
AB C D
E F
master
chanwoo
/featureE’ F’
origin
/chanwoo
/feature
46.
Merge vs. Rebase
•Merge
• 장점
• 이전 커밋들을 들쑤지진 않음, (이전 커밋들이)잘못될 가능성이 없음.
• 단점
• 다른 브랜치들이 매우 활발하다면 그 때문에 머지 커밋이 많이 발생할 수 있고,
때문에 커밋 로그들이 지저분해 보일 수 있음.
47.
Merge vs. Rebase
•Rebase
• 장점
• 프로젝트 히스토리가 훨씬 깔끔해질 수 있음.
• 선형적인 커밋 구조를 만들 수 있음.
• 단점
• 이전 커밋들을 들쑤시고 다니기 때문에, 충돌이 발생하면 merge commit을 만
드는 방법보다 해결이 귀찮음.
• 원격의, 남이 건드릴 수 있는 브랜치(public branch)는 절대 리베이스 하면 안됨.
B != B’
B와B’는 다른 커밋
chanwoo/feature에서 master로 rebase 하면 B도 쌓아 올린다.
만약 B같은 커밋이 여러개라면?
다른 개발자들도 B에서 브랜치를 쳤다면?
C, D에서도 다른 개발자들이 브랜치를 쳤다면?
이런 상황을 전문용어로 개판이라고 한다.
원격의, 남이 건드릴 수 있는 브랜치는 절대 리베이스 하면 안됨!
52.
Discuss with yourcolleagues
Merge를 해도 되고 Rebase를 해도 됩니다.
어떤 방법으로 커밋들을 병합할지는
팀원들과 상의하세요
(아니면 PM이 까라는대로 까야지)
53.
Conflict!
• $ gitrebase --continue
• $ git rebase --skip
• $ git rebase --abort
아직 rebase가 끝난게 아닙니다.
git rebase --continue
AB C D
E F
master
chanwoo
/feature
E’ F’--continue
Resolve하고 난 후,
--continue
56.
git rebase --skip
•충돌난 상황에서, 현재 커밋을 쌓아올리길 포기하고 건너뜁니다.
• 잘 안씀, 커밋 하나하나가 중요하다면.
• 종종 resolve 다 하고 보니 git add할게 없을때 사용함.
• sourcetree의 ‘resolve with theirs/mine’만 사용할때 발생할 수 있음.
57.
git rebase --abort
•현재 rebase 세션을 포기하고 아예 없던일로 합니다.
쌓아올리는 커밋을 하나하나 resolve 하며 --continue 한 두번 하다가 나
중에 화나서 --abort할때 주로 사용함.
58.
git reset ORIG_HEAD
rebase를성공적으로 마치고 난 직후 ,
‘아 이 리베이스 하면 안됐는데’ 라는 생각이 들때 사용함
HEAD를 rebase 직전의 커밋을 가리키게 해 준다.
뭐 이것저것 만졌으면 reflog 찾아봐야지..
git rebase –iHEAD~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)
71.
pick, reword, squashand 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.
72.
git rebase –iHEAD~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)
Squash E
# Thisis 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 '#' w
ill be ignored, and an empty message aborts the commit.
# Explicit paths specified without -i nor -o; assuming --only paths... # Not cu
rrently on any branch. # Changes to be committed:
A B C D+E
I’m hungry and I wanna sleep
Somebody: ?!
somebody가 작업한C,D가 auto mergeable이면 괜찮은데,
E,F때문에 conflict가 떠서 자동 머지가 불가능 하다면?
somebody 입장에서는 갑자기 다른놈이 훼방
하지만 먼저 PR날리고 merge된 놈이 승자.
이 때 somebody가 할 수 있는 행동은?
Rules
unit test는 사전에미리 통과가 됐었어야 push를 할 수 있다
push 된 커밋들은 Travis 빌드 테스트를 통과해야 pull-request를 보낼 수 있다
pull-request가 별 다른 문제점이 없다면 merge 되지만
커밋로그가 불충분 하거나, 풀리퀘 로그가 불충분 하거나,
하나의 커밋에 너무 많은 일이 들어가 있거나,
너무 적은 일이 들어가 있거나,
쓸모 없는 기능으로 판단된다면?
REJECT
Fix problems, SendPR again.
A B
E F
master
chanwoo
/feature
chanwoo/
feature-v2F’
95.
Summarize
• 하나의 커밋은
•적당한 크기, 연관성 있는 변경점, 상세한 커밋 메세지
• 여러개의 커밋은
• 삽질은 커밋 로그에, 하나의 기능은 하나의 커밋으로 줄인다
• --amend, rebase -i
• 브랜치는
• master는 건들지 말고, 기능별로 따 와서, Pull-Request
END
누구나 쉽게 이해할수 있는 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
#50 이 상태에서 feature브랜치와 master 를 머지를 하던 리베이스를 하던 합친다고 해봅시다
#51 B와 B’는 다른 커밋이죠, 그래서 공통 조상이 A로 잡힙니다. 이러면 chanwoo/feature에서 master를 rebase 하려면 B, E, F 부터 쌓아 올려야 하겠죠, 그럼 같은 내용의 커밋 B가 여러번 생기게 됩니다. 히스토리가 더 개판이 되겠죠. 근데 만약에 B같은 커밋이 하나가 아니라 여러개라면? Chanwoo만 브랜치 따서 작업하는게 아니라 다른 사람도 브랜치 따서 작업하던거라면? C나 D 커밋에서 브랜치 따서 작업하던 사람들이 또 있다면? 그 사람들이 rebase할때마다 똑같은 일을 하는 커밋들이 (커밋로그도 똑같음) 늘어나는겁니다.
#54 충돌 없이 잘 되는 경우만 살펴봤죠. 하지만 아까 머지 커밋을 만들때 말했던 것 처럼 리베이스 할때도 서로 다른 코드들이 합쳐지면서 마찬가지로 충돌이 일어날 수 있습니다. 이런경우 어떻게 해결할까요?
리베이스 세션이 열려있을때만 사용할 수 있는 명령어가 몇개 있습니다.
충돌이 일어난다고해서 리베이스가 바로 취소되지는 않고 사용자에게 무슨 짓을 할지를 물어봅니다.
해결하고 리베이스를 계속 진행할껀지
그냥 해당 커밋만 넘겨 버릴지
아니면 아예 포기할지
#55 F를 쌓아 올리지 않고, 리베이스 세션을 잠깐 멈추고 유저에게 뭘 어떻게 할지 물어봅니다.
평소에는 resolve하고 그냥 머지커밋을 만들었다면, 여기선 그냥 rebase를 계속 하면 됩니다.
#62 어떤 한 기능을 구현하기 위해서 이래저래 삽질을 합니다.
이래저래 삽질을 하면 커밋로그가 정신없어 집니다.
#63 여러개의 커밋을 하나로 묶으면 보기 편합니다. 오픈 소스들 같은데 PR 날리다 보면, 커밋들 정리해서 다시 보내라고 하는 경우가 많이 있는데, (커밋이 많다거나, 하나의 커밋이 너무 많은 일을 하거나, 너무 자잘한 커밋이거나) 이럴때 커밋들을 적당히 묶어서 보내야 합니다.
묶을때 또 너무 하나의 커밋이 너무 커지게 묶으면 안되겠죠
묶는 방법 두개를 소개해 드릴겁니다.
#65 이번껀 간단하니까 예시로 보여드리죠,
제가 chanwoo/test라는 브랜치를 만들어서 몇가지 쓸모없는 헤더파일을 지우는 커밋을 만들었다고 쳐요,
여기 보면 diff에 빨간색으로 몇개 지워져 있는게 보이죠?
#66 커밋하고 나서 보니, 수정해야할 내역이 남아 있는데 깜빡하고 이미 커밋을 한 상태입니다
이럴땐 마지막 커밋에 추가할 내용을 stage 시킵니다.
#67 --amend 옵션을 붙여서 커밋을 합니다. 커밋 메세지를 수정하라고 vi가 한번 나옵니다. 수정할꺼 수정하시고 저장하고 vi를 종료 하시면 됩니다.
#68 이렇게 커밋을 새로 만들지 않고도 마지막 커밋의 내용을 수정해서 하나로 몰아넣을 수 있습니다.
#69 그냥 마스터를 리베이스 할 때도, -I 옵션을 붙여서 명령을 내릴 수 있지만, 보통 그렇게는 잘 안쓰고, 커밋 이력을 간소화 하는데 저는 자주 썼습니다.
#71 VI창이 열리면서 이렇게 우리한테 물어봅니다. 어떻게 할지.
여기서 이제 이 커밋들을 어떻게 할지 여러분 마음대로 할 수 있습니다. 순서도 바꿀 수 있고요, 충돌이 나지 않는 선에서. 커밋을 하나하나 제대로 나눠서 했다면 충돌날 일이 적겠죠?
#86 풀리퀘는 머지 커밋이 생깁니다. 이 머지 커밋은 풀리퀘를 받았다는 의미로 기록에서 없애지 않습니다.
#87 somebody 입장에서는 master에서 잘 작업중이었는데 엄한 놈이 와서 내 작업물들을 충돌나게 만들었죠
#88 이렇게 G기반으로 C,D를 쌓아올리고 나서, 리베이스 하고 나서, 작업을 계속 할 수 밖에 없습니다.
#89 시퍼런 색이 마스터 브랜치 입니다.
마스터에서 기능별로 브랜치를 따서 작업을 시작합니다.
몇몇 브랜치는 도태되고, 하나의 브랜치만 살아 남아, master에 머지 됩니다.
그 사이클을 계속 반복해 나가면서 개발이 진행되게 됩니다.
때로는 많은 기능들을 물리치고 자잘한 커밋이 먼저 머지 될 수 있습니다.