안녕하세요 카이도입니다
오랜만에 포스트입니다
사실 이번에 실수로 아찔한 경험을 하고 나서 소소한 의문이 들어서 찾아보게된 내용 공유드립니다
우선 간단한 개념 정리 부터 들어갑니다.
reset
revert
commit 을 되돌리기 위한 기능은 위에 2가지입니다
다만 작동 방식에는 차이가 있습니다
reset 은 히스토리를 남기지 않고 이전 단계로 돌아갑니다
revert은 히스토리를 남기면서 이전 단계로 돌아갑니다
즉 둘은 차이가 있습니다 !
git 에서 위험한 명령어로 저는 reset 과 rebase는 초보자가 건들면 안되는 걸로 배웠고 revert은 github 툴에서도 추천하는 기능입니다.
그런데 revert이 더 위험하다는 여론에 뭔가 갸우뚱해서 찾아보니 revert이 더 안전(?) 함을 인지하게되었습니다.
사용법을 찾으면 간단합니다.
git reflog [head 해쉬 값 리스트.. 즉 작업 리스트 전체 출력]
git reset --hard a3bbb3c
git revert a3bbb3c
간단하죠?
그런데 여기서 문제가 생깁니다.
head{0} << 이후 추가 작업 커밋 혹은 머지
head{1} << 이후 추가 작업 커밋 혹은 머지
head{2} << 이후 추가 작업 커밋 혹은 머지
head{3} << 이후 추가 작업 커밋 혹은 머지
head{4} << sub_branch 추가 작업이후 master 브랜치와 merge 진행 !
head{5} << revert 하면서 몇가지 중요파일 삭제됨
head{6} << master to sub_branch ! merge 하면서 중요파일 add 된 상태
이런 상황이라고 치죠.
6번 merge 이후 merge 파일을 잠시 revert로 제외 시키고 작업 한 다음에, 다시 원본 master와 합쳐지길 원했던 저는 별 문제 없을거라 여겼습니다.
왜냐면 revert도 sub_branch 에서 했거든요.
하지만 revert 커밋의 문제는 [이력을 남긴다] 라는 부분이 문제였던거죠.
master에 revert 커밋도 같이 merge 되는 참사가 발생 합니다
그 이후 10개 가량 정도 추가 커밋이 진행되고 며칠이 지난 다음에나 잘못됨을 알게되는 상황.
요약 하면 중간에 revert 한 이력이 남아서 master에도 영향을 준 상황이라 revert 한 것만 빼고 싶다 ! 이게 요건입니다.
당장 떠오르는 방법은 2가지 이었습니다.
최근 master branch 를 따로 떠놓는다.
master 를 reset 으로 head {6} 으로 내려간다
다시 최신 버전과 reset한 파일중에 diff로 수정된 파일을 덮어 쓴다.
두번째 방법은
최신 버전에서 reset으로 작업 이력을 1개씩 내려가면서 branch 를 하나씩 딴다.
head{6} 까지 내려가서 다시 역순으로 branch merge 하면서 올라간다
어떻게 보면 두번째 방법이 확실하긴 합니다만 귀찮......
그래서 revert를 제외 하는 방법을 찾아보니 딱 이거다 하는건 없었습니다.
그러다 몇가지 명령어를 조합 하면???? 오호?
여기서 기술 들어갑니다!
git reset HEAD~4 --soft
revert 하고 난 다음 작업된 곳까지 돌아간다
다만 soft 로 돌아가면 커밋된 작업의 파일들이 전부 커밋전 상태로 들어갑니다
git stash
돌아간 커밋 전체를 스태이시에 잠시 저장
git reset HEAD~6 --hard
revert 참사가 일어나기 이전으로 돌아가는데 이전 이력 없는 상태로 돌아감
git stash apply
revert 이후 작업된 커밋 전체를 전부 적용 !
커밋시에 충돌이 항상 최신 버전으로 교체 되어야 한다면
git checkout --theirs .
git add .
git commit -a -m "ok revert 만 제외 !! "
이력이 남아있다면 안될리가 없는데 이상하다하다 짱구 굴리다 찾게된 팁입니다 ㅎㅎ
모두 작업 하실때 주의 하세요 ㅠㅠ
뭔가 복잡한듯 하지만 실제 상황이 발생한다면 유용한 팁일것 같습니다.
좋은 정보 감사합니다.