[git] main 브랜치 변경 내용 적용하고 squash하기

EMMA·2022년 7월 26일
3
post-thumbnail

git branch 작업부터 변경 사항 적용, PR까지

처음 입사해서 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 브랜치 변경 내용 갖고오기

그러던 중에, main 브랜치가 변경되었다.
따라서 PR 올리기 전에 main 브랜치 내용을 갖고와 내 브랜치에도 반영한다. pull을 받으면, fast-forward merge (브랜치가 가리키는 커밋을 앞으로 이동시키는 것) 를 진행한다.

#main 브랜치로 이동 
git checkout develop 

#원격 repo에 저장된 변경 내용 갖고 오기 
git pull origin develop 

내 브랜치에도 적용하기 - rebase

이제 내 브랜치로 이동해 변경된 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 해결하기

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)로 변경되었다.


브랜치의 커밋 내역 정리하기 - rebase, squash

이대로 pull request를 하면 rebase를 하기 위해 생겼던 commit 이력이 모두 올라가 약간 지저분해진다. 그래서 이를 정리하기 위한 것이 squash다.

squash라는 명령어가 따로 있는 것은 아니며, rebase를 통해 진행한다.

git rebase -i 97c9763

그러면 아래 예시같이 pick할 커밋 1개와, squash할 커밋을 정한다. squashs로 표기한다.

이미지 출처: https://dev-yakuza.posstree.com/ko/git/git-squash/

그 다음에 커밋 메세지를 1개 선택하면 끝!
아래와 같이 최신 base에 최종 커밋 1개만 남았다.


번외 - merge 사용하기

이미 pull request를 올렸는데, 이후에 main 브랜치가 변경되어 github 상에서 conflict가 생겨 자동 merge가 불가능하다는 알림이 뜨는 경우가 있다.

이런 적이 한번 있었는데, 이 때는 아래와 같이 해결했다.

  1. github 웹 페이지에서는 conflict 부분을 다 안보여 줄 수도 있다.
  2. 따라서, 아래 명령어를 쳐서 conflict 내용을 내 로컬(vs code)에 띄우게 한다.
#메인 브랜치로 이동 
git checkout develop

#로컬 최신화 
git pull origin develop 

#작업 브랜치로 이동
git checkout feature/A

#메인 브랜치 병합하기 -> 새로운 merge 커밋 로그가 생성된다 
git merge develop 
  1. conflict 내용을 해결한다.
  2. git status로 상태 확인한다.
  3. git add - git commit 진행한다.
  4. 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

profile
예비 개발자의 기술 블로그 | explore, explore and explore

0개의 댓글