Git push rejected 오류가 발생했을 때 로컬 브랜치와 원격 브랜치 이력을 비교하는 개념 이미지

원격 브랜치의 최신 커밋을 먼저 확인한 뒤 rebase 또는 merge 방식으로 정리하는 것이 안전합니다.


Git push rejected 오류가 의미하는 것

GitHub에 코드를 올리려고 git push를 실행했는데 rejected non-fast-forward 또는 Updates were rejected 메시지가 나오면, 대부분 로컬 브랜치가 원격 브랜치의 최신 커밋을 따라가지 못한 상태입니다. Git은 원격 저장소의 커밋이 사라질 수 있는 상황을 막기 위해 push를 거절합니다.


대표적인 오류 메시지는 아래와 비슷합니다.


! [rejected]        main -> main (non-fast-forward)
error: failed to push some refs to 'github.com:username/repository.git'
hint: Updates were rejected because the tip of your current branch is behind
hint: its remote counterpart. Integrate the remote changes before pushing again.

확인해야 할 지점은 원격 저장소에 로컬에는 없는 커밋이 있는지입니다. 그 상태에서 내 커밋을 그대로 밀어 넣으면 원격 이력이 덮일 수 있으므로, 먼저 원격 변경 사항을 가져온 뒤 내 커밋을 그 위에 다시 정리해야 합니다.


먼저 확인할 명령어 4가지

바로 git push --force를 입력하지 말고 현재 상태부터 확인해야 합니다. 특히 팀 저장소, 회사 저장소, main 브랜치에서는 강제 push가 다른 사람의 커밋을 지울 수 있습니다.


git status
git branch -vv
git remote -v
git log --oneline --graph --decorate --all -n 30

1. git status로 작업 중인 파일 확인

git status는 커밋하지 않은 변경 사항이 있는지 보여줍니다. 수정 중인 파일이 남아 있으면 pull, rebase, merge 과정에서 충돌이 더 복잡해질 수 있으므로 먼저 커밋하거나 stash로 임시 보관하는 것이 좋습니다.


git status

# 아직 커밋하기 애매한 변경 사항을 임시 보관
git stash push -m "before fixing push rejected"

2. git branch -vv로 현재 브랜치와 원격 추적 브랜치 확인

git branch -vv를 보면 현재 브랜치가 어느 원격 브랜치를 따라가고 있는지 확인할 수 있습니다. 예를 들어 로컬은 main인데 원격 추적 브랜치가 없거나 다른 브랜치를 보고 있다면 push 대상부터 정리해야 합니다.


3. git remote -v로 저장소 주소 확인

git remote -v 결과가 예상한 GitHub 저장소가 아니라면 push rejected가 아니라 잘못된 저장소 주소 문제일 수 있습니다. 저장소 주소가 바뀐 경우에는 Git remote origin 변경 방법에서 원격 주소를 먼저 정리하는 흐름으로 확인할 수 있습니다.


4. git log로 로컬과 원격 이력 비교

git log --oneline --graph --decorate --all은 로컬 브랜치와 원격 브랜치가 어디서 갈라졌는지 보여줍니다. 이 명령어를 보면 단순히 원격 커밋이 앞서 있는지, 서로 다른 커밋이 양쪽에 생겼는지 판단하기 쉽습니다.


Git push rejected가 발생하는 주요 원인

오류 메시지는 비슷해 보여도 원인은 몇 가지로 나뉩니다. 원인을 구분하면 해결 명령어를 더 안전하게 고를 수 있습니다.


상황 주요 원인 먼저 볼 명령어
팀원이 같은 브랜치에 먼저 push함 로컬 브랜치가 원격보다 뒤처짐 git fetch origin, git log --all
GitHub 웹에서 README, 파일, 설정을 수정함 원격 저장소에 로컬에 없는 커밋이 생김 git pull --rebase origin main
커밋 amend 또는 rebase 후 push함 이미 올라간 커밋 이력이 로컬에서 바뀜 git log --oneline --graph --all
다른 브랜치나 다른 저장소로 push함 브랜치 추적 또는 remote 주소가 맞지 않음 git branch -vv, git remote -v

