git rebase --help git-rebase - Reapply commits on top of another base tip
commit log 를 잘 작성하는 것은 협업 또는 본인 스스로 가독성 높은 코드를 작성하기 위한 많은 방법들 중 하나.
2. 원자적 커밋 (Atomic Commits with Git)
하나의 커밋에는 더이상 분리 할 수 없는 최소한의 코드 변경만 포함한다.
atomic commit 예
메세지를 통해 무엇 을 수정했는지 파악이 가능
* Create HTML for form
* Style form
* Add HTML5 validation
* Fix unrelated JS bug
* Add ajax submit to form with mock server results from PHP
* Add JS validation to form
* Send form results via email
* Log form results to database
* Style form validation and success/error messages
-
원자적 커밋이 좋은 이유
- 코드리뷰가 쉬워진다.
- 롤백이 쉬워진다.
- 명확한 히스토리가 된다. (시간이 많이 지난 후에도 작업 내용 파악 용이)
- cherry pick 의 활용 여지가 커진다.
-
자주 쓰는 메세지
- Polish or Polishing
- 컴파일된 코드에 변경이 없는 수정인 경우 (인덴트 수정, 주석 수정, 포멧팅 등)
- Upgrade to XXX
- dependency 의 버전업을 한 경우
- Fix typo
- 변수명등 오탈자 수정한 경우
- Polish or Polishing
※ (rebase 를 알기 전에 알아야 할 amend commit)
HEAD commit 에 변경 사항을 합친다.
$git commit --amend
1) 아래 상태에서 topic 브랜치에 master 의 F, G 를 반영 하는 방법
A---B---C topic
/
D---E---F---G master
2) 기존방법 : (topic 브랜치에서) git merge master
A---B---C---G' topic
/ /
D---E---F-------G master
- git graph가 복잡해짐.
- 충돌이 발생한 경우 merge commit 에는 충돌 해결 commit 이 들어가게 되고 이 log 는 히스토리를 복잡하게 만듦.
3) rebase 방법 : git rebase master idea : rebase.. => (interactive 체크해제 및 onto 에 base branch 지정)
A'--B'--C' topic
/
D---E---F---G master
- git graph 매우 심플
- commit log 상에 불필요한 충돌 해결 commit 이 없음
- fast-forward merge (git merge --ff feature1) 를 통해 불필요한 merge commit 을 없앨 수 있음.
(참고)topic 을 master 에 fast-forward 로 merge 한 모습 (또한 github 에서 PR 을 rebase merge 할 경우 이와 같이 됨)
D---E---F---G---A'--B'--C' topic, master
- 작업이 완료된 후에라도 원자적 커밋 원칙을 준수하기 위해 각 커밋을 다시 고칠 수 있다.
- 하나의 작업 브랜치에서 같은 코드 블럭이 두개의 commit 에 포함되지 않도록 고칠 수 있다.
- 작업 히스토리 파악 용이
- rebase merge 할때 충돌을 최소화 할 수 있다.
A---B---C topic
/
D---E master
1) topic branch 전체 commit 고치기
command : git rebase -i master
idea : rebase.. => (interactive 체크 및 onto 에 base branch 지정)
2) topic branch 최근 2개 commit 고치기
command : git rebase -i HEAD~2
idea : Show VCS Log => (로그중 원하는 commit 에서 context menu ) => Interactively Rebase from hear
A---B---C topic, origin/topic
/
D---E master
rebase interacive 이후 아래와 같이 변함
A---B---C origin/topic
/
D---E master
\
A'---B'---C' topic
force push 를 통해 origin 을 날리고 local branch 로 갱신한다
git push -f origin topic
(force push 주의점)
- 내 작업 브랜치에서만 수행한다.
- 공동 작업 브랜치인 경우 각 멤버의 local 에 추가 수정이 없는지 확인해야 함.
공동작업 브랜치에서 rebase & force push 를 수행한 이후 다른 멤버들은 local branch 를 reset 하여 remote 로 갱신해야 한다
git reset --hard origin/topic
3) 자주 사용하는 interactive mode 의 commit apply 명령
- pick : 이 커밋을 적용한다.
- reward : 이 커밋을 메세지를 수정하고 적용한다.
- edit : 이 커밋에서 멈추어 원하는 수정을 한 뒤에 적용한다.
- squash : 이 커밋을 이전 커밋과 합친뒤 적용한다.
- drop or skip : 이 커밋을 버린다.
- (기타는 문서 확인)
cherry pick 은 다른 브랜치의 특정 commit 만 내 브랜치로 가져오는 기능.
(상황1)
- 내가 개발 작업을 하던 중 버그를 발견 하였고, 이 버그는 핫픽스로 바로 배포 되어야 한다면 어떻게 처리하는게 가장 좋을까?
A---B---C(bug fix)---D topic
/
D---E master
bug fix 인 C 커밋만 master 에서 cherry pick 한 후 배포 한다.
A---B---C(bug fix)---D topic
/
D---E---C'(bug_fix) master
topic rebase onto master 시 C 커밋은 skip 한다.
A---B---D topic
/
D---E---C'(bug_fix) master
(상황2)
- 다른 사람이 이미 구현했지만 배포일정 관계로 아직 머지 하지 않은 기능을 머지하기 전까지 내 브랜치에 추가해서 사용하고 싶다면 어떻게 하는게 가장 좋을까?
A---B---D topic1
/
D---E---F master
\
G---H---B'(cherry pick)---I topic2
- topic1의 B 커밋에 구현된 기능을 topic2 에서 사용하고 싶은 경우 B 커밋을 cherry pick 한다.
- topic1 이 머지된 이후 rebase 를 통해 B' 커밋은 skip 한다.
A---B---D topic1
/ \
D---E-----------D' master
\
G---H---I topic2
레거시 메서드를 다른 클래스로 이동하거나 파일을 이동하거나 이름을 변경하는 것은 히스토리 파악을 어렵게 만들기 때문에 주의해야한다.
리펙토링에서 기존코드 를 개선하는 것이 어려운 경우 기존코드에 deprecated 마크와 함께 새 기능을 추가 하는 방향으로 하는 것이 좋다.