JIHYEONJEONG
Robust Project Structure

Git rebase와 git pull의 차이

git rebase와 git pull(fetch+merge)의 차이점과 깃 플로우 관리에 있어서의 장단점에 대해서 알아본다.

Problem - git rebase와 git pull의 차이

이번 프로젝트에서 가장 까다로웠던 것은 모든 개인(feature을 비롯한 모든) 브랜치가 main에서 git pull을 통해 최신화된다는 점이었다. git pull(fetch+merge)에서 주의해야 할 점은, 로컬 브랜치에서 커밋을 가진 상태로 pull을 시도해 머지하는 경우 코드가 덮어씌워질 수 있다는 점이다.

Goal - git pull(fetch+merge)로 깃 플로우를 관리할 시 코드가 덮어씌워지는 현상에 대해서 확인하고, 더 안전한 방법을 찾아본다

  • git pull(fetch+merge)로 깃 플로우를 관리할 시 코드가 덮어씌워지는 현상에 대해서 확인하고, 더 안전한 방법을 찾아본다

stackoverflow 에서 설명하는 이 케이스를 확인해 보았다.

pull 은 당신의 파일을 덮어씌우지 않습니다. pull 을 사용할 경우, 해당 대상 브랜치를 먼저 fetch 하고 이것을 당신의 로컬 코드에 적용합니다. 이것은 git merge와 동일한 과정입니다. 만약 당신이 App.tsx 파일을 푸시했고 이것을 로컬에서 수정한 상황이라고 생각합니다.

  1. 이 상황에서 당신이 pull을 수행하는 경우 git은 당신의 로컬 수정사항을 기록하고 있으며 이것은 별 문제없이 병합이 됩니다.
  2. 하지만 다른 사람이 같은 파일을 수정하는 경우, 이것은 conflict로 이어져 당신의 선택을 통해 원하는 버전이 머지됩니다.
  3. 만약 다른 사람이 같은 pull 과정을 통해 이 1.cpp 파일을 변경한 커밋을 내가 pull로 가지고 오는 경우, 파일이 덮어씌워질 수 있다.
  • 여기서 문제가 되는 것은, git pull은 머지 커밋을 생성하기 때문에 같은 부분을 수정하는 커밋을 pull 해서 머지하는 경우 머지 커밋간의 시간 우선순위에 의해서 코드가 덮어씌워지는 현상이 있을 수 있다는 것이다.

Implementation - 그렇다면 어떻게 해야 하나?

  1. git rebase
  • 자식 브랜치에서는 머지 커밋을 생성하는 pull 대신 rebase를 사용한다. 먼저 main의 변경점을 가져온 뒤에, 그 다음에 내 커밋을 적용해서 머지 커밋을 없애고 내 커밋을 가장 최신으로 유지한다.
  1. git pull
  • 부모 브랜치(main)에서는 pull request만을 사용해서 자식을 병합한다.(cherry-pick?) 머지 커밋은 여기서만 생성한다.

Refs

On this page