문제 상황
GitHub에서 저장소를 생성한 후, 저장소 주소를 원격(remote)에 추가(git remote add origin https://github…..)하고, 로컬에서도 정상적으로 초기화(git init)했습니다. 그런데 git pull 또는 git merge 명령어가 정상적으로 동작하지 않았고, git push origin main 명령을 실행할 때 아래와 같은 에러가 발생했습니다.
[rejected] main -> main (non-fast-forward)
error: 레퍼런스를 'git@github.com:'에 푸시하는데 실패했습니다
힌트: 현재 브랜치의 끝이 리모트 브랜치보다 뒤에 있으므로 업데이트가
힌트: 거부되었습니다. 푸시하기 전에 ('git pull ...' 등 명령으로) 리모트
힌트: 변경 사항을 포함하십시오.
힌트: 자세한 정보는 'git push --help'의 "Note about fast-forwards' 부분을
힌트: 참고하십시오.
원인
non-fast-forward 에러는 `로컬 브랜치의 커밋 히스토리가 원격 브랜치의 히스토리와 일치하지 않아`, 단순히 "앞으로 나아가는(fast-forward)" 방식으로 업데이트할 수 없을 때 발생합니다.
해결 방법
첫 번째 방법: --allow-unrelated-histories 옵션 추가
Git은 기본적으로 로컬 저장소와 원격 저장소의 커밋 히스토리 전혀 연관되지 않은 경우, 히스토리를 병합하는 것을 거부합니다. 하지만 `git pull --allow-unrelated-histories `를 하면 가능하게 됩니다.
git pull --allow-unrelated-histories origin main
pull할 권한이 없는 문제가 있거나, 병합 결과가 예상과 다르게 복잡해질 수 있으므로, 병합 후 커밋 내역을 잘 확인해야 합니다.
두 번째 방법: 과거 커밋 내역 삭제
과거 커밋 내역을 삭제하고 싶다면, `git reset` 을 사용할 수 있습니다.
최근의 커밋 하나만 삭제:
git reset HEAD^
최근부터 n 개의 커밋 삭제:
git reset HEAD~n
이 방법은 로컬 히스토리를 재작성하는 것이므로, 이미 원격에 푸쉬된 상태라면 강제 푸쉬가 필요합니다.
세 번째 방법: --force 옵션을 사용하여 강제 푸쉬
푸쉬에서 `--force` 옵션을 사용하면 로컬의 커밋 상태로 원격 저장소를 완전히 덮어쓸 수 있습니다.
git push --force origin feature/OOO
이 방법은 원격 저장소의 이전 커밋을 덮어쓰게 되므로, 다른 협업자들이 영향을 받을 수 있으니 협의 후에 진행하는 것이 좋습니다. 가능하면 `--force-with-lease` 옵션을 사용하는 것이 안전합니다.
일반적인 `--force` 옵션은 로컬 커밋 내역으로 원격 브랜치를 무조건 덮어쓰게 되는데, 이 경우 다른 사람이 원격 브랜치에 추가한 변경사항도 함께 덮어쓰게 될 위험이 있습니다.
반면 `--force-with-lease`는 원격 브랜치의 현재 상태가 내가 마지막으로 확인했던 상태와 동일할 때만 강제 푸쉬를 허용합니다. 즉, 만약 다른 사람이 원격 브랜치에 변경사항을 추가했다면 푸쉬를 거부하여, 내 강제 푸쉬로 인해 다른 사람의 작업이 덮어쓰여지는 것을 방지할 수 있습니다.
요약하면,
- `--force`: 로컬 상태로 무조건 원격 브랜치를 덮어쓰며 위험할 수 있음
- `--force-with-lease`: 원격 저장소의 상태를 확인하고, 내가 마지막으로 알던 상태와 동일할 때만 강제로 푸쉬하여 안전하게 업데이트함
'Etc' 카테고리의 다른 글
스프링 통합 테스트에서 Kafka를 지원하는 방법 (@EmbeddedKafka, @ConditionalOnProperty) (0) | 2025.05.12 |
---|---|
ChatGPT로 간단한 웹사이트 만들기 - 3 (0) | 2023.04.25 |
ChatGPT로 간단한 웹사이트 만들기 - 2 (0) | 2023.04.25 |
ChatGPT로 간단한 웹사이트 만들기 - 1 (0) | 2023.04.22 |
IT 개인 블로그 추천 (백엔드 / 알고리즘) (1) | 2022.07.26 |