가장 안전한 해결 순서: fetch 후 rebase

개인 작업 커밋을 원격 최신 커밋 위에 깔끔하게 올리고 싶다면 git pull --rebase 방식이 많이 쓰입니다. merge 커밋을 추가하지 않고 커밋 흐름을 직선에 가깝게 정리할 수 있기 때문입니다.


# 1. 원격 저장소의 최신 상태 가져오기
git fetch origin

# 2. 현재 브랜치를 원격 main 위로 다시 정리
git rebase origin/main

# 3. 문제가 없으면 다시 push
git push origin main

같은 흐름을 한 줄로 실행하면 아래처럼 쓸 수 있습니다.


git pull --rebase origin main
git push origin main

단, 기본 브랜치 이름이 master인 저장소라면 main 대신 master를 사용해야 합니다. 현재 브랜치 이름은 git branch 또는 git branch -vv로 확인할 수 있습니다.


커밋하지 않은 변경 사항이 있을 때

작업 중인 파일이 남아 있으면 rebase가 멈출 수 있습니다. 아직 커밋하기 애매한 수정이라면 stash로 임시 보관한 뒤 다시 적용합니다.


git stash push -m "before pull rebase"
git pull --rebase origin main
git stash pop
git push origin main

git stash pop 후 충돌이 날 수 있습니다. 이 경우 충돌 파일을 직접 정리하고 git add, git commit 또는 진행 중인 rebase 흐름에 맞는 명령어를 이어서 사용합니다.


충돌이 발생했을 때 해결 순서

git pull --rebase 중 같은 파일의 같은 부분을 여러 사람이 수정했다면 충돌이 발생합니다. 이때는 Git이 자동으로 어느 내용을 남길지 판단하지 못하므로 사용자가 직접 파일을 열어 정리해야 합니다.


CONFLICT (content): Merge conflict in app.js
error: could not apply 123abcd... update app logic

파일 안에는 보통 아래와 같은 표시가 생깁니다.


<<<<<<< HEAD
원격 브랜치 쪽 내용
=======
내 로컬 커밋 쪽 내용
>>>>>>> my commit

필요한 내용을 남기고 <<<<<<<, =======, >>>>>>> 표시를 모두 제거한 뒤 아래 순서로 진행합니다.


git add app.js
git rebase --continue
git push origin main

충돌 해결이 너무 복잡하거나 잘못 진행한 것 같다면 rebase를 중단하고 처음 상태로 돌아갈 수 있습니다.


git rebase --abort

merge 방식과 rebase 방식 차이

push rejected를 해결할 때 git pull만 사용할지, git pull --rebase를 사용할지 헷갈릴 수 있습니다. 둘 다 원격 변경 사항을 가져와 내 작업과 합치는 방법이지만 이력 모양이 달라집니다.


방식 명령어 특징 어울리는 상황
merge git pull origin main 원격 변경과 내 변경을 합치는 merge 커밋이 생길 수 있음 팀에서 merge 이력을 남기는 규칙을 사용할 때
rebase git pull --rebase origin main 내 커밋을 원격 최신 커밋 위로 다시 쌓음 커밋 이력을 깔끔하게 유지하고 싶을 때

초보자에게는 “우리 팀 저장소 규칙”이 가장 중요합니다. 팀에서 merge 방식을 쓰기로 했다면 merge를 따르고, 개인 프로젝트나 직선형 이력을 선호하는 저장소라면 rebase가 편합니다.


git pull rebase, merge, force-with-lease 차이를 비교하는 3단계 설명 이미지

rebase, merge, force-with-lease는 모두 Git 이력에 영향을 주므로 현재 브랜치와 원격 상태를 확인한 뒤 선택해야 합니다.


git push --force 대신 force-with-lease를 봐야 하는 경우

