[GIT] Git Merge, PR
Published:
In this post, concept and usage of Git merge, and PR is introduced.
Git 이 무엇인가와 초기 세팅 방법에 대한 기초적인 내용은 여기 참고.
Git Merge
Fast Forward란, 두 브랜치가 갈라지지 않았을 때 새로운 merge commit 없이, 포인터만 앞으로 옮기는 병합을 의미한다. 아래 같은 경우 fast forward가 가능하다. 각 알파벳은 커밋을 의미한다.
A -- B -- C (main)
\
D -- E (feature)
A -- B -- C -- D -- E (main)
반면, 아래와 같은 경우는 fast forward가 불가능하고 별도의 merge commit이 필요하다.
A -- B -- C -- F (main)
\
D -- E (feature)
A -- B -- C -- F ------ M (main)
\ /
D -- E --------
M은 merge commit을 의미한다.
Gir merge 옵션에는 4가지가 있다.
--no-ff: fast-forward 가능해도 항상 merge 커밋 생성--ff: 기본 설정. fast-forward 시도하고 불가하면 merge 커밋 생성.--ff-only: fast-forward 시도하고 불가하면 merge 안함.--squash: 위 예시에서 merge하여 main에 D, E 커밋 기록을 남기지 않고, 하나의 커밋을 남김.A -- B -- C -- S
PR
보통은 로컬에서 git merge를 한 다음, 이를 원격으로 push 하기보단, PR을 만들어서 GitHub에서 Merge 버튼을 누른다.
따라서, 위 4가지 merge 방법에 대응하는 PR merge 방법이 github에 버튼으로 존재한다.
| PR 버튼 | 내부적으로 하는 일 | CLI 개념 |
|---|---|---|
| Create a merge commit | 항상 merge commit 생성 | git merge --no-ff |
| Squash and merge | 커밋 여러 개 → 하나로 합침 | git merge --squash |
| Rebase and merge | 커밋을 base 위로 재배치 | git rebase + git merge --ff-only |
Create a merge commit
A -- B -- C -------- M \ / D -- E브랜치에서 작업한 D, E 커밋을 그대로 유지
- 마지막에 “합쳤다”는 표시용 커밋 M 생성
Squash and merge
A -- B -- C -- S- D, E 같은 여러 커밋을 하나(S)로 합쳐서 main 브랜치에 한 커밋만 추가
Rebase and merge
A -- B -- C -- D' -- E'- D, E를 C 뒤로 “다시 써서” 붙임. merge 커밋 없음. fast-forward처럼 보임
git rebase란, git merge와 다르게 커밋 히스토리를 보존하지 않고 재작성하여 내 커밋들을 최신 브랜치 위로 다시 올려놓는 것을 의미한다. rebase B to A 시,
- A, B 공통 조상 찾는다
- B에서 공통 조상 이후 커밋들을 뽑아낸다
- A의 최신 커밋 위에 B 커밋을 하나씩 다시 적용(cherry-pick)
main: A --- B --- C
\
feature: D --- E
위 상황에서 git merge 하면 (git checkout feature, git merge main) 히스토리가 갈라졌다가 다시 합쳐져 커밋 그래프가 복잡해진다.
A --- B --- C
\ \
D --- E ---- M (merge commit)
git rebase 하면 (git checkout feature, git rebase main) D, E를 잠깐 떼어내서 main 최신(C) 위에 다시 붙이게 된다.
A --- B --- C --- D' --- E'
PR merge conflict
merge conflict이 날 때 2가지 해결 방법이 있다. 그 전에 이를 이해하기 위해 branch와 fetch의 개념을 간단히 알아보자.
브랜치는 그냥 어느 커밋을 가리키고 있는 이름(포인터)다.
git fetch 는 원격 저장소 상황만 가져와서 알려주는 것으로, 로컬의 코드를 바꾸지 않는다. 예를들어, fetch 전 brach 상황이 아래와 같았다고 하자.
내 로컬:
main → C
원격(origin):
main → F
이 때, git fetch origin을 하면 아래처럼 바뀐다.
내 로컬:
main → C
origin/main → F
origin/main은 원격 main을 로컬에 복사해둔 포인터이다.
이제 conflict 발생시 2가지 해결방법을 알아보자. (//ToDo 다음에 이해)
내 로컬 브랜치에서 rebase(또는 merge)로 충돌을 해결하고 push
git checkout feature git fetch origin git rebase origin/main # 충돌 나면 파일 수정 git add <수정한 파일들> git rebase --continue # 반복 git push --force-with-lease
GitHub(PR)에서 “Resolve conflicts”로 해결해서 merge.
Git flow
git flow 란, 하나의 git 개발 규칙, 전략이다.

Leave a Comment