IDEA : IntelliJ
환경 : MAC M1
문제상황
remote의 main 브랜치에 변경사항이 생겨서 rebase 했는데 내 이전 commit에 git에 올라가면 안 되는 정보가 포함되어 있었다.
특정 코드가 prod 환경에서만 돌아가도록 Environment를 주입받고 Spring profile이 prod인지 검사하는 코드가 포함되어있었다. 그런데 테스트 하느라 기존의 application.yml의 이름을 application-prod.yml로 바꾸었는데, 원래 commit할 땐 제외했지만 rebase하는 과정에서 충돌 해결하고 다시 commit하는 과정에서 포함되어버린듯하다. .gitignore을 확인해보니 [application.yml] 파일만 제외하도록 되어있었다. 다행히 아직 push하지 않아서 remote에 올라가진 않았다……
commit 내역을 확인해보니 파일이 HEAD로부터 6번째 커밋에서 올라가있었다(아래 사진에서 선택된 부분).
git reset 명령어를 사용하면 문제의 commit을 아예 취소할 수 있지만, 그러면 그 이후의 commit들이 모두 유실된다.
나는 저 문제의 commit을 취소하고 잘못 올린 파일을 제외한 변경사항을 반영해 다시 commit 한 뒤, 그 이후의 commit들을 다시 순차적으로 적용해주고 싶었다.
commit들의 diff을 임시적으로 저장할 수는 없나?라고 생각해서 찾아보니 diff을 따로 파일로 저장할 수 있는 방법이 있었다.
git format-patch
[git format-patch] 명령어로 특정 커밋의 diff만 저장할 수도 있다.
git format-patch -1 [커밋 해시값] ## 해당 커밋을 임시로 저장
git format-patch -n ## 현재 commit을 포함해 n개의 커밋들을 저장
git format-patch HEAD~n..HEAD ## HEAD로부터 n번째 이전 커밋부터 HEAD까지의 커밋을 저장
위의 명령어를 입력하면 commit의 diff가 patch 파일로 저장된다.
이렇게 저장된 특정 패치 파일을 현재 브랜치에 적용하고 싶으면 아래의 명령어를 사용하면 된다.
git apply [patch 파일명]
해결과정
내가 적용한 순서는 아래와 같았다.
- 문제가 되는 commit 이후의 commit들의 diff들을 임시로 저장
- 문제 되는 커밋을 reset —hard 로 제거한 뒤 해당 커밋에서 민감파일 업로드를 제외한 diff 사항을 수동으로 직접 적용해주기.
- 그 후 1번에서 임시 저장했던 diff들을 순차적으로 적용
1. 문제가 되는 commit 이후의 commit들의 diff들을 임시로 저장
문제가 되는 것은 HEAD로부터 6번째 커밋이므로 HEAD를 포함한 6개의 최신 커밋들을 임시저장해주었다.
git format-patch -6
명령어를 입력하면 생성된 파일들의 이름을 보여준다. 0001이 가장 먼저 수행한 커밋이다.
git format-patch -6
0001-feat-200.patch
0002-feat-200.patch
0003-feat-FeignClient-Provider-200.patch
0004-feat-send-200.patch
0005-feat-200.patch
0006-refactor-200.patch
인텔리제이의 파일목록에서도 생성된 patch 파일들을 확인할 수 있다.
patch 파일들에는 커밋의 정보, diff 내용등이 포함된다.
cat 0001-feat-200.patch
From 07184ffd77f05591521afc6267e117b7f2e2f006 Mon Sep 17 00:00:00 2001
From: PicturePark1101 <seojin5565@gmail.com>
Date: Fri, 30 Aug 2024 16:18:32 +0900
Subject: [PATCH 1/6] =?UTF-8?q?feat=20:=20=EC=9D=91=EB=8B=B5=20=EA=B4=80?=
=?UTF-8?q?=EB=A0=A8=20=EC=97=90=EB=9F=AC/=EC=84=B1=EA=B3=B5=20=EC=BD=94?=
=?UTF-8?q?=EB=93=9C=20=EC=B6=94=EA=B0=80=20#200?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../umc/th/juinjang/apiPayload/code/status/ErrorStatus.java | 4 +++-
.../th/juinjang/apiPayload/code/status/SuccessStatus.java | 5 ++++-
2 files changed, 7 insertions(+), 2 deletions(-)
... 생략
2. 문제 되는 커밋 이전의 시점으로 돌아간 뒤, 해당 커밋에서 민감 파일 업로드를 제외한 diff 사항을 수동으로 직접 적용해주기
git log ## commit 해시값 확인
git reset --hard [돌아가고 싶은 커밋 해시값]
git reset --hard는 HEAD를 해당 커밋으로 옮기고 그 이후 커밋들은 제거하는 명령어이다. 제거하고 싶은 커밋 이전의 커밋의 해시값을 입력하면 된다. 커밋 해시는 [git log] 명령어를 통해 확인할 수 있다.
명령어를 입력하고 나면 아래쳐럼 기존의 커밋들이 사라진 것을 확인할 수 있다.
여기서 문제의 커밋에서 민감파일을 올린 것을 제외한 변경 사항을 다시 작성하여 동일 내용으로 다시 commit 하였다.
3. 그 후 1번에서 임시 저장했던 diff들을 순차적으로 적용
이제 임시 저장했던 commit의 diff을 순차적으로 적용해주자. diff를 적용하는 과정은 아래를 반복하면 된다. [git apply] 명령어를 사용하면 해당 파일의 diff이 현재 상태에 적용되고, 이 변경사항을 commit해주면 된다.
나의 경우엔 IntelliJ를 사용하는데 자동으로 add해줘서 굳이 수동으로 add를 해줄 필요는 없었다.
git apply [patch 파일명]
git add [변경사항파일] 혹은 git add .
git commit -m "커밋메시지"
정상적으로 모든 patch 파일을 적용한 뒤 생성되었던 patch 파일들을 제거해 마무리해주었다.
rm *.patch
깃허브 쓸 때는 항상 주의하자... 특히 다른 사람들과 협업하는 프로젝트일 경우엔 더더욱...