We will find a way, we always have.

-interstellar

DevOps/깃

[Git] 하지말라는거 더 하고 싶어 (feat: git reset -- hard)

Redddy 2024. 9. 20. 00:41

문제

우테코에서 프로젝트를 진행할 때 각 팀당 주어지는 레포지토리는 하나이다. 코딩해듀오는 백엔드와 프론트엔드 브랜치 prefix를 BE와 FE로 정하여 여기에서 작업을 하고 백엔드 코드와 프론트코드 모두 있는 브랜치는 production으로 정하였다. 다시 말해 prefix가 BE면 백엔드 코드만, FE면 프론트엔드 코드만 존재하고 production 브랜치에는 백엔드, 프론트엔드 코드 모두 존재한다. 

 

백엔드 코드와 프론트엔드 코드 각자도생하다가 런칭 페스티벌 즈음에 production 브랜치에서 만났다. 이 브랜치에서 만나는 과정도 CI/CD 파일들이 컨플릭트 나긴 하였지만 어찌저찌 잘 해결하였다. 

 

하지만 문제는 BE/test 브랜치에서 production 코드를 pull 땡겨와 머지하는 실수를 하여 BE/test에 production에 있던 프론트엔드 코드가 자리 잡게 되었다. 프론트코드야 지우면 그만이야 했는데 문제는 그게 아니었다. 프론트코드를 지우면 코드 상으로는 사라지지만 커밋 로그에는 그 흔적들이 남아있었다. 

 

 

프론트엔드 깃컨벤션과 백엔드 깃컨벤션이 달라 더 복잡한 커밋 목록쓰

 

깃 트리 요녀석도 아주 복잡해졌다

 

 

그래서 내린 결론이 BE/test에 있는 프론트엔드 커밋 기록을 지워버리자! 였다.

 

지금까지 깃 커밋을 실수했을 때, 아직 푸시를 하지 않은 상황이고, 커밋 기록도 남기고 싶지 않다면 맘 편히 reset을 하였다. 이미 푸시가 된 상태에서 커밋을 실수했을 때에는 revert를 사용했었다. 이 revert를 사용하면 실수한 커밋을 다시 돌리는 커밋이 생긴다. 즉 실수한 커밋 기록과 이 커밋을 지우는 커밋 기록이 생긴다. 

 

하지만 우리가 원하는 것은 커밋 기록이 남지 않는 것이다. 

 

커밋을 실수 했을 때 돌리기 위해 구글링 하다 보면 팀 프로젝트 할 때에는 git reset --hard 사용을 하지 마라고 한다. 왜냐 새로운 커밋 push 할 때 충돌이 나기 때문이다. 뒤집어서 생각하면 팀원들에게 적절히 알리고 reset 하면 괜찮다는 이야기이다. 그래서 이 BE/test 브랜치 잡고 작업하고 있는 크루가 있는지 확인을 하고 롤백 작업을 시작했다. BE/test에서 작업하다가 영영 돌아올 수 없는 강을 건널 수 있어 BE/test에서 브랜치 하나 더 만들어서 테스트 작업을 했다 😁

 

 

 

 

위 로그에서 reddevilmidzy와 JiHyeonL은 백엔드 크루이고 antiey는 프론트엔드 크루이다. 프론트엔트 로그를 지우고 싶다는 마음에 박스친 커밋 해시 값을 넣어 명령어를 작성했다. 

 

git reset --hard 6e1770d

git push --force

 

 

 

그랬더니 놀랍게도 백엔드 로그만 싹 사라졌다 ㅋㅋㅋ 지우고 싶은 커밋 해시를 넣는게 아니라 그 이전 해시를 넣어야 됐었다. (reset이라는 의미가 해당 해시로 브랜치를 옮기겠다는 의미) 그런데 재미있었던건(어쩌면 당연한)  6e1770d 이후에 찍혀있던 커밋은 취소되는게 당연했는데, 6e1770d 이전에 있던 백엔드 로그들도 다 사라져있었다. 이 말은 즉 적절한 해시 값을 찾으면 프론트엔드 로그만 싹 날릴 수 있다는 의미다! 

 

하지만 그전에 취소한 걸 다시 롤백해야한다. 커밋 취소한 걸 취소하는 방법은 취소할 때 쓴 명령어에다가 이전 커밋 해시 값을 집어넣으면 된다. 하지만 문제는 이전 커밋 해시값이 사라졌다는 것인데, 이건 또 git reflog를 사용해서 알 수가 있다. 여기서 사라진 커밋의 해시도 확인할 수 있는데 이 해시를 다시 reset 하면 된다. HEAD가 바로 어느 해시에 있었는지 확인한 다음 그 해시 값을 넣으면 취소를 취소할 수 있다.

 

적절한 해시 값을 찾아서 reset 해주었더니 깔끔해진 BE/test의 로그를 볼 수 있었다 ㅎ.ㅎ

 

정리

 

# 커밋 취소하고 싶을 때
git reset --hard [지우고 싶은 커밋 해시]
git push --force

# 커밋 취소한거 취소하고 싶을 때
# reflog로 취소하기전 해시 값 확인
git reflog
git reset --hard [reflog로 찾은 해시]
git push --force

 


꿀팁 아닌 꿀팁

 

인텔리제이로 딸깍딸깍하면 revert commit과 undo commit이 있다.

 

 

이 test 커밋을 지우는 것으로 예시를 들어보자면,,,

 

 

revert commit은 앞서 말했다시피 revert 명령어를 사용해서 커밋 취소 커밋을 추가하는 것이다. 

 

새로운 커밋이 생겼다.

 

undo commit은 그 커밋 자체를 취소해버린다. 

 

 

push 안된 상태라면 이 undo commit 편히 사용하자.

 

 

 

 

git reset 문서

 

Git - git-reset Documentation

In the first three forms, copy entries from to the index. In the last form, set the current branch head (HEAD) to , optionally modifying index and working tree to match. The / defaults to HEAD in all forms. git reset [-q] [ ] [--] …​ git reset [-q] [--

git-scm.com

 

git reflog 문서

 

Git - git-reflog Documentation

git-reflog - Manage reflog information

git-scm.com

 

'DevOps > ' 카테고리의 다른 글

[Git] commit 작성 규칙  (0) 2022.10.28