git push --force는 원격 브랜치를 내 로컬 이력으로 강제로 덮어쓸 수 있습니다. 개인 브랜치가 아니라 공유 브랜치에서 잘못 사용하면 다른 사람이 올린 커밋이 사라질 수 있으므로 바로 실행하면 안 됩니다.


이미 push한 커밋을 amend 했거나 rebase로 이력을 바꾼 뒤 원격 브랜치를 갱신해야 하는 특수한 상황이라면, 먼저 팀원과 확인하고 --force-with-lease를 검토합니다. 이 옵션은 내가 알고 있는 원격 브랜치 상태와 실제 원격 상태가 달라졌을 때 push를 막아주는 안전장치 역할을 합니다.


git fetch origin
git log --oneline --graph --decorate --all -n 30

# 공유 브랜치에서는 팀 규칙 확인 후 사용
git push --force-with-lease origin main

보호된 main 브랜치에서는 강제 push 자체가 막혀 있을 수 있습니다. 이 경우 로컬에서 억지로 해결하려 하기보다 pull request, branch protection, 리뷰 규칙을 따라야 합니다.


Windows, Mac, Linux에서 다른 점

push rejected를 해결하는 Git 명령어는 Windows, Mac, Linux에서 거의 같습니다. 차이는 명령어 자체보다 터미널 환경, 줄바꿈 설정, 파일명 대소문자 처리에서 자주 생깁니다.


  • Windows: Git Bash와 PowerShell 모두 사용할 수 있지만, 예제 명령어는 Git Bash 기준으로 따라 하면 편합니다.
  • Mac: 기본 터미널 또는 iTerm에서 같은 명령어를 사용할 수 있습니다. 파일명 대소문자만 바꾼 커밋은 주의가 필요합니다.
  • Linux: 서버나 컨테이너 안에서 작업할 때 현재 브랜치와 remote 주소를 먼저 확인하는 것이 좋습니다.
  • 줄바꿈 문제: 충돌이 과하게 보이면 core.autocrlf 설정을 확인합니다.

git config --get core.autocrlf

VSCode에서 push가 실패했을 때 확인할 것

VSCode의 Source Control 화면에서 Push 또는 Sync Changes를 눌렀는데 rejected 오류가 나올 수 있습니다. 이때도 원리는 같습니다. VSCode가 특별한 오류를 만든 것이 아니라 내부에서 Git 명령어를 실행하다가 원격 이력 충돌을 만난 것입니다.


  • 왼쪽 Source Control 패널에서 변경 파일이 남아 있는지 확인합니다.
  • 하단 상태바에서 현재 브랜치가 main, master, 작업 브랜치 중 무엇인지 확인합니다.
  • Sync Changes를 반복해서 누르기보다 터미널에서 git status, git pull --rebase origin main을 직접 실행합니다.
  • 충돌 파일은 VSCode의 Accept Current, Accept Incoming, Accept Both 버튼으로 정리할 수 있지만 최종 내용은 직접 읽고 확인해야 합니다.

VSCode에서 커밋, 푸시, 브랜치 흐름이 아직 익숙하지 않다면 하단의 관련 글에서 기본 흐름을 먼저 정리해 두면 같은 오류를 줄일 수 있습니다.


재발을 줄이는 설정과 작업 습관

push rejected 오류는 협업 저장소에서 흔히 발생합니다. 완전히 없애기는 어렵지만, 작업 시작 전 원격 변경 사항을 확인하는 습관만으로 대부분 줄일 수 있습니다.


# 작업 시작 전
git fetch origin
git status -sb

# 현재 브랜치가 원격보다 뒤처졌다면
git pull --rebase origin main

항상 rebase 방식으로 pull하고 싶다면 전역 설정을 사용할 수 있습니다. 다만 팀 규칙이 merge 중심이라면 개인 설정을 바꾸기 전에 저장소 운영 방식을 먼저 확인하는 것이 좋습니다.


git config --global pull.rebase true
git config --global rebase.autoStash true

