분기된 히스토리 해결: Git Merge vs Rebase 전략

분기된 브랜치, 충돌 처리, 공유 히스토리, 팀 안전 워크플로우 선택을 위한 git merge와 git rebase 비교.

분기된 히스토리 해결: Git Merge vs Rebase 전략

Git merge와 rebase는 모두 브랜치가 다른 브랜치에서 분기되었을 때 도움이 됩니다. 차이점은 히스토리를 보존하는 방식에 있으며, 잘못된 선택은 협업을 필요 이상으로 어렵게 만들 수 있습니다.

모든 변경에 완벽한 히스토리가 필요하지는 않습니다. 팀이 이해하고 공유 브랜치를 안정적으로 유지할 수 있는 전략이 필요합니다.

분기된 히스토리의 의미

분기된 히스토리는 두 브랜치가 공통 시작점 이후에 서로 다른 커밋을 가질 때 발생합니다. 예를 들어, 월요일에 main에서 feature/log-cleanup을 생성했습니다. 화요일에 누군가 보안 수정 사항을 main에 병합했습니다. 이제 브랜치와 main은 각각 상대방이 없는 커밋을 가지고 있습니다.

다음 명령어로 확인할 수 있습니다:

git log --oneline --graph --decorate --all

Git이 브랜치와 원격 브랜치가 분기되었다고 알릴 수도 있습니다. 이는 양쪽에 고유한 커밋이 있다는 의미입니다. Git은 이를 결합하는 방법을 결정하도록 요구합니다.

일반적인 두 가지 도구는 merge와 rebase입니다:

git merge main

또는:

git rebase main

두 방법 모두 동일한 최종 파일 내용을 생성할 수 있습니다. 히스토리는 다르게 보입니다.

Git Merge 작동 방식

Merge는 기존 커밋을 다시 쓰지 않고 히스토리를 결합합니다. 브랜치와 main이 모두 앞으로 이동한 경우, Git은 두 작업 라인을 연결하는 병합 커밋을 생성합니다.

일반적인 흐름은 다음과 같습니다:

git switch feature/log-cleanup
git fetch origin
git merge origin/main

충돌이 없으면 Git은 병합 커밋을 생성하거나 가능한 경우 fast-forward를 수행합니다. 충돌이 있으면 Git은 일시 중지하고 해결하도록 요청합니다.

Merge는 협업의 실제 형태를 보존하려는 경우에 좋습니다. 작업이 병렬로 진행되었고 나중에 결합되었음을 보여줍니다. 이는 장기 실행 브랜치, 릴리스 브랜치 및 공유 기능 브랜치에 유용할 수 있습니다.

단점은 빈번한 병합이 노이즈를 추가할 수 있다는 것입니다. "main을 feature로 병합" 커밋이 많은 브랜치는 스캔하기 어려울 수 있습니다. 이것이 잘못되었다는 의미는 아니지만 히스토리를 덜 깔끔하게 만들 수 있습니다.

다음과 같은 경우 merge를 사용하세요:

  • 브랜치가 다른 개발자와 공유되는 경우.
  • 커밋 히스토리를 다시 쓰지 않으려는 경우.
  • 팀이 통합 지점의 정확한 기록을 중요시하는 경우.
  • 릴리스 브랜치나 보호된 브랜치를 업데이트하는 경우.

이미 푸시되어 다른 사람이 사용하는 브랜치의 경우, merge가 일반적으로 더 안전한 기본값입니다.

Git Rebase 작동 방식

Rebase는 브랜치 커밋을 새 기본 커밋 위에 나타나도록 이동합니다. 두 개의 분기된 라인이 병합 커밋으로 연결되는 대신 브랜치 히스토리가 선형이 됩니다.

일반적인 흐름은 다음과 같습니다:

git switch feature/log-cleanup
git fetch origin
git rebase origin/main

Git은 커밋을 하나씩 최신 main 위에 재생합니다. 충돌이 발생하면 Git은 재생할 수 없는 커밋에서 중지합니다. 충돌을 해결한 후 다음 명령어로 계속 진행합니다:

git add <fixed-files>
git rebase --continue

Rebase가 혼란스러우면 다음 명령어로 되돌릴 수 있습니다:

git rebase --abort

Rebase는 로컬, 개인 브랜치에 유용합니다. 히스토리를 읽기 쉽게 유지하기 때문입니다. 리뷰어는 커밋이 처음부터 최신 main 위에 구축된 것처럼 볼 수 있습니다.

