git충돌이슈기록

way·2024년 5월 30일

devOps

목록 보기
2/2
post-thumbnail

업무 상황에서 발생했던 git충돌이슈에 대해서 회사에서 인지하고 대처 방안을 기록했던 내용이다.
먼저 git merge 전략에 대해 복습 해 본다.

Merge전략 복습

(1)Merge Commit

merge된 브랜치가 삭제되어도 git history에는 그대로 남아 어떤 이력으로 merge가 실행되었는지 모두 기록이 남음. 모든 브랜치가 나뉘어 관리되기 때문에 가독성은 다소 떨어질 수 있으나 업무에서는 이러한 이력이 중요하기 때문에 이 방법을 사용한다.

merge dev into 'feature/test1' branch

git checkout feature/test1
git merge dev

(2)Squash and Merge

merge 할 때 --squash 옵션을 주는 방법이다.
squash 옵션을 주면 병합시킬 때 commit 이력을 하나로 만들어준다. merge할 내 브랜치와 변경사항이 있는 다른 브랜치의 이력들을 모두 하나로 합친 후 commit하는 전략이다. 충돌 이슈는 이 커밋전략으로 인해 발생했다.... 물론 버전관리가 잘 되어있다면 문제될 게 없다.


merge dev into 'feature/test1' branch with --squash

git checkout feature/test1
git merge --squash dev
git commit -m "squash merge"

(3)Rebase and Merge

브랜치의 베이스를 새로 설정한다. rebase후에는 브랜치가 나뉘어지지 않고 commit한 내용이 마치 타겟 브랜치에서 변경된 것처럼 깔끔하게 변경된다. 이 전략의 경우 merge시점을 알 수 없기 때문에 tag로 깔끔하게 관리하는 게 관건이다.

충돌 발생 issue기록

발생했던 충돌이슈는 다음과 같다.
1. 개발자A가 feature/test1 브랜치에서 develop(dev)브랜치로 100개(예시)의 파일을 한번에 업데이트. → feature/B 브랜치를 작업하던 개발자B가 dev로 머지 요청 시 100개의 파일이 충돌.
2. feature/test2 브랜치를 작업하던 환경에서 오랫동안 업데이트 되지 않은 로컬파일과 feature/test1 브랜치의 파일이 squash merge된 후, dev 브랜치에 덮어 씌워짐.
3. 100개의 파일+수많은 로컬파일이 squash merge로 인해 어떠한 과정으로 변경되었는지 이력이 남지 않고, 일괄수정한 파일의 갯수가 많아(100개) 덮어쓴 파일과 수정한 파일의 구분이 가지 않아, 모든 commit 내역의 버전을 일일이 확인 할 시간도 촉박했다!

원인 : 개발자B가 local 파일들을 최신 상태로 업데이트 하지 않고 오래 방치한 상태로 squash commit시도.

조치 : 해당 이슈를 모든 개발자들에게 전파하고 fo-web에 커밋을 중지시키고 메일로 공지 발송. 각 모듈마다 자신의 파일을 확인하고 잘못 머지된 커밋의 바로 이전 파일을 현재 위치로 덮어쓰도록 작업 요청.

로컬에서 연습해본 git브랜치 머지 시 충돌 해결

intelliJ로 git 브랜치 머지 시 충돌 시 해결할 수 있도록 충돌상황을 만들어 로컬에서 연습해봤다.

  1. main브랜치에 commit

  2. dev브랜치로 나가서 동일한 파일의 동일한 위치에 commit

    1. main 브랜치로 checkout후
      git merge dev(merge할 브랜치 명) 하면,
      “자동 병합이 실패했습니다. 충돌을 바로잡고 결과물을 커밋하십시요” 라는 문구가 표시.
      충돌이 일어난 파일에 <<<< HEAD 와 dev의 변경사항이 모두 표시된 조정문구가 표시.
    1. abort merge??

main의 문구 : git merge practice
dev의 문구 : hello world

merge 후 충돌이 일어난 부분에 바꾼 문구 “git merge dev”

위와 같이 문구를 바꾼 후에 Terminal의 commit을 시도 했으나 뭔가 계속 실패... intelliJ를 껐다 켜고 Local Change Files에서 UI로 조작해서 조정한 충돌 파일을 Commit 하니까 성공.

main에 커밋하자 dev브랜치에 커밋할 내역이 있다는 표시(초록화살표)가 나온다. 바로 dev에 checkout 해서 해당 커밋내역(merge내역)을 dev에도 커밋하여, dev에 변경사항을 반영해 줌.

브랜치 main에도 dev에도 “git merge dev”로 변경되어 충돌이 해소되었다.

교훈

여러명의 작업자가 하나의 프로젝트에서 작업 할 때 충돌은 불가피한 것일 수 있다. 이러한 충돌이나 사고를 막기 위해서라도 팀 내에서 통합된 형상관리 전략과 이해는 굉장히 중요한 것 같다.

내 팀에서 merge전략을 정해야 한다면 반드시 merge commit전략을 사용 할 것 같다...
보기에는 지저분하더라도 모든 이력이 남아있는 것이 맥락을 모르는 제3자가 봐도 조치를 취할 수 있는 방법인 듯 하다. (intelliJ같은 인터페이스를 사용할 경우 자동으로 merge설정이 rebase나 squash로 되어있지 않은지 확인 필요!)

그러나 개인 프로젝트 내에서는 무조건 rebase를 하고 있긴 하다. 협업을 위한 툴이므로 용도에 맞는 전략을 취하는 것이 좋겠다.

제일 중요한 건... 로컬에 리모드 버전 업데이트를 잘하는것이다. target 브랜치와 오랫동안 동기화가 안 된 경우에는 commit전 반드시 target브랜치의 소스를 내 작업브랜치로 pull하고 내 로컬에서 충돌을 해결하는 것이 가장 바람직하다.

0개의 댓글