앗! Git 서버에서 pull이 안돼요? (로컬 HEAD가 원격보다 앞서 나갔을 때) 🤯

홍태극·2023년 8월 9일
0

앗! Git 서버에서 pull이 안돼요? (로컬 HEAD가 원격보다 앞서 나갔을 때) 🤯

개인 프로젝트를 하다가 가끔 이런 상황 만나지 않으세요? 원격 저장소(origin)에 이미 올려버린(push) 내용을 "아차!" 싶어서 이전 상태로 되돌리고 싶을 때 말이에요. 저도 얼마 전에 Next.js 프로젝트 하다가 그런 일이 있었어요.😅

VS Code의 Git 확장 프로그램으로 GUI 써서 간단하게 revert 하고 다시 push했죠. 그리고는 프로젝트 돌리고 있는 서버에 가서 git pull을 딱 받았어요.

그런데... 문제가 터졌습니다! 😱 서버에서 pull 받고 npm run build 하려는데 에러가 뙇! 제가 원했던 시점으로 revert가 제대로 안 됐던 거더라고요. 혼자 쓰는 레포지토리였고, 되돌린 기록(revert 커밋) 남는 게 좀 지저분해 보여서 로컬에서 그냥 git reset --hard <돌아가고_싶은_커밋_ID> 명령어로 확 되돌려 버렸어요. 그리고 원격 저장소에 다시 push를 했죠 (아마 이때 push --force 옵션을 썼을 수도 있어요, 과거를 바꾸는 거니까요!).

자, 이제 다시 서버로 가서 git pull을 했는데... "이미 최신 버전입니다 (Already up to date)." 라는 메시지만 덩그러니 뜨는 거예요. 완전 당황했죠! 😳 분명히 내 로컬에서 작업하고 원격 저장소에 반영했는데, 서버에서는 업데이트가 안 된다니?

그래서 git log로 서버의 상태를 확인해 봤더니 이런 상태였어요. 커밋 메시지 앞에 chore:, revert:, feat:, fix: 같은 접두어는 어떤 종류의 작업이었는지 나타내는 표시(Conventional Commits 규칙)예요.

commit 6416f7dd99dc3d724cc434d367241437b424c665 (HEAD -> main) // <- 서버의 현재 상태 (HEAD)
Author: Aiden Hong <brain1401@gmail.com>
Date:   Thu Aug 10 06:09:37 2023 +0900

    chore: 포트번호 3002번으로 번경

commit 9eae814cc70675781a81dd301b8a91887fb5f72c
Author: Aiden Hong <brain1401@gmail.com>
Date:   Thu Aug 10 06:07:46 2023 +0900

    revert: Revert "feat: PostDetail PC화면 개선"

    This reverts commit de433a195fc346dfc6b759dfc2c5fc2f21c09710.

commit 47dbafafcf7c88223be1b8528b8f176151a82436
Author: Aiden Hong <brain1401@gmail.com>
Date:   Thu Aug 10 02:08:57 2023 +0900

    feat: vercel analytics 추가

commit de433a195fc346dfc6b759dfc2c5fc2f21c09710 (origin/main) // <- 원격 저장소의 최신 상태 (origin/main) 가 여기?!
Author: Aiden Hong <brain1401@gmail.com>
Date:   Thu Aug 10 02:02:50 2023 +0900

    feat: PostDetail PC화면 개선

commit b1354c842a1a51baff0888b9b8b012632e656dea
Author: Aiden Hong <brain1401@gmail.com>
Date:   Thu Jul 27 06:52:26 2023 +0900

    feat: 유저 페이지 모바일 UI 개선

commit 2fe39f89ce008bae3fe46ce9b68c5a9a6af8d996
Author: Aiden Hong <brain1401@gmail.com>
Date:   Thu Jul 27 06:24:20 2023 +0900

    feat: navbar 모바일 UI 개선

commit 547a19a2416b4f210961892ffe817ce9db237786
Author: Aiden Hong <brain1401@gmail.com>
Date:   Thu Jul 27 00:59:54 2023 +0900

    feat: postDetail 모바일 반응형 개선

commit f438fae28e4bccde0661cab9fbfdda8c82f62418
Author: Aiden Hong <brain1401@gmail.com>
Date:   Wed Jul 26 05:59:01 2023 +0900

    fix: 반응형 적용 안됨 수정

commit 26dd2183cb77102f5d03ed7867ac86a8ab422097
Author: Aiden Hong <brain1401@gmail.com>
Date:   Wed Jul 26 03:51:35 2023 +0900

    feat: navbar 제외하고 전체 페이지 반응형 구현

보이시나요? 서버의 HEAD -> main (현재 로컬 상태) 이 원격 저장소의 최신 상태인 origin/main 보다 더 예전 커밋을 가리키고 있어요! 제가 로컬에서 reset하고 강제로 push하면서 원격 저장소의 히스토리가 바뀌었는데, 서버는 아직 그 이전 히스토리 위에 있었던 거죠. 이러니 pull이 안 될 수밖에요. 😭

🛠️ 해결 방법은 없을까요? (혼자 쓸 때)

이런 상황, 생각보다 종종 마주칠 수 있는데요, 혼자서 사용하는 레포지토리라면 해결 방법은 의외로 간단해요! 서버(또는 pull이 안 되는 다른 로컬 환경)에서 아래 과정을 따라 하면 돼요.

1. 일단 원격 저장소 정보부터 최신으로!

먼저, 지금 원격 저장소(origin)에 어떤 최신 정보가 있는지 알아봐야 해요. 아래 명령어를 사용하면 돼요.

git fetch origin

