필요한 부분에 따라 링크를 해두었으니 '이동' 을 통해 확인하면 좋을 것 같다.
- 문제상황설명 (이동)
- 내가 생각한 문제 해결 방식 2가지 (이동)
- 첫 번째 방식이 부적절하다고 생각하는 이유 (이동)
- 해결한 방법 (이동)
- 두 번째 방식이 적절하다고 생각하는 이유 (이동)
1. 문제상황설명
하나의 repository 안에 backend 와 frontend 파일을 위치시키고 버전을 관리하고 있었는데, 다른 프론트엔드 팀원에게 backend 폴더가 PR 변경사항에 잡혔다고 연락이 왔다.
프론트엔드에서 backend 폴더에 작업 내용이 있을 리 없으니 당연히 변경사항으로 잡힐 일이 없는데, 뭔가 실수가 있었던 것 같아 원래대로 되돌려야 하는 상황이었다.
2. 내가 생각한 문제 해결 방식 2가지
이 때 생각난 방식은 2가지가 있었다.
- git reset HEAD^ 로 commit 을 하나하나 내릴 때마다 git status 로 변경사항을 살펴보며 backend 폴더의 변경사항이 잡히는 지점까지 내려간 후, 변경이 발생한 파일을 원래대로 되돌리기
- 변경이 발생한 파일의 최신 버전 commit hash 를 확인한 후, git restore --source [commit hash] [file name] 을 이용하여 해당 파일만 원래 상태로 되돌리기
지금 생각하기에 올바른 방법은 2번이지만, 그동안 귀찮아서 1번 방식으로 하던 본인을 반성하며 1번 방식이 왜 부적절하다고 생각하게 되었는지, 2번 방식이 왜 적절하다고 생각하는지 남기려한다.
1번 방식이 왜 부적절하다고 생각하는지 필요하지 않다면, 2번 방식으로 바로 이동 (이동)
3. 첫 번째 방식이 부적절하다고 생각하는 이유
일단 첫 번째 방식의 흐름을 살펴보자
git reset HEAD^
git status
# modified 로 backend 폴더가 잡힐 때까지 반복
# 변경된 backend 폴더의 파일을 원상복구
# 적절히 commit 메시지를 남긴 후
git push --force
# 로컬에서 commit 을 reset 한 후 remote 로 올리는 것이기 때문에 강제로 push 를 해주어야한다.
1. git reset HEAD^ 와 git status 를 반복, backend 폴더가 아래 이미지와 같이 modified 로 잡힐 때까지 commit 을 내린다.
2. 변경된 backend 폴더의 파일을 원래대로 돌리기
3. 다시 add / commit 을 한 후 git push --force 를 이용하여 remote 에 강제로 push 하기
이미 remote 로 모든 변경사항이 전부 올라간 상황인데, 로컬에서 commit 을 내린 후 그것을 remote 에 적용하려 하는 상황이다. 때문에 로컬의 commit 히스토리를 remote 에 강제로 push 해야 하므로 --force 를 붙여야 한다.
- 위 방식대로 해왔던 이유
commit 실수가 발생했을 때, 잘못 다룬 파일에 대한 수정사항이 git 에 아예 올라가지 않았으면 하는 강박증이 있었다.
위 방식대로 수동으로 commit 을 내린 후 수정사항을 취소해주면, commit 을 눌렀을 때 변경사항이 전혀 잡히지 않으므로 그동안 위 방식대로 해왔다.
하지만 이번 문제상황에서는 위 방식대로 할 수가 없었다.
backend 폴더가 변경사항에 잡힌 것을 뒤늦게 PR File Changes 에서 발견하였으며, git reset HEAD^ 로 commit 을 내려가며 찾기에는 쌓여있는 commit 이 너무 많았다.
(PR convention 을 생각한다면 작업단위를 최소화하며 1기능 1PR 이 되도록 노력해야 하는 것은 알지만, 일단은 번외로 하자. 모든 개발 상황이 꼭 best practice 대로 흘러가리라는 법은 없으니)
이 상황을 맞닥뜨리고 나니, 그동안의 방식이 부적절했다는 것을 깨달을 수 있었다.
- 그동안 해오던 방식이 부적절하다고 생각하게 된 이유
1. 버전관리가 무의미해진다.
git 은 버전관리를 위해 존재하며, 위 이미지와 같은 commit history 또한 언젠가는 필요할지도 모르는 기록들이다. git reset 을 통해 commit 을 내린 후 history 를 지워버리는 행위는 버전관리가 무의미해지는 행위라는 생각이 들었다.
2. 수동으로 무언가를 한다는 것은 비효율적이며, 관련 없는 파일들에 대해서도 영향을 끼친다.
지금 해결하고자 하는 문제는 '실수로 변경이 발생한 파일을 찾아가, 원래대로 되돌리기' 일 뿐이다. 하지만 git reset 을 통해 commit 을 일일히 내리며 변경을 확인하는 경우에는 변경한 파일이 언제 modified 로 나타날 지 모르며, commit history 로 남아야 할 파일들도 계속해서 unstaged 되게 된다.
그동안 왜 그렇게 했을까 부끄럽지만, 지금이라도 깨달았으니 앞으로는 그러지 말아야겠다.
4. 해결한 방법
1. 어떤 파일이 실수로 변경되었는지 찾는다.
2. 해당 파일의 last commit hash 를 찾는다.
# cd 를 통해 변경된 파일의 폴더 디렉토리로 이동
git restore --source [commit hash] [file name]
3. 변경된 파일을 포함하는 폴더까지 이동한 후, git restore 명령어를 통해 현재 remote 에 있는 last commit 으로 파일을 변경해준다.
4. 그리고 다시 add / commit / push 를 하여 remote 에(PR 에) 반영해준다.
이렇게 할 경우 PR 의 commit history 에는 남을지라도, PR 전체의 File Changes 에서는 다시 사라지게 된다. (하나의 PR 안에서 수정을 했다가, 원상복구의 과정을 거친것...)
5. 두 번째 방식이 적절하다고 생각하는 이유
위에 적은 두 번째 방식이 적절하다고 생각하는 이유는 그동안 해오던 방식이 부적절하다고 생각하게 된 이유 (이동) 에 정확히 반대로 대응하여 설명할 수 있을 것 같다.
1. 버전관리에 문제가 생기지 않는다.
git reset HEAD^ 를 사용한 방법은 git commit history 를 내리며 파일이 수정된 시점을 찾는다. 하지만 다시 생각한 방법은 기존의 git commit history 를 건드리지 않으므로 다른 history 에 영향을 주지 않는다.
2. 수작업이 아니라 남겨진 commit history 를 활용하여 파일을 되돌리며, 우리의 관심사에만 집중하게 된다.
git reset HEAD^ 를 통해 commit 을 내리며, 관련 없는 파일들도 모두 unstaged 하는 것과 다르게, remote 에 남아있는 commit hash 를 통해 필요한 파일에만 영향을 끼치게 된다.
'개발 관련 > Git' 카테고리의 다른 글
[Git] git submodule을 이용하여 중요한 정보 숨기기 (0) | 2022.01.11 |
---|---|
[Git] git 명령어 (0) | 2021.08.02 |
[Git] fork한 repository 동기화부터 pull request (PR)를 보내기까지 (0) | 2021.08.02 |
댓글