리베이스 및 머지 충돌 해결
Git rebase는 커밋을 대상 브랜치의 끝으로 이동하여 한 브랜치의 변경 사항을 다른 브랜치에 결합합니다. Git이 처음에 그 브랜치를 만든 후 대상 브랜치에 제출된 모든 커밋을 가져옵니다. Git이 가져온 커밋 위에 브랜치의 커밋을 적용합니다.
Git rebase는 커밋을 대상 브랜치의 끝으로 이동하여 한 브랜치의 변경 사항을 다른 브랜치에 결합합니다. 이 작업은:
- 대상 브랜치의 최신 코드로 브랜치를 업데이트합니다.
- 더 쉬운 디버깅과 코드 리뷰를 위해 깔끔하고 선형적인 커밋 기록을 유지합니다.
- 충돌 해결을 위해 커밋 수준에서 머지 충돌을 해결합니다.
- 코드 변경의 시간 순서를 보존합니다.
리베이스를 수행하면:
-
Git이 처음에 그 브랜치를 만든 후 대상 브랜치에 제출된 모든 커밋을 가져옵니다.
-
Git이 가져온 커밋 위에 브랜치의 커밋을 적용합니다. 이 예시에서는
feature라는 브랜치가 생성된 후(주황색),main의 커밋 네 개(보라색)가feature브랜치로 가져옵니다:
대부분의 리베이스는 main에 대해 수행되지만 다른 브랜치에 대해서도 리베이스할 수 있습니다. 다른 원격 리포지터리를 지정할 수도 있습니다.
예를 들어 origin 대신 upstream.
git rebase는 커밋 기록을 다시 작성합니다. 공유 브랜치에서 충돌 및 복잡한 머지 충돌을 일으킬 수 있습니다.
기본 브랜치에 대해 브랜치를 리베이스하는 대신
git pull origin master 사용을 고려하세요. 풀은 다른 사람의 작업을 손상시킬 위험이 적으면서 유사한 효과를 냅니다.
리베이스#
Git을 사용하여 리베이스하면 각 커밋이 브랜치에 적용됩니다. 머지 충돌이 발생하면 해결하라는 메시지가 표시됩니다.
커밋에 대한 더 고급 옵션을 보려면 대화형 리베이스를 사용하세요.
사전 요구 사항:
- 브랜치에 강제 푸시할 권한이 있어야 합니다.
Git을 사용하여 대상 브랜치에 대해 브랜치를 리베이스하려면:
-
터미널을 열고 프로젝트 디렉토리로 변경합니다.
-
대상 브랜치의 최신 내용이 있는지 확인합니다. 이 예시에서 대상 브랜치는
main입니다:git fetch origin main -
브랜치를 체크아웃합니다:
git checkout my-branch -
선택 사항. 브랜치의 백업을 만듭니다:
git branch my-branch-backup이 시점 이후에
my-branch에 추가된 변경 사항은 백업 브랜치에서 복원하면 손실됩니다. -
main브랜치에 대해 리베이스합니다:git rebase origin/main -
머지 충돌이 있는 경우:
-
편집기에서 충돌을 해결합니다.
-
변경 사항을 스테이징합니다:
git add . -
리베이스를 계속합니다:
git rebase --continue
-
-
다른 사람의 커밋을 보호하면서 대상 브랜치에 변경 사항을 강제 푸시합니다:
git push origin my-branch --force-with-lease
대화형 리베이스#
대화형 리베이스를 사용하여 각 커밋을 처리하는 방법을 지정합니다. 다음 지침은 Vim 텍스트 편집기를 사용하여 커밋을 편집합니다.
대화형으로 리베이스하려면:
-
터미널을 열고 프로젝트 디렉토리로 변경합니다.
-
대상 브랜치의 최신 내용이 있는지 확인합니다. 이 예시에서 대상 브랜치는
main입니다:git fetch origin main -
브랜치를 체크아웃합니다:
git checkout my-branch -
선택 사항. 브랜치의 백업을 만듭니다:
git branch my-branch-backup이 시점 이후에
my-branch에 추가된 변경 사항은 백업 브랜치에서 복원하면 손실됩니다. -
GitLab UI의 머지 리퀘스트에서 Commits 탭에서 리베이스할 커밋 수를 확인합니다.
-
이 커밋들을 엽니다. 예를 들어 마지막 다섯 개의 커밋을 편집하려면:
git rebase -i HEAD~5Git이 터미널 텍스트 편집기에서 오래된 순서로 커밋을 엽니다. 각 커밋에는 수행할 작업, SHA, 커밋 제목이 표시됩니다. 예를 들어:
pick 111111111111 Second round of structural revisions pick 222222222222 Update inbound link to this changed page pick 333333333333 Shifts from H4 to H3 pick 444444444444 Adds revisions from editorial pick 555555555555 Revisions continue to build the concept part out # Rebase 111111111111..222222222222 onto zzzzzzzzzzzz (5 commands) # # Commands: # p, pick <commit> = use commit # r, reword <commit> = use commit, but edit the commit message # e, edit <commit> = use commit, but stop for amending # s, squash <commit> = use commit, but meld into previous commit # f, fixup [-C | -c] <commit> = like "squash" but keep only the previous -
i를 눌러 Vim의 편집 모드로 전환합니다.
-
화살표 키를 사용하여 편집하려는 커밋으로 커서를 이동합니다.
-
첫 번째를 제외한 각 커밋에서
pick을squash또는fixup(또는s또는f)으로 변경합니다. -
나머지 커밋에 대해 반복합니다.
-
편집 모드를 종료하고 저장 후 종료합니다:
- ESC를 누릅니다.
:wq를 입력합니다.
-
스쿼시 시 Git이 커밋 메시지를 편집하라고 요청합니다:
#으로 시작하는 줄은 무시되며 커밋 메시지에 포함되지 않습니다.- 현재 메시지를 유지하려면
:wq를 입력합니다. - 커밋 메시지를 편집하려면 편집 모드로 전환하여 변경한 다음 저장합니다.
-
대상 브랜치에 변경 사항을 푸시합니다.
-
리베이스 전에 대상 브랜치에 커밋을 푸시하지 않은 경우:
git push origin my-branch -
이미 커밋을 푸시한 경우:
git push origin my-branch --force-with-lease일부 작업은 브랜치를 변경하기 위해 강제 푸시가 필요합니다. 자세한 내용은 원격 브랜치에 강제 푸시를 참조하세요.
-
명령줄에서 충돌 해결#
각 변경 사항을 최대한 제어하려면 GitLab에서가 아니라 명령줄에서 로컬로 복잡한 충돌을 수정해야 합니다.
사전 요구 사항:
- 브랜치에 강제 푸시할 권한이 있어야 합니다.
-
터미널을 열고 기능 브랜치를 체크아웃합니다:
git switch my-feature-branch -
대상 브랜치에 대해 브랜치를 리베이스합니다. 이 예시에서 대상 브랜치는
main입니다:git fetch git rebase origin/main -
선호하는 코드 편집기에서 충돌이 있는 파일을 엽니다.
-
충돌 블록을 찾아 해결합니다:
- 유지할 버전(
=======전후)을 선택합니다. - 유지하지 않을 버전을 삭제합니다.
- 충돌 마커를 삭제합니다.
- 유지할 버전(
-
파일을 저장합니다.
-
충돌이 있는 각 파일에 대해 프로세스를 반복합니다.
-
변경 사항을 스테이징합니다:
git add . -
변경 사항을 커밋합니다:
git commit -m "Resolve merge conflicts"[!warning] 이 시점 전에
git rebase --abort를 실행하여 프로세스를 중지할 수 있습니다. Git이 리베이스를 중단하고git rebase를 실행하기 전 상태로 브랜치를 롤백합니다.git rebase --continue를 실행한 후에는 리베이스를 중단할 수 없습니다. -
리베이스를 계속합니다:
git rebase --continue -
원격 브랜치에 변경 사항을 강제 푸시합니다:
git push origin my-feature-branch --force-with-lease
원격 브랜치에 강제 푸시#
커밋 스쿼시, 브랜치 리셋, 리베이스와 같은 복잡한 Git 작업은 브랜치 기록을 다시 작성합니다. Git은 이러한 변경 사항에 대해 강제 업데이트가 필요합니다.
강제 푸시는 다른 사람의 변경 사항을 파괴할 위험이 있으므로 공유 브랜치에서는 권장하지 않습니다.
브랜치가 보호된 경우 다음을 하지 않으면 강제 푸시할 수 없습니다:
- 보호를 해제합니다.
- 강제 푸시를 허용합니다.
자세한 내용은 보호된 브랜치에서 강제 푸시 허용을 참조하세요.
백업된 브랜치 복원#
리베이스 또는 강제 푸시가 실패하면 백업에서 브랜치를 복원합니다:
-
올바른 브랜치에 있는지 확인합니다:
git checkout my-branch -
브랜치를 백업으로 리셋합니다:
git reset --hard my-branch-backup
리베이스 후 승인#
브랜치를 리베이스하면 커밋을 추가한 것입니다. 프로젝트가 커밋을 추가하는 사용자의 승인을 방지하도록 구성된 경우 리베이스한 머지 리퀘스트를 승인할 수 없습니다. 또한 이전에 커미터였고 이전에 승인할 수 없었던 사용자가 이제 변경 사항을 승인할 수 있게 될 수 있습니다.
또한 승인 후 리베이스를 수행한 사용자는 여전히 머지 리퀘스트를 승인한 것으로 표시될 수 있습니다. 그러나 사용자의 승인은 머지 리퀘스트에 필요한 승인 수에 포함되지 않습니다.
관련 항목#
문제 해결#
CI/CD 파이프라인 문제 해결 정보는 CI/CD 파이프라인 디버깅을 참조하세요.
/rebase 빠른 작업 후 Unmergeable state#
/rebase 명령은 백그라운드 태스크를 예약합니다. 태스크는 대상 브랜치의 최신 커밋에서 소스 브랜치의 변경 사항을 리베이스하려고 시도합니다.
/rebase 빠른 작업을 사용한 후 이 오류가 표시되면 리베이스를 예약할 수 없습니다:
This merge request is currently in an unmergeable state, and cannot be rebased.
이 오류는 다음 조건 중 하나가 참인 경우 발생합니다:
- 소스 브랜치와 대상 브랜치 간에 충돌이 있습니다.
- 소스 브랜치에 커밋이 없습니다.
- 소스 또는 대상 브랜치가 존재하지 않습니다.
- 오류가 발생하여 diff가 생성되지 않았습니다.
unmergeable state 오류를 해결하려면:
- 머지 충돌을 해결합니다.
- 소스 브랜치가 존재하고 커밋이 있는지 확인합니다.
- 대상 브랜치가 존재하는지 확인합니다.
- diff가 생성되었는지 확인합니다.
/rebase 후 /merge 빠른 작업 무시#
/rebase가 사용되면 소스 브랜치가 리베이스되기 전에 머지되거나 삭제되는 경쟁 조건을 피하기 위해 /merge가 무시됩니다.
