학습 정리
Branch
- 브랜치는 프로젝트을 바탕으로 독립적으로 개발을 할 수 있을 수 있는 저장소를 말한다.
- main(master)은 프로젝트의 Version을 관리하는 branch이다.
- main branch에서 수행하기 조심스러운 작업들을 branch를 생성하여 작업할 수 있다.
- main brach에서 merge 또는 pull request를 하지 않는 이상 main branch에는 영향을 미치지 않는다.
- 사용법
- 목록 조회 (-v 옵션 추가시 상세 정보)
- 브랜치 생성
- 브랜치 전환
git switch branch_name
git checkout branch_name
그러나 checkout은 이외에 많은 기능을 담당하기 때문에 단순 브랜치 전환의 경우에는 switch를 사용하는 것이 좋다.
- 브랜치 삭제
git branch -d branch_name
- 브랜치 생성과 동시에 전환
git checkout -b branch_name
git switch -c branch_name
- 이름 변경
git branch -m old_name new_name
Merge Branch
- 각자 수행한 작업들을 하나로 병합하고, 다시 같은 시작점에서 개발을 시작할 수 있다.
- 다른 브랜치에서 구현한 기능을 추가하기위해서 기능을 구현한 브랜치를 병합하는 방식으로 협업이 가능하다.
- 여러가지 방식이 존재한다.
아래 예시를 develop == main, feautre/task == feature_branch로 생각하자.
Fast-Forward Merge
main에는 추가적인 commit이 존재하지 않고

feature_branch에만 commit이 존재하면

main의 HEAD를 feature_branch의 HEAD 위치로 이동만 시키는 것이므로
별도의 Merge Commit Message가 없다.

- 장점
- 히스토리 그래프가 깔끔하다.
- Fast-Forward 관계라면 branch를 비교하는 것이 아니기 때문에 conflict가 나지 않는다.
- 단점
- main branch에 추가적인 commit이 존재할 경우 Fast-Forward Merge를 수행할 수 없다.
- 추가된 Commit들이 동일한 부분에서 작업이 이루어진 경우 conflict가 발생할 수 있다.
- 사용법
git merge branch_name
- 기본 옵션이 fast-forward이다.
- 병합을 진행할 두 branch가 Fast-forward 관계이면
Fast-forward merge
가 진행된다.
- 그렇지 않을 경우
3 way-merge
가 진행된다.
git merge --no-ff branch_name
- Fast-forward 관계이더라도 상관없이 Merge 커밋을 생성하여 병합한다.
git merge --ff-only branch_name
- 현재 브랜치와 병합 대상의 관계가 Fast-forward인 경우에만 병합을 진행한다.
- 아닌 경우에는 병합 X
3 Way-Merge (Merge Commit)

- main, feature_branch 각각에 commit이 존재하면 기본적으로 진행되는 Merge 방식이다.
- main, feature_branch의 마지막 commit과 두 branch의 공통되는 조상인 commit(base), 총 3개의 commit을 비교하는 방식으로 진행된다.
- base commit을 제외한 두 commit끼리 비교를 진행하면 기존 상태를 모르기 때문에 변경되었는지, conflict가 일어났는지도 알 수 없다. --> 3개의 commit을 비교하는 이유
- 한 곳에서만 변경한 부분은 변경된 곳으로 설정, 두 곳 모두 수정한 부분에서 conflict 발생
- 장점
- 해당 브랜치의 시작 지점을 알 수 있다.
- 브랜치의 모든 커밋이 그대로 남아 작업 내역을 보존할 수 있다.
- Merge가 되는 시점에도 Commit이 생긴다. (Merge Commit)
- 단점
- Commit이 불필요하게 많아지면 히스토리 그래프가 복잡해진다.
- Merge 순서와 Commit 순서가 별도로 기록되어 히스토리 관리가 어렵다.
- 사용법
git merge branch_name
- 두 branch가 Fast-Forward 관계가 아닐 경우
3 way-merge
로 merge 진행
git merge --no-ff branch_name
Squash Merge

- Squash는 여러 개의 커밋을 하나로 합치는 기능을 말한다.
- feature_branch의 커밋을 전부 하나의 커밋으로 합친 뒤 main에 commit하는 방식이다.
- 장점
- 하나로 합친 commit이 feature_branch를 참조하지 않기 때문에 깔끔하게 main 관리가 가능하다.
- 자잘한 commit 사항이 남지않고 병합이 되었다는 사실 자체에만 집중한 기록이 남는다. 이로인해 변경사항을 읽기에 수월하다.
- PR Title이 Commit Message가 되기 때문에 PR Title을 제대로 관리해야 한다.
- 단점
- atomic level의 rollback이 불가능하다.
- 일반적인 Merge Commit 보다 정보력이 떨어진다.
- 위의 두 문제 모두 feature_branch의 모든 커밋을 하나로 통합하기 때문이다.
- 사용법
git merge --squash feature_branch
- feature_branch의 모든 커밋을 하나의 커밋으로 만들어 merge를 진행한다.
Rebase
Fast-Forward 관계가 아닌 상황이다.

3 Way-Merge는 새로운 Commit Message를 만들어 연결하였지만, Rebase는 feature_branch의 Commit과 동일한 Commit을 생성해 main에 붙이는 것이다.

그렇기 때문에 c2, c3, c4의 commit id가 #c2, #c3, #c4로 변경된 것을 볼 수 있다.
이후에 main에서 feature_branch 대상으로 Fast-Forward Merge를 진행하면 된다.
- 장점
- 모든 커밋을 하나의 브랜치에서 작업한 것처럼 보이게 할 수 있다.
- merge commit을 남기지 않는다.
- atomic level의 rollback이 가능하다.
- commit 단위의 history 기록이 가능하다.
- 단점
- git에 익숙하지 않은 경우 어려움이 발생한다.
- 모든 commit에 대한 conflict를 해결해야할 수 있어야 한다.
- 그렇기 때문에 feature_branch에서 너무 큰 작업을 하면 안된다.
- feature의 단위를 너무 크게 잡아서는 안된다.
- 사용법
git switch feature_branch
git rebase main
- conflict 발생시 해결 후
git rebase --continue
git switch main
git merge --ff-only feature_branch
- 주의사항
- 원격에 push된 commit에 대한 것을 rebase하려고 하면 commit history가 꼬일 수 있다.
- 다른 팀원들이 해당 브랜치를 사용하지 않는다고 확신할 때, 커밋을 깔끔하게 정리하기 위해 사용가능하지만 이 경우에도 팀원들과 조율하는 것이 좋다.
- 일반적으로 rebase는 local에서 사용하고 협업시 가급적 merge 사용하자.