마크다운: 병합 충돌 해결을 위한 리베이스

Git에서 리베이스는 다른 브랜치의 내용으로 브랜치를 업데이트합니다. 리베이스는 브랜치의 변경 내용이 대상 브랜치의 변경 내용과 충돌하지 않는지 확인합니다.

만약 병합 충돌이 발생하면 리베이스하여 해결할 수 있습니다.

리베이스하는 동안 발생하는 일들

리베이스를 할 때:

  1. Git은 초기에 브랜치를 생성한 후에 대상 브랜치에 제출된 모든 커밋을 가져옵니다.
  2. Git은 브랜치에 있는 모든 커밋을 해당 브랜치에서 가져온 모든 커밋 위에 쌓습니다:

    Git 리베이스 그림

대부분의 리베이스는 main을 대상으로 수행되지만, release-15-3와 같은 다른 브랜치에 대해 리베이스할 수 있습니다. 또한 origin 대신 upstream과 같은 다른 원격 저장소를 지정할 수도 있습니다.

경고: git rebase는 커밋 기록을 다시 쓰기 때문에 다른 사람들이 사용하는 브랜치에서는 주의해야 합니다. 복잡하고 해결하기 어려운 병합 충돌을 일으킬 수 있습니다. 기본 브랜치 대신에 브랜치를 리베이스하기 보다는 끌어오는 것(git pull origin master)을 고려해보세요. 끌어오기는 다른 사람들의 작업을 위해 리스크가 적은 영향을 끼칩니다.

Git을 사용하여 리베이스

Git을 사용하여 리베이스할 때 각 커밋이 브랜치에 적용됩니다. 병합 충돌이 발생하면 충돌을 해결하라는 메시지가 표시됩니다.

커밋에 대해 더 고급화된 옵션이 필요하면 대화형 리베이스를 수행하세요.

준비 사항:

  • 브랜치에 강제 푸시할 수 있는 권한이 있어야 합니다.

Git을 사용하여 브랜치를 대상 브랜치에 리베이스하려면:

  1. 터미널을 열고 프로젝트로 이동하세요.
  2. 대상 브랜치의 최신 내용을 확인하세요. 이 예에서 대상 브랜치는 main입니다:

    git fetch origin main
    
  3. 브랜치를 확인하세요:

    git checkout my-branch
    
  4. 선택 사항. 브랜치를 백업하세요:

    git branch my-branch-backup
    

    이후 my-branch에 추가된 변경 내용은 백업 브랜치에서 복원할 수 없습니다.

  5. 메인 브랜치를 대상으로 리베이스하세요:

    git rebase origin/main
    
  6. 만약 병합 충돌이 존재한다면:
    1. 에디터에서 충돌을 해결하세요.

    2. 파일을 추가하세요:

      git add .
      
    3. 리베이스를 계속하세요:

      git rebase --continue
      
  7. 타겟 브랜치로 변경 사항을 강제로 푸시하세요. 다른 사람의 커밋을 보호하면서:

    git push origin my-branch --force-with-lease
    

UI에서 리베이스

GitLab UI에서 병합 요청을 리베이스할 수 있습니다.

준비 사항:

  • 병합 충돌이 없어야 합니다.
  • 소스 프로젝트에 대한 Developer 권한이 있어야 합니다. 이 권한을 갖는 유저는 소스 프로젝트의 소스 브랜치에 푸시할 수 있는 권한을 부여합니다.
  • 만약 병합 요청이 포크에 있다면, 포크가 상위 프로젝트의 멤버로부터 커밋을 허용해야 합니다(멤버 허용하기).

UI에서 리베이스하려면:

  1. 병합 요청으로 이동하세요.
  2. 댓글란에 /rebase를 입력하세요.
  3. 댓글 달기를 선택하세요.

GitLab은 브랜치를 기본 브랜치에 대해 리베이스하도록 예약하고 가능한 한 빨리 실행합니다.

Git을 사용하여 대화형 리베이스

각 커밋을 어떻게 처리할 지를 지정하려면 대화형 리베이스를 사용하세요. 대화형 리베이스는 명령줄에서 수행해야 합니다.

준비 사항:

  • 이 지침을 따르려면 Vim이 여러분의 텍스트 편집기여야 합니다.