다음과 같은 경우 rebase를 사용하세요:

  • 브랜치가 본인 소유이고 공유되지 않은 경우.
  • 깔끔하고 선형적인 커밋 히스토리를 원하는 경우.
  • 풀 리퀘스트를 열기 전에 브랜치를 준비하는 경우.
  • 팀이 명시적으로 rebase된 기능 브랜치를 선호하는 경우.

주요 규칙은 간단합니다: 팀이 예상하지 않는 한 공개 커밋을 rebase하지 마십시오. Rebase는 커밋 해시를 다시 씁니다. 다른 사람이 이전 커밋을 기반으로 작업한 경우, 다시 쓰면 혼란을 초래할 수 있습니다.

더 많은 일상적인 Git 히스토리 도구는 프로젝트 히스토리 탐색을 참조하세요.

Merge 또는 Rebase 중 충돌 처리

충돌은 Git이 변경 사항을 자동으로 결합할 수 없을 때 발생합니다. 배포 매니페스트, 종속성 잠금 파일 및 공유 구성 파일과 같은 바쁜 파일에서 흔히 발생합니다.

상태를 확인하는 것으로 시작하세요:

git status

충돌이 있는 파일을 열고 충돌 마커를 찾으세요:

<<<<<<< HEAD
현재 브랜치 버전
=======
들어오는 버전
>>>>>>> branch-name

표시된 블록을 실제로 원하는 최종 내용으로 바꾸는 것이 작업입니다. 마커를 유지하지 마세요.

편집 후 파일을 스테이징하세요:

git add path/to/file

Merge의 경우 다음 명령어로 마무리하세요:

git commit

Rebase의 경우 다음 명령어로 계속 진행하세요:

git rebase --continue

충돌 해결 후 테스트 또는 관련 검증 명령어를 실행하세요. 파일이 구문적으로 깨끗하더라도 논리적으로 잘못될 수 있습니다. 예를 들어, 두 개의 Kubernetes YAML 변경 사항이 충돌 없이 병합되면서 중복 포트나 일치하지 않는 레이블을 정의할 수 있습니다.

팀 전략 선택

최고의 전략은 프로젝트에 예측 가능한 히스토리를 만드는 전략입니다. 많은 팀이 개인 기능 브랜치에는 rebase를 사용하고 풀 리퀘스트에는 병합 커밋을 사용합니다. 다른 팀은 모든 기능 작업을 하나의 커밋으로 스쿼시합니다. 일부 인프라 팀은 브랜치가 통합된 정확한 시점을 보여주기 때문에 병합 커밋을 선호합니다.

규칙을 선택하고 문서화하세요. 간단한 정책은 다음과 같을 수 있습니다:

  • 리뷰 전에 자신의 기능 브랜치를 rebase하세요.
  • main, 릴리스 브랜치 또는 공유 브랜치는 절대 rebase하지 마세요.
  • 승인된 풀 리퀘스트에는 병합 커밋을 사용하세요.
  • 작고 단일 목적의 수정에는 스쿼시 병합을 사용하세요.

이렇게 하면 긴급 작업 중 Git 스타일 논쟁을 방지할 수 있습니다. 또한 CI, 릴리스 노트 및 배포 도구가 일관된 히스토리에 의존할 수 있으므로 자동화가 더 쉬워집니다.

도움을 요청해야 할 때

다른 사람이 사용할 수 있는 브랜치에서 rebase 후 강제 푸시하기 전에 물어보세요. 또한 충돌이 보안 설정, 데이터베이스 마이그레이션, 프로덕션 배포 파일 또는 이해하지 못하는 생성된 잠금 파일에 영향을 미칠 때 물어보세요.

Merge 또는 rebase가 복잡해지면 중단하고 git status로 상태를 확인하세요. 일반적으로 git merge --abort 또는 git rebase --abort로 중단하고 이전 상태로 되돌릴 수 있습니다. 작업 트리가 깨끗해 보일 때까지 임의의 명령어를 시도하는 것보다 낫습니다.

Merge와 rebase는 동일한 광범위한 문제를 해결하지만 다른 이야기를 전합니다. Merge는 작업이 어떻게 결합되었는지 보존합니다. Rebase는 더 깔끔한 커밋 라인을 만듭니다. 각각 적합한 곳에 사용하면 Git 히스토리가 위험 요소가 아닌 유용한 도구로 남을 것입니다.