처음 입사해서 pull request를 할 때 얼마나 긴장되던지. (사실 지금도 마찬가지...)
내 딴에는 main 브랜치 변경 적용하랴, conflict 나면 해결하랴, history를 squash 하랴, rebase 하랴 우여곡절이 많았고 그럼에도 불구하고 내가 생각한 시나리오(?) 대로 100% 되지 않아 좀 많이 짜증나기도 했다.
어쨌든 이번에 PR 올릴 때 마치 패키지처럼 git의 여러 가지 기능을 쓰게 되어, 좋은 practice가 된 기념으로 기록해본다.
메인 브랜치인 develop
에서 feature/A
브랜치를 따고, 작업을 진행했다.
#변경 내용 확인하기
git diff
#status 확인하기 - 여러모로 이 명령어가 제일 편하긴 하다
git status
git status
를 통해 내가 작업한 파일들이 맞는지 확인 후, commit을 진행하면 되는데 나같은 경우 이 때 3개의 commit을 만들었다.
#모든 log들을 한 줄로 확인하기
git log --oneline
그러면 아래와 같이 3개의 commit 이력이 뜬다. 이 때 base는 merge #32까지 된 main 브랜치다.
그러던 중에, main 브랜치가 변경되었다.
따라서 PR 올리기 전에 main 브랜치 내용을 갖고와 내 브랜치에도 반영한다. pull
을 받으면, fast-forward merge (브랜치가 가리키는 커밋을 앞으로 이동시키는 것) 를 진행한다.
#main 브랜치로 이동
git checkout develop
#원격 repo에 저장된 변경 내용 갖고 오기
git pull origin develop
이제 내 브랜치로 이동해 변경된 main 내용을 들여온다.
#내 브랜치로 이동
git checkout feature/A
#main 브랜치 내용을 갖고오기
git rebase develop
git rebase develop
은, 현재 내 브랜치의 base를 develop으로 옮기겠다는 뜻이다. 이렇게 명령어를 쳤더니 충돌이 발생했다.
여기서 충돌이 발생하는 이유는 rebase
의 원리에 있다.
1) rebase
를 치면, 처음 내 브랜치가 파생된 base로부터 내 브랜치 커밋 내역까지 임시 저장소로 옮겨진다 (옮겨진 내용: fetch)
2) base부터 내 브랜치 커밋 내역까지의 플로우는 삭제되고, 내 브랜치는 가장 최신 base로 옮겨진다
3) 임시저장소에 있던 fetch에서 커밋 내역을 하나씩 꺼내 최신 base에 병합시킨다
위와 같은 과정을 거치기 때문에, 3) 커밋 내역을 하나씩 자동 merge하는 과정에서 충돌이 생기는 것이다. 이 때는 수동으로 코드를 정리한다.
conflict가 발생하면, vs code 상에서는 자동으로 conflict 부분이 표시된다.
최대한 shorcut들을 쓰지 않고, 직접 확인해가면서 수동으로 조정하는 것이 제일 안전하다.
<<<<<head : 현재 branch를 표시해주는 마크
Accept Current Change : head 부분을 적용한다
Accept Incoming Change : 변경된 부분을 적용 (병합 대상이 된 develop의 내용으로 변경)
Accept Both Change : 둘 다 남긴다
Compare Change : conflict 부분을 더 쉽게 보여준다
>>>>>develop : merge 될 병합대상 develop의 내용
해결했으면, git add
- git commit
을 통해 resolve를 마크해준다. 해결 후, 아래와 같이 명령어를 쳤다.
git rebase --continue
그런데 계속 resolve - commit 하지 않은게 없는지 확인하라는 메세지가 떠서, skip 했다.
git rebase --skip
아래와 같이 변경되었고, base는 merge #32였던 log에서 최신(merge #35)로 변경되었다.
이대로 pull request를 하면 rebase를 하기 위해 생겼던 commit 이력이 모두 올라가 약간 지저분해진다. 그래서 이를 정리하기 위한 것이 squash
다.
squash
라는 명령어가 따로 있는 것은 아니며, rebase
를 통해 진행한다.
git rebase -i 97c9763
그러면 아래 예시같이 pick
할 커밋 1개와, squash
할 커밋을 정한다. squash
는 s
로 표기한다.
그 다음에 커밋 메세지를 1개 선택하면 끝!
아래와 같이 최신 base에 최종 커밋 1개만 남았다.
이미 pull request를 올렸는데, 이후에 main 브랜치가 변경되어 github 상에서 conflict가 생겨 자동 merge가 불가능하다는 알림이 뜨는 경우가 있다.
이런 적이 한번 있었는데, 이 때는 아래와 같이 해결했다.
#메인 브랜치로 이동
git checkout develop
#로컬 최신화
git pull origin develop
#작업 브랜치로 이동
git checkout feature/A
#메인 브랜치 병합하기 -> 새로운 merge 커밋 로그가 생성된다
git merge develop
git status
로 상태 확인한다.git add
- git commit
진행한다. git push origin feature/A
(새로운 커밋 로그로 push됨) 참고 자료
https://m.blog.naver.com/PostView.naver?isHttpsRedirect=true&blogId=da91love&logNo=221151405391
https://dev-yakuza.posstree.com/ko/git/git-squash/
https://doing7.tistory.com/7