[Git] Pull Request를 보내기 전에, Rebase를 해야 할까요 혹은 merge commit을 만들어야 할까요?

Rebase vs Merge commit

목적: PR을 보내기 전에 내가 보낼 브랜치가 master와 fast-forward(컨플릭트 없이 바로 머지될 수 있는 상태)상태가 되도록 만든다.

그런데 매번 이렇게 할 필요는 없고,
1. PR을 보낼 브랜치가 master보다 너무 옛날 상태일때나
2. GitHub에서 PR을 보냈더니 ‘merge conflict warning’이 페이지에서 보일 때 (같은 코드가 고쳐졌을때 자동으로 보임)
만 하면 된다.

방법 1. (내 브랜치에 먼저 머지 후 풀리퀘)

  • master의 최신 상태를 내 브랜치에 merge시킨다.
  • master와 내가 똑같은 파일을 고쳤다면 conflict가 날 것이다. 그럼 해결한다.
  • 해결해서 만들어진 merge commit을 push한다 (merge commit이 새로 하나 생김)
  • 장점: 한 번의 ‘merge’만으로 쉽게 해결할 수 있다.
  • 단점: merge commit이 생겨서 깔끔하지 않다. 코드 수정한 의미있는 커밋만 보고싶을텐데 말이다.

방법 2. (리베이스 후 풀리퀘)

  • master의 최신 상태를 base로 해서 내 브랜치를 rebase한다.
  • rebase의 원리는, 내가 원하는 커밋을 base로 해서 내 브랜치가 마치 그 커밋에서 딴 것처럼 기록을 조작하는 것이다.
  • 내부에서 돌아가는 방식은, 내가 원래 딴 커밋에서부터 내가 목표하는 base커밋까지 하나씩 옮겨가면서 새로 커밋을 하는것이다.
(원래상태)

[3시커밋 --- 4시커밋 --- 5시커밋] 
  ㄴ--- 내브랜치커밋

(5시커밋을 베이스로 리베이스를 실행한다)
[3시커밋 --- 4시커밋 --- 5시커밋] 
              ㄴ--- 내브랜치커밋 // 한 커밋씩 옮겨가며 commit한다. 컨플릭이 나면 고쳐준다.

(Continue rebase를 누른다)
[3시커밋 --- 4시커밋 --- 5시커밋] 
                        ㄴ--- 내브랜치커밋 // 목표하는 5시커밋까지 왔다. 컨플릭이 나면 고쳐준다

  • 모두 완료되었으니 push를 해야하는데, 히스토리를 조작하는 위험한 작업이므로 force옵션을 넣어 push해야한다.
  • 결과: 내브랜치커밋이 master의 최신 상태인 5시커밋에서 딴 것처럼 히스토리가 조작된다. 그래서 내 브랜치에서 master로 Pull Request를 보냈을 때 fast-forward(컨플릭트 없이 바로 머지할 수 있는) 상태가 된다.
  • 장점: merge commit없이 깔끔한 커밋 히스토리를 만들 수 있다.
  • 단점: 만약 중간에 코드 컨플릭트가 나면 그 사이에 있는 커밋들 모두에서 컨플릭트를 수정해줘야 할 수 있다. 귀찮다.

언제 무엇을 써야하나?

  • Type 0. master에서 딴지 그리 오래 되지 않은 브랜치: 그냥 PR을 보내본다. conflict warning이 보이면 그 때 2번이나 3번 방법을 쓴다
  • Type 1. 내 브랜치에 커밋이 엄청 많다. 그리고 master랑 비슷한 코드를 만져서 컨플릭트가 날 가능성이 높다: 방법 1(내 브랜치에 먼저 머지 후 풀리퀘)을 사용한다.
  • Type 2. 내 브랜치에 커밋이 그리 많진 않다. 깔끔한 커밋 히스토리를 남기고 싶다(오픈소스 등): 방법 2(rebase)를 사용한다.

git rebase후 push 에러 해결

개요

내 브랜치에서 메인 브랜치를 찝어서 rebase를 한 뒤 push하면 아래와 같은 에러가 뜰 때가 있다.

rebase Updates were rejected because the tip of your current branch is behind 어쩌구저쩌구

뭐 내 브랜치 가리키는게 뒤에 있어서 샬라샬라 같은 문제인듯 하다.
여기서 pull을 받고 push를 하거나 혹은 commit하면
merge commit이 들어가거나 혹은 rebase해서 받아온 커밋이 복제되어서 두번 반복해서 들어가는 안예쁨이 있다.

해결

git push -f origin

로 포스 푸쉬를 하면 된다.
그럼 깔끔히 rebase된 상태로 서버에 올라간다.

may the force with you.

refer

http://stackoverflow.com/questions/15143042/cant-push-to-branch-after-rebase