처음 이 오류를 만났다면 아래 기준부터 적용하면 됩니다.


  • push가 거절되면 먼저 git statusgit branch -vv를 본다.
  • 원격 커밋을 가져오지 않은 상태에서 --force를 쓰지 않는다.
  • 팀 브랜치에서는 rebase, force push 전에 팀 규칙을 확인한다.
  • 충돌 표시가 생기면 표시 줄을 지우는 것이 아니라 남길 코드를 판단한다.
  • main 브랜치에 직접 push하지 않는 저장소라면 pull request 흐름을 따른다.

공식 자료로 더 확인하기

Git push rejected 오류는 로컬 저장소와 원격 저장소의 이력 차이에서 발생하므로, 명령어를 실행하기 전에 Git과 GitHub의 공식 설명을 기준으로 원인을 확인하는 것이 안전합니다. 특히 rebase, push, force 옵션은 저장소 이력에 영향을 줄 수 있으므로 공식 문서에서 동작 방식을 함께 확인하는 것이 좋습니다.


GitHub Docs - non-fast-forward 오류

GitHub에서 push가 거절되는 대표적인 원인과 원격 변경 사항을 먼저 가져와야 하는 이유를 확인할 수 있습니다.

GitHub non-fast-forward 오류 공식 설명 확인

Git 공식 문서 - git pull

git pull이 fetch와 merge를 어떻게 수행하는지, rebase 옵션을 사용할 때 어떤 차이가 있는지 확인할 수 있습니다.

git pull과 rebase 옵션 공식 문서 보기

Git 공식 문서 - git push

git push의 기본 동작과 --force, --force-with-lease 옵션의 차이를 확인할 수 있습니다.

git push 옵션 공식 문서 확인

함께 보면 좋은 글

Git pull 오류도 함께 점검하기
push rejected를 해결하려면 원격 변경 사항을 가져오는 과정이 필요합니다. 이때 로컬 변경 사항 때문에 pull이 막히는 경우가 많으므로 함께 확인하면 좋습니다.
Git pull 오류 해결: Your local changes would be overwritten by merge 원인과 해결

VSCode에서 Git 흐름 정리하기
VSCode의 Source Control 화면에서 push, sync, conflict 표시가 헷갈린다면 커밋·푸시·브랜치 흐름을 먼저 정리해 두는 것이 좋습니다.
VSCode Git 입문 2026: 커밋/푸시/브랜치/충돌 해결

자주 묻는 질문

Q1. Git push rejected는 GitHub 서버 오류인가요?

대부분 서버 오류가 아닙니다. 원격 저장소에 로컬에 없는 커밋이 있거나, 로컬과 원격 브랜치의 이력이 달라졌을 때 Git이 push를 거절한 것입니다. 먼저 git status, git branch -vv, git fetch origin으로 현재 브랜치와 원격 상태를 확인하는 것이 좋습니다.


Q2. git pull과 git pull --rebase 중 무엇을 써야 하나요?

git pull은 원격 변경 사항을 가져와 merge 방식으로 합치고, git pull --rebase는 내 로컬 커밋을 원격 최신 커밋 위로 다시 쌓습니다. 개인 프로젝트나 깔끔한 이력을 선호하는 저장소에서는 rebase가 편하지만, 팀 저장소에서는 정해진 브랜치 운영 규칙을 따르는 것이 우선입니다.


Q3. git push --force-with-lease는 언제 써야 하나요?

이미 올린 커밋을 amend 하거나 rebase로 이력을 바꾼 뒤 원격 브랜치를 갱신해야 할 때 검토할 수 있습니다. 다만 공유 브랜치에서는 다른 사람의 작업에 영향을 줄 수 있으므로 먼저 git fetch origin과 로그를 확인하고, 팀원과 합의한 뒤 사용하는 것이 안전합니다.


Git push rejected는 원격 이력을 먼저 확인하고 내 커밋을 그 위에 안전하게 올리면 대부분 해결됩니다.