🐛이슈
- 발생한 오류 copy & paste
- 오류가 발생한 상황 간략히 설명
프로젝트 기초 세팅을 끝내고 깃허브 리포지토리에 git push를 하려고 했다. 아래 명령어를 순서대로 입력해서 원격 저장소와 연동하고, git pull을 받은 뒤 git push를 해서 진행하고 있었다.
$ git init
$ git remote add origin {리포지토리 주소}
$ git add .
$ git commit -m "git init"
$ git pull origin main
$ git push origin main
그런데 git pull까진 정상적으로 작동했지만, git push에서 아래 오류가 발생했다.
kej43@DESKTOP-HPA6R33 MINGW64 ~/HyThon (main)
$ git push origin main
To https://github.com/2024-HY-THON/team3-be.git
! [rejected] main -> main (fetch first)
error: failed to push some refs to 'https://github.com/2024-HY-THON/team3-be.git'
hint: Updates were rejected because the remote contains work that you do not
hint: have locally. This is usually caused by another repository pushing to
hint: the same ref. If you want to integrate the remote changes, use
hint: 'git pull' before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for details.
😓원인과 해결방안
- 오류가 발생한 원인 간략히 설명
- 해결방안 설명
아래 오류 메시지를 읽어보면 왜 실패했는지 파악할 수 있다.
hint: Updates were rejected because the remote contains work that you do not have locally. This is usually caused by another repository pushing to the same ref. If you want to integrate the remote changes, use 'git pull' before pushing again. See the 'Note about fast-forwards' in 'git push --help' for details.
로컬 디렉터리를 살펴보니 원격 리포지토리엔 존재하는 README.md 파일이 없는 걸 확인할 수 있었다. 이후 git pull을 다시 입력해 README.md를 받아오려고 했지만 변함이 없었다.
- git pull origin main은 origin main의 내용을 로컬 main에 병합한다.
- git fetch 후 git merge 실행하는 것과 동일하다.
- 이때, 공통된 조상이 없는 히스토리는 git merge로 해결할 수 없다. 따라서 이미 만들어진 리포지토리와 로컬 내용을 합치려면 pull만으론 해결할 수 없다.
$ git pull origin main
해결방안1
아래 명령어를 입력하면 원격과 로컬 리포지토리의 내용이 다르더라도 로컬의 내용을 원격에 덮을 수 있다. 이걸 쓰면 git push는 무조건 성공하긴 한다.
- 대신 원격 리포지토리의 모든 커밋 내용이 사라지기 때문에 없어져도 괜찮다고 판단했을 때만 사용해야 한다.
$ git push -f origin main
해결방안2
git pull --rebase를 사용한다.
- git fetch 후 git rebase 실행하는 것과 동일하다. git merge가 아닌 git rebase를 실행하기 때문에 공통된 조상이 아니어도 합칠 수 있다.
- 기존 git pull은 두 브랜치의 히스토리와 merge 커밋 모두 남겨두지만, git pull --rebase는 merge 커밋을 남기지 않아 히스토리를 깔끔하게 만들 수 있다.
When true, rebase the current branch on top of the upstream branch after fetching. If there is a remote-tracking branch corresponding to the upstream branch and the upstream branch was rebased since last fetched, the rebase uses that information to avoid rebasing non-local changes.
When set to merges, rebase using git rebase --rebase-merges so that the local merge commits are included in the rebase (see git-rebase(1) for details).
When false, merge the upstream branch into the current branch.
When interactive, enable the interactive mode of rebase.
See pull.rebase, branch.<name>.rebase and branch.autoSetupRebase in git-config(1) if you want to make git pull always use --rebase instead of merging.
출처: git pull --help로 확인할 수 있는 문서
$ git pull origin main --rebase
나는 이 방법을 써서 문제를 해결했다.
해결방안3
git pull origin main --allow-unrelated-histories을 사용한다.
- 위에서 말했듯이 공통된 조상이 없는 히스토리는 git merge로 해결할 수 없다. --allow-unrelated-histories 옵션을 붙이면 서로 독립적이고 관련된 기록이 없는 두 저장소를 합칠 수 있다.
By default, git merge command refuses to merge histories that do not share a common ancestor. This option can be used to override this safety when merging histories of two projects that started their lives independently. As that is a very rare occasion, no configuration variable to enable this by default exists and will not be added.
Only useful when merging.
출처: git pull --help로 확인할 수 있는 문서
🪽참고자료
- 링크 기록