머리말
급하게 날라온 Git 관련 이메일
Google API Key를 업로드
Git에서 feature 브랜치로 기능 구현을 마치고 GitHub로 git push를 진행한 직후 아래와 같은 이메일이 발송되었다.
😱😱😱
여태 잘 주의하다가 새롭게 기능을 추가하면서 API Key가 유출되는(!) 문제가 발생했다. 구글에서 제공한 Info.plist에 API Key가 있는 줄은... 꿈에도 몰랐다
순간 식은 땀이 흐르면서 막막함이 들었지만 원인을 분석해서 차례차례 해결해나갔다 🔥
GitHub Repository의 Private 전환 & 문제의 git log 찾기
1) GitHub repository를 "Private"으로 전환하기
일단 해당 Repository가 Public으로 공개된 상태라면 곧바로 비공개 상태로 변경해야 한다.
1-1) (Repository Page) > Settings > General
곧바로 Repository 페이지로 들어가 Settings를 클릭 후 스크롤 다운 ⬇
1-2) Danger Zone > Change repository visibility
맨아래로 스크롤 하면 Danger Zone에 Change visibility를 눌러 Private으로 전환한다
2) git log로 문제의 커밋 확인하기
2-1) git log 명령어에 3가지 옵션을 붙여 다른 branch와 확인하기
git log --oneline --graph --all
위와 같은 명령어를 입력하면 아래와 같이 결과가 나올 것이다. 문제의 commit이 어디부터 시작인지 분석해보자.
- git log 옵션의 의미
- oneline 긴 로그 설명을 한 줄만 보여주도록 함
- graph 그래프 형식으로 보여준다
- all 모든 브랜치를 다 보여주기
* bbbbbbb (HEAD -> feature/push-notification, origin/feature/push-notification) feat: Firebase Messaging을 이용한 알림 기능 구현
및 테스트 성공
* aaaaaaa chore: Firebase SDK 설치
* 0729903 feat: Apple Push Notification 기능 구현
* 25c4159 docs: 앱 관련 파일 위치 이동 및 빌드 설정
* 6034082 (tag: 1.1.1, origin/main, origin/develop, origin/HEAD, main, develop) Merge branch 'release-1.1.1'
필자 같은 경우는 "aaaaaaa"의 commit부터 잘못 되었다.
문제의 git log를 다루는 3가지 방법
(2023-11-17 업데이트)
개요
이제 문제의 git log를 다뤄야 하는데, 방법은 크게 3가지 방법이 있고, 각각의 단점이 있다.
- git revert
- git rebase -i & edit
- git reset
명령어 | 정의 및 특징 | 단점 | |
`git revert` | - 과거의 커밋을 현재로 끌어올리는 "재설정" - 팀플에 적합 (과거의 커밋 히스토리가 그대로 남는다) |
- revert를 한 히스토리가 남는다. - 병합(merge)이기 때문에 돌아가려는 과거와 현재의 충돌(conflict)을 일일이 손봐야 한다. |
|
`git rebase -i` & edit (interactive rebase) |
- 현재 브랜치에 있는 커밋을 가공하여 커밋의 "복제본"으로 대체 - squash, reword, edit 등이 있는데 이중에 특정 커밋의 파일 상태를 변경하는 edit을 이용하면 그 커밋의 파일 상태를 변경할 수 있다 - 팀플에 부적합 (커밋의 해시번호 변경) |
- 복제본이기에 메시지가 동일하더라도, 커밋의 해시 번호(hash number)가 뒤바뀐다 | |
`git reset` | - 실제 과거의 커밋으로 되돌아가기(HEAD의 이동) - 팀플에 부적합 (아예 새로운 커밋 생성) |
- 새로운 커밋으로 기존을 덮어쓰는 것이기에 새로운 커밋이 생성 - 너무 멀리 떨어진 커밋을 수정하기에 부적합 (과거의 시점부터 새로운 커밋을 새로 만들어야 한다) |
3) git reset으로 과거의 commit으로 되돌아가기
- 프로젝트 자체가 혼자였지만, 아니라 하더라도 main 브랜치가 아닌 혼자 진행하는 feature 브랜치이기에 마음 편히 git reset을 진행할 수 있었다.
📌 주의사항
- 문제가 발생한 커밋이 다른 사람과 같이 진행하는 branch라면, git revert나 interactive rebase 등으로 커밋을 변경할 경우 커밋의 해시 번호가 바뀌기 때문에 팀원의 양해를 구하고 진행해야 할 것이다. (*)
- 또한 필자는 문제의 커밋을 발견한 지점이 HEAD와 멀지 않았기에 git reset을 사용했다.
3-1) git reset에 soft 옵션으로 staged 상태는 남기기
# 방법 1. 커밋의 해시 넘버로 돌아가기
git reset --soft <commit hash number>
# 방법 2. 현재 HEAD를 기준으로 인덱스 번호로 돌아가기
# - 가장 최근 커밋은 HEAD^
# - HEAD~ 이후에 붙는 숫자 n은 HEAD로부터 n만큼 떨어져 있다.
git reset --soft HEAD~2
# 방법 3. HEAD 대신 @ 이용하기
git reset --soft @~2
(2023-11-13 월 업데이트)
그냥 git reset를 하게 되면 기본값인 `--mixed`가 적용되어 staged 상태가 저장되지 않은 채 해당 커밋으로 되돌아간다 일일이 git add 하는 게 귀찮다. 따라서 `--soft`로 일단 staged 상태를 유지해서 필요한 부분만 적용하는 게 좋다.
git reset --soft 0729903
`aaaaaaa`가 발생했으니 그 직전 커밋인 `0729903`으로 되돌아간다.
4) 문제의 파일을 unstaged로 변경 및 gitignore에 파일 추가
4-1) `git reset HEAD <file>`로 해당 문제의 파일 unstaged 하기
`--soft` 옵션으로 커밋의 staged 기록이 남아 있으니 문제의 파일을 unstaged로 바꾼다.
git reset HEAD (프로젝트)/.../GoogleService-Info.plist
4-2) 커밋에 부적절한 파일 unstaged (선택)
만약 되돌아간 커밋에서 추가로 커밋할 내용이 원래의 커밋 내용과 벗어난 파일이 있을 수 있다.
필자의 경우에는 단순히 Firebase와 관련된 패키지 설치가 주된 내용이었기에, 그 외에 상관없는 파일은 모두 unstaged 했다.
그냥 문제의 파일만 반영하고 싶다면 이 단계를 생략해도 된다.
# 예시
git reset HEAD (프로젝트)/.../AppDelegate.swift
4-3) `.gitignore` 파일에 staged 하지 말아야 할 파일을 추가
이제 수정해야하는 부분을 수정한다. 필자 같은 경우에는 `.gitignore`가 문제이니 이를 반영한다.
# .gitignore
# 아래 내용 추가
GoogleService-Info.plist
4-4) 수정한 `.gitignore` 파일 staged
이제 `.gitignore`에 반영해서 업데이트 한다.
5) 해당 파일 수정 및 차례차례 commit 하기
📌 "4-3"의 경우를 거쳤을 경우에만 해당
git commit -m "커밋 내용"
4-3 단계를 거쳤다면 이제 다시 문제의 커밋 이후에, 작성한 커밋이 또 있다면 계속해서 커밋을 진행한다. staged/unstaged은 본인의 판단하에 진행하면 된다.
6) 해당 브랜치를 강제 푸쉬하기
git push origin +(브랜치 이름)
이미 GitHub에는 문제의 커밋이 반영되어 있기에 해당 브랜치의 내용을 강제로 덮어씌어야 한다.
아래 같이 크게 3가지 방법이 있는데, 편한 걸 이용하면 된다. (필자는 주로 +를 자주 쓴다)
# 방법 1
git push origin +feature/push-notification
# 방법 2
git push -f origin feature/push-notification
# 방법 3
git push --force origin feature/push-notification
꼬리말
완성 결과
다행히 git을 제외한 새로운 커밋으로 만들었고 이를 강제로 덮어 씌웠다 :)
* dc65056 (HEAD -> feature/push-notification, origin/feature/push-notification) feat: Firebase Messaging을 이용한 알림 기능 구현
및 테스트 성공
* 0366771 chore: Firebase SDK 설치
* 0729903 feat: Apple Push Notification 기능 구현
* 25c4159 docs: 앱 관련 파일 위치 이동 및 빌드 설정
* 6034082 (tag: 1.1.1, origin/main, origin/develop, origin/HEAD, main, develop) Merge branch 'release-1.1.1'
해당 GitHub Pull Requests
아래에도 잘 반영이 되어 이제 APIKey가 보이지 않는다
댓글