rebase, reset - 원격 저장소를 망가뜨리는 상황을 피하기 위해 주의해야 할 점

김동규·2023년 4월 26일
0

Git

목록 보기
11/15
post-thumbnail

개요

어느정도 깃에 익숙해졌다 하더라도 깃헙과 같은 원격저장소(remote repository)를 통해 처음으로 협업을 경험하면 혹시나 남들에게 피해를 줄까봐 겁을 먹게 됩니다. 그렇지만 사실 원격 저장소의 히스토리를 망가뜨리지 않기 위해 고려해야 할 점은 단 한 문장으로 요약할 수 있습니다.

이미 github에 push한 커밋은 변형, 삭제하지 마세요.

git은 로컬의 커밋이 원격 저장소의 커밋보다 많은 상황에는 관대합니다. 애초에 개발자들이 로컬에서 쌓아올린 커밋을 원격 저장소로 push하는게 자연스러운 작업흐름이기 때문이죠.

그러나 push하는 상황에서 이미 자신에게 보내줬던 커밋을 삭제하여 찾아볼 수 없거나, 다른 커밋과 합쳐졌거나, 해시값이 변경되었다면 히스토리가 다르다고 판단하여 받아들이기를 거부합니다. 이것은 대부분의 개발자가 rebase보다 merge를, reset보다 revert를 선호하는 이유입니다.

본문에서는 이런 위험을 피하기 위해 주의해야 할 명령어들을 탐구해보겠습니다.

다시 한번 강조하지만, 명령어들이 위험한게 아닙니다. 이미 github에 push한 커밋을 변형시키는 상황이 위험한 겁니다.

이미 push한 커밋의 해시값을 변경하기: git commit --amend | git rebase --interative -> edit

git commit --amend는 현재 index의 변경사항을 바로 직전 커밋과 함께 적용하는 명령입니다.
핀셋처럼 섬세하고 작은 작업에 어울리는 커맨드이지만, 이미 직전 커밋이 push된 상황이라면 github은 작은 변화에도 질색할 겁니다.

메세지를 고치거나 직전 커밋과 병합해야 한다면 반드시 push하기 전에 로컬에서 작업을 마친 후 올려주세요.

벌써 --amend했는데요... 다시 clone받는 것밖에 답이 없나요?

!주의 : 보시는 분이 있다면 헷갈리게 해서 미안합니다. 아래쪽에 표시된 rebase는 브랜치 이름입니다. 다른 이름으로 지을걸...

해결방법이 있습니다. 이미 push한 커밋을 --amend했거나 rebase의 대화형 인터페이스를 통해 수정하여 해시값이 변경된 상태라면 origin/<branchname>과 <branchname>로 포인터가 가리키는 커밋이 나뉘어 있을 겁니다.
(원래 de7beb6에는 rebase브랜치가 위치하고 있어야 합니다만 이미 다음 내용을 진행해버려서 올라가있는 상태입니다)

git merge origin/rebase

/* 또는 그 사이에 원격 브랜치에 추가적인 변경사항이 있었다면... */ 
git pull

충돌이 발생할 겁니다. 해결하고 add commit을 다시 진행해주면...

쓸데없이 히스토리가 복잡해졌지만 어쨌든 push 가능한 상태로 복구되었습니다.

이미 push한 commit을 삭제한 경우: reset --hard

여럿이 함께 저장소에서는 reset --hard 명령어로 히스토리를 망가뜨리는 것도 가능합니다. 사실 혼자 쓰더라도 위험성을 제대로 인지하지 못했다면 reset --hard는 되도록 사용하지 않는 것이 좋습니다.

git reset --hard로 HEAD를 이동시켰을 때 예상되는 상황은 두 종류로 분류할 수 있습니다.

  1. 아직 원격 저장소의 참조를 가지고 있다: 사실상 위와 같은 경우입니다. HEAD는 이동했지만 origin/branch로 표시되는 참조를 아직 가지고 있어서 커밋을 분실하지는 않았을 겁니다. 해결법도 위와 같습니다. merge하며 충돌을 해결해주세요.

  2. 완전히 참조를 잃어버렸습니다: 아직 깃의 가비지 컬렉터가 동작하지 않았담녀 reflog와 다른 명령으로 복구할 수 있을 겁니다. 다만 별도의 명령어를 다루게 되어 분량이 늘어나므로 다음 기회에 소개하겠습니다.

profile
공식문서를 사랑하는 프론트엔드 주니어 개발자

0개의 댓글

관련 채용 정보