🚀 프로젝트/집플래닛

집플래닛 트러블 슈팅 | Git 충돌 해결 트러블슈팅: git push 오류 및 rebase 문제 해결

seheej 2024. 10. 16. 11:32

상황 설명

React 프로젝트를 진행하던 중, feat/mypage 브랜치에서 코드 변경사항을 원격 저장소에 푸시하려고 했습니다. 아래 명령어를 사용해 커밋 후 푸시를 시도했습니다:

git add .
git commit -m "add: 마이페이지 수정/삭제 버튼 기능 연결, 메인페이지 수정/삭제 버튼 감춤, 메인페이지 배너 영역 추가, css 수정"
git push origin feat/mypage

 

그러나 푸시 도중 다음과 같은 오류가 발생했습니다:

! [rejected]        feat/mypage -> feat/mypage (non-fast-forward)
error: failed to push some refs to 'https://github.com/jigong2024/home-planet.git'
hint: Updates were rejected because the tip of your current branch is behind

 

원격 저장소의 feat/mypage 브랜치에 이미 업데이트된 커밋이 존재하고, 로컬 브랜치의 커밋이 원격 브랜치보다 뒤쳐져 있기 때문에 발생한 오류였습니다.

 

 

문제 원인 분석

오류 메시지는 원격 브랜치의 히스토리가 로컬 브랜치보다 앞서있기 때문에, 로컬에서 변경한 내용을 푸시할 수 없다는 뜻입니다. 이 문제를 해결하려면 먼저 원격 브랜치의 변경사항을 로컬 브랜치에 통합해야 합니다.

저는 git pull origin feat/mypage 명령어를 실행해 원격의 변경사항을 가져오려고 했으나, 리베이스가 기본 설정되어 있어 feat/mypage* (Rebasing) 상태로 전환되었습니다. 그리고 제가 작업한 코드가 사라져 당황스러웠습니다.

 

 

 

해결 방법

    1. 리베이스 설정 확인 및 변경
      Git에서 git pull 명령어의 기본 설정이 리베이스로 되어 있었기 때문에, 병합 대신 리베이스가 수행되었습니다. 리베이스로 인해 커밋 히스토리를 다시 정렬하는 과정에서 충돌이 발생했고, 리베이싱 브랜치가 생성되었습니다. 먼저, 리베이스 설정을 확인하고 병합으로 변경하였습니다.
      1. git config pull.rebase
        # 결과: true
        
        # 리베이스 설정을 병합으로 변경
        git config pull.rebase false
        
      2. 리베이스 중단 및 푸시 시도
        리베이스 상태에서 진행하기 어렵다고 판단되어, git rebase --abort 명령어로 리베이스를 중단한 후, 다시 푸시를 시도했습니다.하지만 여전히 non-fast-forward 오류가 발생했습니다. 이 오류는 원격 브랜치의 커밋 히스토리와 로컬 브랜치의 히스토리가 충돌하는 상황에서 발생합니다.
      3. git rebase --abort
        git push origin feat/mypage
      4. 강제 푸시 (--force)
        최종적으로, 로컬 브랜치의 커밋을 원격 브랜치에 덮어씌우기 위해 --force 옵션을 사용해 강제로 푸시했습니다.
      5. git push --force origin feat/mypage
        

        이를 통해 원격 브랜치에 성공적으로 푸시되었습니다.
        Enumerating objects: 66, done.
        Counting objects: 100% (66/66), done.
        Delta compression using up to 16 threads
        Compressing objects: 100% (34/34), done.
        Writing objects: 100% (38/38), 6.62 KiB | 3.31 MiB/s, done.

 

 