이 명령어는 원격 저장소의 최신 변경 내역 정보를 가져오기만 하고, 아직 내 로컬 코드에 합치지는(merge) 않아요. 일단 최신 정보가 뭔지 구경만 하는 단계라고 생각하시면 돼요. 👀

2. 로컬 브랜치를 원격 브랜치에 강제로 맞추기! (🚨🚨🚨 초강력 주의 🚨🚨🚨)

이제 가장 중요한 단계예요. 내 로컬 main 브랜치 상태를 방금 Workspace로 확인한 원격 origin/main 브랜치의 상태와 완전히 똑같이 만들어 버리는 거예요. 아래 명령어를 사용하면 됩니다.

git reset --hard origin/main

이 명령어는 현재 내 로컬 main 브랜치가 가리키는 커밋 위치를 강제로 origin/main이 가리키는 최신 커밋 위치로 옮겨버리고, 작업 디렉토리의 파일 내용까지 그 상태로 싹 바꿔버려요.

⚠️ 진짜 진짜 중요! 경고! ⚠️
reset --hard 명령어는 매우 강력하고 위험해요! 만약 이 명령어를 실행하는 서버(또는 로컬 환경)에 원격 저장소에는 없는 로컬만의 변경 사항이나 커밋이 있었다면, 그 내용이 전부! 완전히! 영원히! 사라져요! 복구도 거의 불가능하고요. 😱

그러니 이 명령어를 쓰기 전에는 반드시 현재 작업 내용을 백업하거나, 다른 브랜치에 임시로 커밋해두는 등 안전 조치를 꼭 취해야 해요! 지금 우리가 처한 문제는 원격 저장소의 내용을 그대로 따라가야 해결되는 상황이라 이 명령어를 쓰는 거지만, 항상 위험성을 인지하고 조심 또 조심해야 합니다!

3. 잘 맞춰졌는지 확인하기!

마지막으로, 로컬 브랜치가 원격 브랜치와 잘 맞춰졌는지 git log 명령어로 다시 한번 확인해보세요.

git log

이제 HEAD -> mainorigin/main이 같은 커밋을 가리키고 있다면 성공이에요! 🎉

🤝 잠깐! 협업할 때는 절대 이렇게 하면 안 돼요!

위에서 설명한 reset --hardpush --force (또는 reset --hard origin/main) 방법은 혼자 쓰는 레포지토리에서나 어쩔 수 없이 쓰는 방법이에요. 만약 팀원들과 함께 작업하는 공유 브랜치(예 main, develop, master)에서 이런 문제가 발생했다면 절대! 네버! reset --hardpush --force를 사용하면 안 돼요! 🙅‍♀️🙅‍♂️

왜냐고요? 내가 원격 저장소의 히스토리를 강제로 바꿔버리면, 다른 팀원들이 작업하던 내용과 충돌이 나거나, 심하면 팀원들의 로컬 저장소가 완전히 꼬여버릴 수 있어요. 그럼 모든 팀원이 각자 자기 로컬 저장소를 수동으로 복구해야 하는 끔찍한 상황이 벌어질 수 있답니다. (마치 위에서 서버 고쳤던 것처럼요!)

그럼 협업 중에는 어떻게 해야 할까요?

  • 🥇 git revert 사용하기 (강력 추천!)
    잘못된 커밋을 되돌리는 가장 안전하고 표준적인 방법은 git revert <되돌릴_커밋_ID>를 사용하는 거예요. revert는 문제가 된 커밋을 없애는 게 아니라, 그 커밋의 변경 사항을 취소하는 새로운 커밋을 만들어요. 이렇게 하면 기존 히스토리는 그대로 유지되면서 문제만 해결할 수 있어서, 다른 팀원들에게 영향을 주지 않아요. 만약 처음 revert가 잘 안 됐다면, 왜 안 됐는지 원인을 찾거나, revert 커밋 자체를 다시 revert 하는 방법을 고민하는 게 훨씬 안전해요!
  • 🗣️ 소통! 또 소통!
    실수로 잘못된 내용을 공유 브랜치에 push했다면, 혼자 해결하려고 하기 전에 반드시 팀원들에게 먼저 상황을 알리고 상의하세요! 함께 머리를 맞대고 가장 안전한 해결책을 찾는 것이 중요해요. "제가 실수로 main에 잘못 push했는데, revert 할까요? 아니면 다른 방법이 좋을까요?" 이렇게요!
  • 🌿 기능 브랜치(Feature Branch) 활용하기
    애초에 이런 실수를 줄이려면, 새로운 기능 개발이나 수정 작업을 할 때는 각자 개인 브랜치(기능 브랜치)를 만들어서 작업하고, 충분히 검토한 후에 Pull Request(PR)를 통해 공유 브랜치(main 등)에 합치는(merge) 방식을 사용하는 것이 좋아요. 이렇게 하면 문제가 있는 코드가 중요한 공유 브랜치에 바로 반영되는 것을 막을 수 있답니다.

✨ 정리하며

reset --hardpush --force로 꼬여버린 상황에서 git fetchgit reset --hard origin/main으로 로컬 저장소를 복구하는 방법을 알아봤어요. 하지만 이 방법은 혼자 작업할 때 정말 어쩔 수 없는 경우에만 사용하는 비상 수단이라는 점! 그리고 로컬 변경 사항이 날아갈 수 있는 위험한 작업이라는 점을 꼭 기억해주세요!

협업할 때는 무조건 git revert를 사용하고, 팀원들과 충분히 소통하는 것이 훨씬 안전하고 바람직한 방법이라는 것도 잊지 마시고요! Git은 강력한 도구지만, 올바르게 사용해야 그 힘을 제대로 발휘할 수 있답니다. 😉

0개의 댓글