현재 상황
1. 학교 개발 동아리에서 팀 프로젝트를 하기 위해 레포지토리를 만들었는데, 처음에 만들 때 프론트와 백 레포지토리를 분리하지 않고, 하나의 레포지토리에서 모두 작업하며 만들었다.
(프론트는 리액트 네이티브, 백엔드는 장고였는데, 이를 하나의 레포지토리에 통합해서 진행했다.
왜 처음부터 분리를 안했는지 묻는다면.. 동아리 활동 운영 정책상 분리를 하면 안되는 줄 알았기 때문이다.)
2. 그 상태에서 프론트도 커밋을 올렸고, 백엔드도 커밋을 올렸다.
3. 그런데 동아리 운영공지로 백엔드와 프론트 레포지토리를 분리해서 만들라는 공지를 받았다.
4. 단순히 백엔드 소스코드만 복사해서 새 레포지토리에 커밋을 할 수도 있겠으나, 그렇게 하면 지금까지 작업한 커밋들이 모두 사라지는게 아쉽다.
그래서 지금까지 올린 백엔드 커밋만 새로운 백엔드 레포지토리에 그대로 옮기고 싶다.
기존 레포지토리의 커밋 상황이다.
다행히 커밋이 많이 있지는 않지만, 프론트 커밋과 백엔드 커밋이 뒤죽박죽 섞여있는 상황이다.
이 상황에서 백엔드 커밋만 쏙쏙 뽑아서 새로운 백엔드 레포지토리에 넣으려고 한다.
해결 방법
1. 기존 레포지토리를 커밋째로 통째로 복사한다.
https://gogo-jjm.tistory.com/90
이 글을 참고해서 진행하였다.
1. 우선 기존에 프론트/백 모두 커밋을 올렸던 레포지토리 주소를 A 라고 하면, 아래와 같은 명령어를 실행해서 해당 레포지토리의 git 정보를 가져온다.
git clone --mirror A
이 레포지스토리의 이름을 A_Name 이라고 하면, A_Name.git 이라는 이름의 git 정보가 클론된다.
2. 이제 A_Name.git 이라는 이름을 .git 으로 바꿔준다.
mv A_Name.git .git
이제 이 디렉토리에서 사용하는 git 명령어는 지금 가져온 깃에 대해 적용된다.
3. 바뀐 운영 정책에 따라 백엔드 전용 레포지토리를 새로 만들었다.
해당 레포지토리 주소를 B 라고 하자.
기존에 혼합된 커밋들이 들어있는 .git 폴더의 remote 레포지토리 주소를 새 레포지토리 주소로 바꾼다.
git remote set-url origin B
4. 그리고 push 한다.
git push --mirror
모든 커밋이 새로운 레포지토리에 그대로 복사되었다.
2. git rebase 를 이용해 프론트 커밋들 삭제하기
인터넷에 "git 특정 커밋 삭제" 와 같은 식으로 검색하면, git rebase 를 이용한 커밋 삭제 방법들이 나온다.
그러나 단순히 git rebase -i {commit hash} 를 이용하면 명령어로 넘어온 해시의 커밋 "이후" 커밋들을 조작하게 된다.
지금 상황에서는 기존 레포지토리가 생성된 후 최초로 실행된 커밋이 프론트 커밋이라서 최초 커밋도 삭제해야 한다.
이는 아래 블로그 정보로 해결할 수 있었다.
https://computer-science-student.tistory.com/550
왜인지 모르겠으나 mirror 로 기존 레포지토리를 복사한 뒤 이름을 바꿔 생성한 .git 에서 작업을 할 때는 에러가 발생하였다.
따라서 B 레포지토리를 다시 clone 한 뒤 아래 명령어를 실행하였다.
git clone B
git rebase -i --root
그러면 커밋 메세지를 입력할 때처럼 아래와 같이 수정할 커밋을 선택하도록 하는 창이 뜬다.
이 중에서 남길 커밋은 pick 을 유지하고, 버릴 커밋은 drop 으로 바꿔준다.
나는 위와같이 프론트 커밋들에 대해 drop 을 적용하였다.
이 내용을 저장하고 창을 닫으면 이 내용대로 rebase 가 실행된다.
그런데 충돌이 발생했다고 한다.
충돌 위치는 "backend/readme.md" 파일 하나다.
이 파일에서 충돌을 해결해주고 hint 에 나온대로 새로 git add . 를 한 뒤, git rebase --continue 를 해주면 된다.
<<<<<<< HEAD
=======
이 사이에 있는 내용이 기존 내용이고,
=======
>>>>>>>
이 사이에 있는 내용이 충돌한 내용이다.
나는 기존 내용을 남기고 충돌한 내용을 지워서 충돌을 해결할 생각이다.
이렇게 HEAD 내용을 남기도록 고친 뒤 저장했다.
이제 hint 에서 말한대로 add 해준다.
git add .
어차피 파일 하나니까 그냥 . 으로 add 하였다.
한번 git status 를 실행히보니 이렇게 나왔다.
11개 커밋은 rebase 처리했는데, 충돌때문에 뒤에 3개는 처리를 못한 상황이었다.
그런데 모든 충돌이 해결되었으니 "git rebase --continue" 를 실행하라고 한다.
git rebase --continue
성공적으로 rebase 되었다.
3. 원격 레포지토리에 적용하기
이제 이 결과물을 원격 레포지토리에도 적용해주자.
기존 원격 레포지토리에는 rebase 가 적용되어 있지 않으므로, 이대로 push 하면 커밋내역이 맞지 않아 충돌한다.
그래서 git pull 을 해서 원격 커밋을 내려받고 다시 push 하라고 한다.
이 방식도 커밋 내역이 서로 안맞아서 실패할 것이고, 성공하더라도 rebase 작업을 처음부터 다시해주어야 하니 이렇게 하면 안된다.
그냥 이 커밋 내역을 강제로 원격에 덮어 씌우도록 하자.
git push -f
그러면 이렇게 push가 된다.
아마 실무라면 이런식으로 작업하는게 위험하겠지만, 지금은 기존 A 레포지토리라는 백업도 있고, 프론트 커밋을 원격 레포지토리에서 없애는 것이 목적이었으니 이게 맞는 방법이라고 생각한다.
이렇게 백엔드 커밋들만 남게 되었다!