[Git] Merge하면서 branch 사라졌을때 커밋 복구, Reset과 Revert의 차이

zzzzsb·2022년 12월 4일
0

Github

목록 보기
2/2

현재 엘리스 AI 트랙 5기에서 진행중인 팀프로젝트에서는 매주 토요일 코치님들께 코드리뷰를 받는다.

코드리뷰를 위해 매주 금요일마다 Merge Request를 작성하는데,
이때 해당 주차에 작업한 코드내용을 모두 dev에 합치고 master로 최종 머지 하기 위함이다.

Issue의 시작,,,,

그런데 다들 작업진행하느라 정신이 없어서.. 지난 2주차 코드리뷰 내용을 Merge하지 않은 상태로 작업을 진행해버렸다.

즉, 지난주차 MR이 master에 머지되지 않은 상태로, 계속 dev 브랜치에 작업내용이 쌓여 2,3주차 코드가 함께 쌓여있었다...!

그래서 팀원 중 한명이 지난 2주차 Merge Request를 Closed했는데, 이 과정에서 아래 Merge option에 delete source branch가 check된 상태로 승인을 하신것 같았다.

(옵션은 꼭 한번 더 확인해보자...ㅠㅠ)

결론: dev 브랜치가 사라져버리고, 3주차 코드(코드리뷰 받기 전)내역이 전부 master로 합쳐짐

원하는 상태: master는 2주차 커밋(코드리뷰 받아서 수정한 내용)까지 합쳐지고, 3주차 코드작성 커밋까지 dev에 남아있어야 함

해결을 위한 여정...

이슈가 발생했던 당시 노트북 사용이 불가능했던 상황이라, 나는 밤 늦게 깃랩을 확인해 볼 수 있었다.

그사이에 다른 팀원분게서 이슈를 해결하기 위해 여러 조취를 취하시고 위와같은 메시지를 남겨주셨다.

1) local에서는 origin/dev가 있다고 인식하지만 실제로는 존재하지 않는다. 그래서 dev branch를 생성할 수 없다.
2) master를 revert 했지만 이전 merge 기록때문에 변경사항이 없다고 인식해 MR진행이 되지 않는다.
3) 우선 임시로 MR을 위한 newMaster와 newDev 브랜치를 만들어 두었다.


Reset vs Revert

위의 2번 문제의 경우 reset을 해야하는데 revert 사용해서 발생한 문제였다.

reset과 revert 개념, 차이

reset과 revert는 특정 시점의 commit으로 되돌리고 싶을때 사용하는 명령어이다.

둘의 공통점은 과거의 커밋으로 되돌린다는 점이지만, 가장 큰 차이점은 과거로 되돌리겠다는 내용이 커밋이력에 남는가? 이다.

reset은 말 그대로 '리셋'으로, 현재까지의 커밋 이력을 남기지 않고 원하는 특정 시점 커밋으로 완전히 되돌아 간다.
revert는 과거로 돌아가겠다는 이력을 남기고 원하는 특정시점 커밋으로 돌아간다. 즉, 이전의 커밋내역을 남겨두고 새로운 커밋을 생성하며 과거로 돌아간다.

Reset은 위 그림과 같이 4번째 커밋 -> 3번째 커밋 으로 되돌아갈 경우, 4번째 커밋은 완전히 사라지게 된다.

Revert는 위 그림을 보면 3번째 커밋 -> 2번째 커밋으로 되돌아갈 경우 4번째 커밋에 2번째 내용의 커밋이 위치하게 된다.
(현재 위치: 3번째 커밋 / 되돌아갈 위치: 2번째 위치 / => 되돌아갈 2번째 커밋 내역이 현재 위치 다음인 4번째에 위치하게 됨)

Reset, Revert는 언제 사용해야 할까?

Reset 명령은 커밋에 기록이 남지 않아 히스토리를 깔끔하게 유지할 수 있고, 혼자 작업할 때 편하게 되돌아갈 수 있다. 하지만 다른 사람들과 같은 브랜치에서 작업하고 있었다면 커밋이 뒤섞여버릴 수도 있다.

Revert 명령은 히스토리에 되돌아간 기록이 남게되어 왜 되돌아갔는지 기록을 남길 수 있다. 다른 사람들과 협업할 때에도 코드 충돌을 최소화 할 수 있다.

Reset, Revert 사용법

git reset --soft [commit ID] 
git reset --mixed [commit ID]
git reset --hard [commit ID]
git reset HEAD~10 
git reset HEAD^
  • soft: commit된 파일들을 staging area로 되돌려 놓는다(commit 하기 전 상태로)
  • mixed: 옵션을 따로 붙여주지 않는다면 기본으로 설정되는 옵션이다. commit된 파일들을 working directory로 되돌려 놓는다(add 전 상태로)
  • hard: commit된 파일들 중 tracked 파일들을 working directory에서 삭제한다.(untracked 파일은 계속 untracked로 남음)
  • HEAD_취소할 커밋 개수: 현재로부터 원하는 만큼의 commit 취소
  • HEAD^: 가장 최근이ㅡ commit 취소(기본 옵션 mixed)
git revert [commit id]

돌아가고자 하는 commit id를 붙여준다.


어떻게 해결했는가?

  1. 일단 master를 reset으로 이 커밋으로 돌려놔서 아예 처음 상태로 만들었구요
  2. 제 local dev를 아예 삭제하고 병용님 newDev에서 다시 dev를 생성해서
    원격으로 push해서 dev 다시 만들었고,
  3. 병용님이 살려놓아주신 newMaster브랜치를 master로 MR올려서 합쳤구요
    (이전 코드리뷰 ea707b37 커밋으로 )
  4. dev 살아났고, master도 1주차 코드리뷰 상태로 되살렸으니
    dev -> master로 MR 생성했습니다!

fatal: a branch named 'dev' already exists

1) local에서는 origin/dev가 있다고 인식하지만 실제로는 존재하지 않는다. 그래서 dev branch를 생성할 수 없다.

git branch -d dev

local dev를 삭제해주고, 복구해놓은 newDev에서 새롭게 dev 브랜치를 다시 생성했다.

3주차 커밋내용까지 반영된 dev 브랜치 복구 완료,,

master revert -> reset

2) master를 revert 했지만 이전 merge 기록때문에 변경사항이 없다고 인식해 MR진행이 되지 않는다.

git reset [commit id]

이전 master 커밋을 찾아 reset 명령어를 통해 커밋 내용을 되돌렸다. (과거 내역이 남지 않음)

그리고 newMaster(2주차 코드리뷰 완료된 커밋들) -> Master로 Merge 해줬다.

이제 Master는 원하는대로 2주차 코드리뷰 완료된 커밋들만 존재하는 상태가 되었다!

임시로 만들어둔 branch 삭제

3) 우선 임시로 MR을 위한 newMaster와 newDev 브랜치를 만들어 두었다.

master, dev 복구 완료했으니 임시로 생성한 브랜치 삭제해주자.

# 로컬 브랜치 삭제
git branch -d newMaster
git branch -d newDev

# 원격 브랜치 삭제
git push origin --delete newMaster
git push origin --delete newDev

dev -> master Merge Request 생성

3주차 코드리뷰 Merge Request도 생성해줬다.

해결 완료!!


참고자료

profile
성장하는 developer

0개의 댓글