git flow란 깃에서 제공하는 강력한 브랜칭 기능을 활용한 변경이력 관리 전략입니다.
이 전략은 회사마다, 프로젝트마다 달라질 수 있습니다.
예를 들어 현재 내가 다니고 있는 wecode에서는 프로젝트를 진행할 때
메인 줄기가 되는 main branch
각 기능을 구현하는 feature/{기능} branch
둘을 가지고 진행하였으며 기능이 완성되면 main에 merge시켜 하나의 줄기로 합치는 작업을 해왔는데요.
이런식으로 브랜칭을 어떻게 할지 전략을 세우고 그에 맞게 작업하는 것을 git flow라고 합니다.
프로젝트를 진행하며 충돌이나 파일이 아예 삭제되버리는 이슈들이 가끔씩 발생되곤 했습니다.
이럴 경우 커밋 기록을 찾아서 revert를 하던지 복붙을 하던지 했어야 했는데 모든 feature 브랜치의 커밋 기록과 merge된 커밋 기록까지 나와버리니 찾기가 여간 힘든게 아니었습니다.
이런 이슈를 해결할 수 있는 것이 rebase입니다.
rebase란 커밋 기록을 작업하고 있는 branch를 우선적으로 나타나게 하거나 수많은 커밋 기록을 합치는 등 기록 관리에 굉장한 효율을 보여주고 있습니다.
그럼 어떻게 사용하는건지 한 번 알아볼까요?
먼저 CRA를 통해 react Project를 생성해주겠습니다.
저는 Main.js와 Login.js를 만들어주었습니다.
여기서 main과 login을 각각 작업하는 개발자가 있으며
서로 feature/main or login 브랜치를 생성해서 작업을 한다고 가정해보겠습니다.
import React from "react";
function Login() {
return <div>Login</div>;
}
export default Login;
위 코드를 작업했다는 가정하에 아래처럼 바꿔보겠습니다.
import React from "react";
function Login() {
return <div>Login!!!!!!</div>;
}
export default Login;
그리고 커밋을 날려줍니다.
(commit message : ADD : first commit)
그리고 어느정도 작업이 진행되었다고 가정하고 두 번째 커밋을 날려줍니다.
변경된 코드는 아래와 같습니다.
import React from "react";
function Login() {
return (
<div>
Login!!!!!!
<input type="text" placeholder="아이디 입력" />
<input type="password" placeholder="비밀번호 입력" />
</div>
);
}
export default Login;
(commit message : ADD : create input)
이제 푸시를 하고 git log로 커밋 기록을 확인해보겠습니다.
앞서 실행한 두 개의 커밋 기록이 정상적으로 보이네요
이제 main 브랜치에서 작업하는 다른 개발자가 되어봅시다.
main 브랜치에서 feature/main 브랜치를 생성하고 코드를 작성해줍니다.
import React from 'react'
function Main() {
return (
<div>Main!!</div>
)
}
export default Main
그리고 커밋 & 푸시까지 해줍니다.
(commit message : ADD : first commit main)
여기까지 한 후 깃허브 pull request에서 앞서 푸시했던 feature/login 브랜치를 rebase로 merge해줍니다.
- feature/login rebase and merge
그리고 feature/main도 rebase merge 해줍니다.
- feature/main rebase and merge
자 이제 feature/main에서 머지한 코드를 feature/login에 불러와보도록 하겠습니다.
main branch로 이동 후 "git pull origin main"으로 feature/main의 코드를 적용시킨 후
feature/login으로 이동해 "git merge main"하여 코드를 합쳐줍니다.
이제 git log 명령어로 커밋 기록을 확인해봅시다.
로그를 보니 feature/login, feature/main, merge된 커밋기록까지 전부 찍혀있습니다.
지금이야 작업량이 거의 미비하지만 나중에 프로젝트가 커질수록 이런 커밋은 굉장히 많아지고 복잡해질 것입니다.
이제 merge 대신 rebase를 사용해 둘의 커밋 차이를 비교해봅시다.
먼저 git reflog 명령어로 merge 이전 기록의 해시 코드를 가져와줍니다.
위에서 두 번째인 4f908d9가 되겠네요
이제 저 코드를 git reset --hard 명령어로 merge 전 시점으로 돌아갑니다.
그리고 git rebase main -i main 명령어로 rebase를 진행합니다.
그리하면 이전의 커밋된 내용이 나오네요.
이 내용을 수정하여 저장하면 넘어가지는데 여기서 Pick이라고 된 커밋의 기록이 남게됩니다.
pick을 다른 옵션으로 바꿀 수 있으며 정말 다양한 옵션이 존재하는데 저는 여기서 두 번째 커밋 기록을 squash를 뜻하는 s 옵션을 사용하겠습니다.
정상적으로 진행이 된다면 또 다른 내용이 나타납니다.
이전의 커밋 메세지들인데, 여기서 수정할 수 있습니다.
저는 그냥 넘어가겠습니다.
간혹 설정이 잘못되거나 충돌이 존재하면 rebase -i라는 문구가 표시됩니다. (설정에 따라 안보일수도 있습니다.)
충돌을 해결해주고 git rebase --continue 명령어로 마무리해주어야 합니다.
자 이제 커밋 기록이 정리되었네요. (first commit, create input이 두 번 찍힌 이유는 작성자의 실수입니다 하하.. ^^..)
현재 내가 있는 branch가 제일 상단에 위치하게되며 하나의 커밋 안에 여러개의 커밋 메세지가 묶여있는 형태입니다.
또 한 가지 확인할 수 있는 것은 바로 merge 기록이 사라졌다는 것이죠.
이로써 불필요한 커밋 기록을 줄이고 한 눈에 알아보기 쉬워졌습니다.
마무리하며
git rebase는 처음에 접했을 때 개인적으로 어려웠습니다.
그래도 잘 정리된 커밋 기록을 보면 공부하길 잘했다는 생각이 듭니다.
아래 오늘 배운 명령어에 대해 정리하고 마무리하도록 하겠습니다.
$ git rebase [-i] => git rebase를 진행할 때 커밋 메세지를 다시 설정할 수 있다.
$ git rebase --abort => rebase 도중 처음으로 돌아가고자 할 때 사용한다.
$ git rebase --continue => rebase 도중 충돌이 발생했을 때 충돌 해결 후 rebase를 다시 진행할 때 사용한다.
$ git reflog => git 명령 기록을 확인하며 각 시점의 hash 코드를 확인할 수 있다.
$ git reset => reflog에서 얻어낸 hash 코드를 가지고 특점 시점의 커밋으로 되돌아갈 수 있다.