Git rebase 및 강제 푸시

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

Merge 충돌이 있는 경우 리베이스하여 해결할 수 있습니다.

리베이스 중 발생하는 일

리베이스시:

  1. Git은 먼저 대상 브랜치에 제출된 모든 커밋을 가져옵니다.
  2. 그러고나서 귀하의 브랜치에 있는 커밋을 가져온 브랜치의 모든 커밋 위에 쌓습니다.

    Git rebase illustration

대부분의 리베이스는 main을 대상으로 하지만, 다른 브랜치(예: release-15-3)를 대상으로 하거나 origin 대신에 다른 원격 리포지터리(예: upstream)를 지정할 수 있습니다.

caution
git rebase는 커밋 히스토리를 다시 작성합니다. 공유된 브랜치에서 이 작업을 하는 것은 위험할 수 있습니다. 이로 인해 복잡하고 해결하기 어려운 Merge 충돌이 발생할 수 있습니다. 기본 브랜치에 대해 귀하의 브랜치를 리베이스하는 대신에, 귀하의 브랜치를 대신에 Merge하는 것(git pull origin master)을 고려해보세요. Merge은 덜 위험하면서도 유사한 효과를 가집니다.

Git을 사용한 리베이스

Git을 사용하여 리베이스할 때 각 커밋이 귀하의 브랜치에 적용됩니다. Merge 충돌이 발생하는 경우 해결해야 합니다.

커밋에 대해 더 고급 옵션을 원한다면, 대화식 리베이스를 사용하세요.

필수 조건:

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

Git을 사용하여 귀하의 브랜치를 대상 브랜치에 대해 리베이스하려면 다음을 수행하세요:

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

    git fetch origin main
    
  3. 귀하의 브랜치를 체크아웃합니다:

    git checkout my-branch
    
  4. 선택 사항. 브랜치의 백업을 만듭니다:

    git branch my-branch-backup
    

    이 지점 이후에 추가된 변경 사항은 백업 브랜치를 복원할 경우 손실됩니다.

  5. main 브랜치에 대해 리베이스합니다:

    git rebase origin/main
    
  6. Merge 충돌이 있는 경우:
    1. 에디터에서 충돌을 해결합니다.

    2. 파일을 추가합니다:

      git add .
      
    3. 리베이스를 계속합니다:

      git rebase --continue
      
  7. 귀하의 변경 사항을 대상 브랜치에 강제 푸시하되, 다른 사람의 커밋을 보호합니다:

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

UI에서 리베이스

GitLab UI에서 Merge Request을 리베이스할 수 있습니다.

필수 조건:

  • Merge 충돌이 없어야 합니다.
  • 소스 프로젝트에 대해 최소한 Developer 역할이 있어야 합니다. 이 역할을 가지고 있어야 소스 프로젝트의 소스 브랜치에 푸시할 권한이 부여됩니다.
  • Merge Request이 포크에 있는 경우, 해당 포크는 해당 프로젝트의 成员로부터의 커밋을 허용해야 합니다(해당 링크 참조).

UI에서 리베이스하려면:

  1. Merge Request으로 이동합니다.
  2. 댓글에 /rebase를 입력합니다.
  3. 댓글을 선택합니다.

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

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

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

필수 조건:

  • 이 지침에 따라 진행하려면 Vim이 여러분의 텍스트 에디터여야 합니다.

대화식 리베이스를 수행하려면:

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

    git fetch origin main
    
  3. 귀하의 브랜치를 체크아웃합니다:

    git checkout my-branch
    
  4. 선택 사항. 브랜치의 백업을 만듭니다:

    git branch my-branch-backup
    

    이 지점 이후에 추가된 변경 사항은 백업 브랜치를 복원할 경우 손실됩니다.

  5. GitLab UI에서 Merge Request에서 리베이스할 커밋 수를 확인하여 커밋 탭을 볼 수 있습니다.

  6. 이러한 커밋을 엽니다. 예를 들어, 브랜치의 마지막 다섯 개의 커밋(HEAD~5)을 편집하려면 다음을 입력합니다:

    git rebase -i HEAD~5
    

    Git은 터미널 텍스트 에디터에서 가장 오래된 커밋부터, 오래된순으로 가장 최신 커밋까지 엽니다. 각 커밋마다 취해야 할 동작, SHA, 커밋 제목이 표시됩니다.

    pick 111111111111 구조적 수정의 두 번째 라운드
    pick 222222222222 변경된 페이지의 수신 링크 업데이트
    pick 333333333333 H4에서 H3로 전환
    pick 444444444444 편집의 리비전 추가됨
    pick 555555555555 개념 부분을 계속해서 빌드
       
    # zzzzzzzzzzzz로부터 111111111111..222222222222를 리베이스합니다 (5개 명령)
    #
    # 명령:
    # p, pick <commit> = 커밋 사용
    # r, reword <commit> = 커밋 사용, 그러나 커밋 메시지 편집
    # e, edit <commit> = 커밋 사용, 그러나 수정 중단
    # s, squash <commit> = 커밋 사용, 그러나 이전 커밋과 통합
    # f, fixup [-C | -c] <commit> = "squash"와 유사하지만 이전 커밋만 유지
    
  7. Vim의 편집 모드로 전환하려면 i를 누릅니다.
  8. 키보드 화살표를 사용하여 디렉터리에서 두 번째 커밋으로 이동합니다.
  9. picksquash 또는 fixup(‘s’ 또는 ‘f’)으로 변경합니다.
  10. 나머지 커밋에 대해서도 똑같이 수행합니다. 첫 번째 커밋은 pick으로 남겨 둡니다.
  11. 편집 모드를 끝내고 저장하고 종료합니다:

    • ESC를 누릅니다.
    • :wq를 입력합니다.
  12. 통합하는 경우, 커밋 메시지가 출력되므로 편집할 기회가 주어집니다.

    • #로 시작하는 모든 줄은 무시되어 커밋 메시지에 포함되지 않습니다. 그 외의 모든 것이 포함됩니다.
    • 해당 내용을 그대로 두려면 :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
    

리베이스 후 승인

브랜치를 리베이스하면 추가된 커밋이 있습니다. 만약 프로젝트가 사용자가 커밋을 추가하는 것을 방지하도록 설정되어 있다면 커밋을 추가하는 사용자의 승인을 방지하는 경우에는 리베이스된 Merge Request을 승인할 수 없습니다.

관련 주제

문제 해결

/rebase 퀵 액션 후 Merge할 수 없는 상태

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

이 Merge Request은 현재 Merge할 수 없는 상태이며, 리베이스할 수 없습니다.

이 오류는 다음 중 하나 이상의 조건이 참일 때 발생합니다:

  • 소스 브랜치와 대상 브랜치 사이에 충돌이 있습니다.
  • 소스 브랜치에 커밋이 없습니다.
  • 소스 또는 대상 브랜치 중 하나가 존재하지 않습니다.
  • 차이가 생성되지 않도록 에러가 발생했습니다.

Merge할 수 없는 상태 오류 해결 방법:

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

/rebase/merge 퀵 액션이 무시됨

/rebase를 사용하면 경합 조건이 발생하여 소스 브랜치가 리베이스되거나 삭제되기 전에 /merge가 무시됩니다.