티스토리 뷰
미루고 미루다 Rebase를 복습하고 실습해보는 시간을 가지려고 합니다.
초보의 경우엔 Merge를 이용하는게 충돌의 위험이 적다고 하지만 언제까지 초보로 머무를 수도 없고!
실제 협업할때 Merge대신 Rebase를 많이 이용한다고 하기 때문에 배워보도록 할게요!
Rebase는 기준점을 변경해준다는 의미인데요! feature branch에서 rebase main을 해주면 main의 최신 commit을 기준점으로 해서 feature branch에 있는 모든 커밋을 지우고 새로 생성하여 선형적으로 나열해줍니다.
선형적으로 나열해주기 때문에 merge보다 탐색이 쉽우며 변경사항을 보기에 유용하다. 그러나 커밋을 삭제하고 다시 생성하기 때문에 충돌의 위험이 크다.
우선 Merge와 Rebase는 모두 하나의 branch에서 다른 branch로 변경사항을 통합하는 기능을 수행합니다.
그러나 이는 매우 다른 방식으로 수행하기 때문에 상황에 맞게 적절히 선택하는게 중요합니다.
우선 실습을 통해 무슨 차이가 있나 먼저 체험해볼게요.
1. Rebase테스트 폴더를 만들고 Git init을 해준 뒤 main branch에서 A.txt파일을 생성해주었습니다.
% git init
% touch A.txt
% git add .
% git commit -m "Create A.txt"
Git log
2. merge또는 rebase를 사용하기 위해 feature branch를 생성하고 feature branch에서 B.txt 파일을 생성해볼게요. 그리고 2개의 커밋을 추가해주었습니다.
% git branch feature
% git checkout feature
% touch B.txt
% git add .
% git commit -m "Create B.txt"
% vi B.txt // 파일 열고 내용 추가
% git add .
% git commit -m "write B.txt content"
3. main으로 이동하여 A.txt의 내용을 추가하는 커밋과 A.txt의 내용을 변경하는 커밋 2개를 추가해주었어요.
% git checkout main
% vi A.txt // 파일 열고 내용 추가
% git add .
% git commit -m "write A.txt content"
% vi A.txt // 파일 열고 내용 변경
% git add .
% git commit -m "Edit A.txt content"
4. main의 변경 사항이 발생했습니다. 우리는 변경 이전에 main에서 branch를 땄으므로 변경된 내용이 feature branch에서 적용할 수 없습니다. 이 때 merge또는 rebase를 이용한 branch병합으로 새로운 변경사항을 feature브런치에서 적용할 수 있습니다.
먼저 merge를 이용해보겠습니다.
% git checkout feature
% git merge main
위와 같이 Merge를 이용하게 되면 Merge commit이 무조건 하나씩 생기는데 프로젝트가 활발한 경우엔 Merge commit때문에 어떤 변화가 언제 반영되었는지에 대한 이력 없이 하나의 commit으로 합쳐지기 때문에 변경이력을 알기 어렵게 됩니다.
Git Reflog 와 Git Reset --hard 명령어를 통해 되돌린 후에 Rebase를 이용한 병합또한 진행해보겠습니다.
% git checkout feature
% git rebase main
차이가 보이시나요!
Rebase는 불필요한 Merge Commit을 제거하며 위 다이어그램처럼 선형 히스토리로 나타내어집니다. 이는 Git Log, Git bisect, gitk등의 명령으로 프로젝트를 좀 더 쉽게 탐색할 수 있게 해줍니다.
그러나 이 작업은 히스토리를 재작성하는 일이기 때문에 협업 워크플로우에 잠재적으로 치명적일 수 있는 가능성이 있다고 합니다.
그렇기에 Rebase의 Golden Rule 즉 지켜야하는 규칙이 있는데 이것은 공용 브랜치에서는 절대 사용하지 않는 것입니다.
예를들어서 main branch를 feature branch로 rebase한 경우에는 다음과 같이 main에 있는 모든 커밋을 feature 끝으로 재작성합니다.
main branch는 공용 branch인데 rebase로 인해 2개의 커밋이 feature branch로 재작성되었고 이는 사용자의 리포지토리에서만 이 작업이 이루어지며 다른 팀원들은 여전히 원래의 2개의 커밋이 남아있는 main branch에서 작업하고 있습니다.
이 때 중요한 점은 Rebase는 기존 커밋을 삭제하고 재작성하는 것이기 때문에 Git은 Rebase된 커밋2개와 팀원들의 main branch에 있는 기존 커밋 2개가 같은 변경사항 커밋이라는 것을 인지하지 못합니다.
여기서 main branch와 feature branch를 동기화 시키는 방법은 다시 main branch로 병합하는 것인데 이는 똑같은 변경사항을 포함하는 두 커밋 집합이 발생하는 매우 혼란스러운 상황입니다!!
어렵다면 공용 branch에서는 rebase를 사용하지 않으면 됩니다!!
또 중요한것은 대화형 Rebase라는 것인데요!
새로운 브런치로 이동될 때 커밋을 변경할 기회를 제공해줍니다!!
약간 굳이 기록하지 않아도 되는 커밋을 제거해주면서 rebase를 해주는 거라고 보면 될 것 같아요!
% git checkout feature
% git rebase -i main
이렇게 하면 이동하려는 모든 커밋이 아래와 같이 나열됩니다.
pick 8f541fe Create B.txt
pick e38734f write B.txt content
여러가지 명령이 있는데 아래 중 필요한 명령을 사용하여 커밋을 변경하면됩니다.
- p, pick <commit> = use commit 커밋을 사용하는 명령입니다.
- r. reword <commit> = use commit, but edit the commit message 커밋을 사용하나 메세지를 바꿉니다.
- e, edit <commit> = use commit, but stop for amending 커밋을 사용하지만 수정을 위해 중지합니다.?? 뭘까요 이건.
- s, squash <commit> = use commit, but meld into previous commit 커밋을 사용하지만 이전 커밋에 병합합니다.
f, fixup [-C | -c] <commit> = like "squash" but keep only the previous commit's log message, unless -C is used, in which case keep only this commit's message; -c is same as -C but opens the editor squash와 비슷하지만 -C를 사용하지 않는 한 이전 커밋메세지만 유지합니다. -c 는 -C와 동일하지만 편집기를 엽니다.
오.. 다 쓰기엔 너무 많아요! rebase를 사용해보시면 아래 주석으로 여러가지가 뜨는데 사용하실때 참고하시면 될 것 같아요!
참고 링크
https://www.atlassian.com/ko/git/tutorials/merging-vs-rebasing
병합과 기준 재지정(rebase) 비교 | Atlassian Git Tutorial
관련된 git merge 명령으로 git rebase를 비교하고 잠재적인 모든 기회를 식별하여 일반 Git 워크플로우로 기준 재지정을 통합합니다.
www.atlassian.com