주의사항 및 팁

  1. 다른 팀원의 작업을 덮어쓰지 않도록 주의
    • --force를 사용하면 원격 저장소의 커밋 히스토리를 덮어쓰게 됩니다. 이 과정에서 다른 팀원의 커밋이 사라질 수 있으니, 협업 중인 브랜치에서는 반드시 충돌을 해결한 후 push해야 합니다.
  2. git pull --rebase로 최신 상태 유지
    • git pull을 사용할 때 --rebase 옵션을 추가하면, 내 로컬 커밋을 원격의 최신 커밋 뒤로 재배치해 충돌을 방지할 수 있습니다. rebase를 통해 충돌을 사전에 방지하고, push --force를 사용할 필요성을 줄일 수 있습니다.
  3. --force-with-lease를 사용해 안전하게 푸시
    • git push --force-with-lease는 원격 브랜치가 내가 예상한 상태일 때만 강제로 푸시하는 옵션입니다. 만약 원격 브랜치에 예상치 못한 커밋이 있을 경우, 푸시가 거부됩니다. 이 방법은 다른 팀원의 작업을 실수로 덮어쓰는 것을 방지하는 안전한 대안입니다.
  4. 로컬 변경 사항 백업
    • push --force 사용 전에 로컬 변경 사항을 백업하는 것이 중요합니다. git stash를 통해 변경 사항을 임시 저장하거나, 별도의 브랜치에 커밋해놓으면 실수로 데이터 손실이 발생했을 때 복구할 수 있습니다.
  5. 깃 로그 확인 (git log)
    • git push --force를 하기 전에, 로컬과 원격의 커밋 차이를 확인하는 것이 중요합니다. git log나 git diff를 통해 현재 내 로컬 브랜치와 원격 브랜치의 차이를 살펴보고, 필요한 경우 충돌을 수동으로 해결한 뒤 푸시를 진행하세요.

 


 

git push --force는 언제 사용해야 하나?

1. 브랜치에 이격이 발생했을 때

브랜치에 이격이 발생했다는 것은 로컬 브랜치와 원격 브랜치의 커밋 히스토리가 달라졌다는 뜻입니다. 특히, 내가 작업 중인 브랜치에 원격에서 변경 사항이 생겼는데, 이를 반영하지 않고 바로 push를 시도하면 non-fast-forward 오류가 발생할 수 있습니다. 이때 강제로 푸시할 수 있는 방법이 push --force입니다.

2. Git의 파일 크기 제한

Git은 기본적으로 100MB 이상의 파일을 업로드하지 못하도록 제한을 두고 있습니다. 만약 큰 파일을 커밋하려다 오류가 발생하여 수정한 경우, 잘못된 커밋을 수정해 강제로 푸시해야 할 때도 --force를 사용할 수 있습니다. 하지만 이 경우도 가능하면 큰 파일을 버전 관리하지 않도록 주의해야 합니다.

3. 일상적으로는 사용하지 않음

push --force는 일상적인 상황에서는 잘 사용하지 않는 것이 좋습니다. 그 이유는 원격 저장소에 있는 코드나 히스토리를 덮어써버리는 위험이 있기 때문입니다. 특히 협업 프로젝트에서 다른 팀원의 작업을 손상시킬 수 있는 위험이 큽니다.

 


git push --force를 사용하면?

1. 로컬의 상황을 원격에 덮어씀

push --force를 사용하면 로컬 브랜치의 상태로 원격 브랜치를 강제로 덮어씁니다. 기존 원격 브랜치의 히스토리와 관계없이, 로컬의 커밋 히스토리가 그대로 반영됩니다. 이 과정에서 원격 브랜치에 남아있던 모든 변경 사항이 무시됩니다.

2. 다른 사람의 코드가 사라질 수 있음

협업 프로젝트에서 --force를 잘못 사용하면 다른 팀원이 작업한 커밋이 삭제될 수 있습니다. 만약 여러 명이 같은 브랜치에서 작업 중이라면, 그들의 변경 사항이 로컬 커밋에 의해 덮어져 사라질 위험이 있습니다. 따라서 협업 환경에서는 가능한 --force 대신 --force-with-lease를 사용하는 것이 더 안전합니다.

 


결론

이번 트러블슈팅 경험은 Git에서 발생하는 충돌 문제와 그 해결 과정을 배우는 중요한 경험이었습니다. 특히, 협업 환경에서 Git을 사용할 때는 rebase와 merge 설정에 대한 이해가 필수적입니다. Git 충돌을 겪고 해결하는 과정을 통해 Git 사용 방법에 대한 이해가 더 깊어졌습니다.