대화형 리베이스를 위해:

  1. 터미널을 열고 프로젝트로 이동하세요.
  2. 대상 브랜치의 최신 내용을 확인하세요. 이 예에서 대상 브랜치는 main입니다:

    git fetch origin main
    
  3. 브랜치를 확인하세요:

    git checkout my-branch
    
  4. 선택 사항. 브랜치를 백업하세요:

    git branch my-branch-backup
    

    이후 my-branch에 추가된 변경 내용은 백업 브랜치에서 복원할 수 없습니다.

  5. GitLab UI에서 병합 요청에서 얼마나 많은 커밋을 리베이스할 것인지 커밋 탭으로 확인하세요.

  6. 이러한 커밋을 엽니다. 예를 들어, 브랜치에서 마지막 다섯 개의 커밋(HEAD~5)을 수정하려면 다음과 같이 입력하세요:

    git rebase -i HEAD~5
    

    Git은 마지막 다섯 개의 커밋을 최신 커밋부터 오래된 커밋까지 터미널 텍스트 편집기에서 엽니다. 각 커밋은 해당 커밋에 대한 동작, SHA, 커밋 제목을 보여줍니다:

    pick 111111111111 구조적 수정의 두 번째 라운드
    pick 222222222222 이 변경된 페이지로의 인바운드 링크를 업데이트
    pick 333333333333 H4에서 H3로 변경
    pick 444444444444 편집 내용에서 수정 사항 추가
    pick 555555555555 컨셉 부분을 계속해서 변경 사항을 추가함
    
    # 111111111111..222222222222을 zzzzzzzzzzzz에 리베이스하는 것 (5 명령어)
    #
    # 명령어:
    # p, pick <commit> = 커밋 사용
    # r, reword <commit> = 커밋 사용, 그러나 커밋 메시지 편집
    # e, edit <commit> = 커밋 사용, 그러나 수정 중지
    # s, squash <commit> = 커밋 사용, 그러나 이전 커밋과 결합
    # f, fixup [-C | -c] <commit> = "squash"와 같지만 이전 커밋만 유지
    
  7. i를 눌러 Vim의 편집 모드로 전환하세요.
  8. 키보드 화살표를 사용하여 목록에서 두 번째 커밋으로 이동하세요.
  9. picksquash 또는 fixup(s 또는 f)로 변경하세요.
  10. 나머지 커밋도 동일하게 변경하세요. 첫 번째 커밋은 pick으로 남겨두세요.
  11. 편집 모드를 끝내고 저장한 후 종료하세요:

    • ESC를 누릅니다.
    • :wq를 입력하세요.
  12. 결합을 하는 경우, Git은 커밋 메시지를 출력하여 편집할 기회를 제공합니다:

    • #로 시작하는 모든 줄은 무시되고 커밋 메시지에 포함되지 않습니다. 다른 내용은 모두 포함됩니다.
    • 그대로 두려면 :wq를 입력하세요. 커밋 메시지를 편집하려면 편집 모드로 전환하여 커밋 메시지를 편집하고 저장하세요.
  13. 타겟 브랜치에 커밋하세요.

    • 리베이스하기 전에 커밋을 타겟 브랜치에 푸시하지 않았다면, 강제 푸시 없이 변경 사항을 푸시하세요:

      git push origin my-branch
      
    • 이미 이러한 커밋을 푸시했다면, 강제 푸시하세요:

      git push origin my-branch --force-with-lease
      

강제 푸시

Git에서 복잡한 작업은 원격 브랜치를 강제로 업데이트해야 하는 경우가 있습니다. 커밋을 합치거나 브랜치를 리셋하거나 리베이스하는 등의 작업은 브랜치의 이력을 다시 작성하게 됩니다. Git은 이러한 파괴적인 변경이 우연히 발생하는 것을 방지하기 위해 강제 업데이트를 요구합니다.

공유 브랜치에서는 강제 푸시를 권장하지 않습니다. 다른 사람의 변경 사항을 소멸시키게 될 수 있습니다.

만약 강제로 푸시하려는 브랜치가 보호된 상태인 경우 다음과 같은 조치를 취하지 않는 한 해당 브랜치에 강제로 푸시할 수 없습니다:

그런 다음 강제로 푸시하고 다시 보호 상태로 변경할 수 있습니다.

백업된 브랜치 복원

브랜치가 백업되었고 리베이스나 강제 푸시를 시도할 수 있습니다. 문제가 발생하면 해당 브랜치를 백업에서 복원할 수 있습니다:

  1. 올바른 브랜치에 있는지 확인하세요:

    git checkout my-branch
    
  2. 백업을 기준으로 브랜치를 리셋합니다:

    git reset --hard my-branch-backup
    

리베이스 후 승인

브랜치를 리베이스하면 새로운 커밋이 추가됩니다. 프로젝트가 커밋을 추가하는 사용자의 승인 방지로 구성되어 있는 경우 리베이스된 머지 요청에 대해 승인할 수 없습니다.

관련 주제

문제 해결

/rebase 퀵 액션 이후 병합 불가능 상태

/rebase 명령은 백그라운드 작업을 예약합니다. 해당 작업은 소스 브랜치의 변경 사항을 대상 브랜치의 최신 커밋에 리베이스하려고 합니다. /rebase 퀵 액션을 사용한 후에 이 오류가 표시된다면, 리베이스를 예약할 수 없습니다:

This merge request is currently in an unmergeable state, and cannot be rebased.

이 오류는 다음 중 하나 이상이 발생한 경우에 발생합니다:

  • 소스와 대상 브랜치 사이에 충돌이 있다.
  • 소스 브랜치에 커밋이 없습니다.
  • 소스나 대상 브랜치 중 하나가 존재하지 않습니다.
  • 오류로 인해 차이가 생성되지 않았습니다.

병합 불가능 상태 오류를 해결하려면:

  1. 충돌을 해결합니다.
  2. 소스 브랜치가 존재하고 커밋이 있는지 확인합니다.
  3. 대상 브랜치가 존재하는지 확인합니다.
  4. 차이가 생성되었는지 확인합니다.

/rebase 이후 /merge 퀵 액션이 무시됨

만약 /rebase를 사용한 후 /merge가 무시된다면, 소스 브랜치가 리베이스되거나 삭제되기 전에 레이스 조건을 피하기 위해 /merge가 무시됩니다.