두 Branch 간 History 및 형상을 통합하는 기능이다.
Fast forward merge
No fast forward merge
Merge가 완료되면 두 브랜치의 형상 History가 통합되어 기록되는데, 이 때 기록 방법이 두 가지로 나뉜다.
하나는 Fast Forward(이하 ff) 이며 통합된 History를 한 가닥으로 기록한다. 반면 다른 하나인 No Fast Forward(이하 no-ff) 는 두 가닥으로 표현하여 기록한다.
FF는 Commit history를 단순화할 수 있다는 장점이 있지만, 개발 History를 파악하기 어렵다는 단점이 있다.
반면 No-FF는 개발 History를 파악하기 용이하다는 장점이 있지만, Commit history가 복잡해질 수도 있다는 단점이 있다.
하지만 형상 관리라는 것이 개발 과정을 기록하고 후에 파악하기 용이하기 위한 것이 그 목적이므로, 보통은 No-FF Merge를 사용하는 편이다.
# Default : FF와 No-FF 중 git config에 설정된 방법으로 Merge
$ git merge <target-branch-name>
# Example
$ git merge Branch_B
# FF Merge
$ git merge --ff <target-branch-name>
# No-FF Merge
$ git merge --no-ff <target-branch-name>
주의사항
두 Branch의 History를 통합하여 기록할 곳을 둘 중에서 선정해야 한다.
그리고 그 Branch로 Checkout한 후에 Merge를 실행해야 한다.
Merge 이후 Target branch가 제거되는 것은 아니다.
Merge는 두 Branch를 합친다기보다는, 현재 HEAD가 위치한 Branch의 History 및 형상에다가 Target branch의 History 및 형상을 더한다는 의미가 더 가깝다.
추가로 특정 Commit 포인트와의 Merge도 가능하다.
그 때는 대신 를 지정하면 된다.
# Set ff as merge default
$ git config merge.ff true
# Set no-ff as merge default
$ git config merge.ff false
Merge를 하다보면 종종 Conflict가 발생하는 경우가 있다.
이는 두 Branch가 동일한 부모 branch로부터 파생되어 분리된 이후에, 동일한 위치의 코드가 각 Branch에서 수정이 발생했을 경우다.
Git은 동일한 위치의 두 가지 수정사항 중 어느 것이 올바른 것인지 스스로 판단하지 않고, 사용자에게 그 몫을 넘겨준다. 이것이 바로 Conflict다.
그리고 Conflict 발생 시, Git은 Confilict가 발생한 파일 목록을 출력하고, 파일의 해당 위치마다 다음과 같은 표식을 기록해둔다.
/*
##### Format #####
<<<<<<<<<<< HEAD
// Codes
======================
// Codes
>>>>>>>>>>> <target-branch-name> or <target-branch-commit-number>
*/
/* Example */
// ret = add(a, b);
<<<<<<<<<<< HEAD
ret = sub(a, b);
// Modified by jgchoi 201220
======================
ret = mul(a, b);
// Modified by jhkim 201214
>>>>>>>>>>> Branch_B
Conflict를 해결하는 방법은 Git이 기록해둔 두 개의 선택지(HEAD, Target-branch)에서 올바른 코드를 선택 또는 통합한 뒤 나머지는 지워주면 된다.
Conflict 수정이 모두 완료되면 다시 한 번 Commit을 실행한다. 그러면 Merge commit 포인트가 생성된다.
Git merge 기능을 통해서 코드를 통합하지 않고, Beyond compare 등의 툴을 사용하여 직접 통합할 수도 있다. 하지만 후자의 방법은 치명적인 단점이 존재하는데 이는 Target branch의 History가 모두 휘발된다는 것이다.
형상을 관리하고 추적하기 위해서는 Target branch의 History 또한 통합해야 하는데, 직접 통합은 오직 코드만 통합이 가능하기 때문이다.
👍👍👍