'git merge'와 'git rebase'의 차이점은 무엇입니까?


499

차이 무엇 git mergegit rebase?


14
내 답변이 삭제 되었으므로이
HiB

6
그건 그렇고 나는이 사이트를 추가 할 것입니다. git learn에 대해 알아야 할 모든 것 : pcottle.github.io/learnGitBranching
Rollyng

먼저 읽어보십시오 : git-scm.com/book/en/v2/… 그렇다면 : git-scm.com/book/en/v2/Git-Branching-Rebasing 당신은 정말로 이해할 것입니다.
Liber

답변:


867

가정 원래 3 커밋이 있었다, A, B, C:

알파벳

그런 다음 개발자 Dan은 commit을 작성 D했고 개발자 Ed는 commit을 작성했습니다 E.

에이 비 씨 디이

분명히,이 갈등은 어떻게 든 해결되어야합니다. 이를 위해 두 가지 방법이 있습니다.

합병 :

ABCDEM

두 커밋 D과는 E아직 여기있다, 그러나 우리는 커밋 병합을 만들 M모두으로부터 상속 변경 DE. 그러나 이것은 많은 사람들이 혼동되는 다이아몬드 모양을 만듭니다 .

REBASE :

ABCDER

R실제 파일 내용이 M위 의 merge commit의 내용과 동일한 commit을 만듭니다 . 그러나 커밋 E은 존재하지 않는 것처럼 제거합니다 (점-사라지는 선으로 표시). 이러한 소멸로 인해 E개발자 Ed에 로컬이어야하며 다른 저장소로 푸시 된 적이 없어야합니다. rebase의 장점은 다이아몬드 모양을 피하고 역사는 좋은 직선을 유지한다는 것입니다. 대부분의 개발자는 그것을 좋아합니다!


53
멋진 삽화. 그러나 나는 rebase가 처리되는 긍정적 인 음색에 전적으로 동의하지 않습니다. 병합 및 리베이스 충돌에서 수동 해결이 필요한 충돌이 발생할 수 있습니다. 그리고 프로그래머가 참여할 때 항상 버그가 될 수있는 무시할 수없는 오류가 있습니다. 병합 오류가 발생하면 전체 팀 또는 커뮤니티가 병합을보고 버그가 도입되었는지 확인할 수 있습니다. rebase의 역사는 1 명의 개발자 repo에 유지되며 심지어 reflog에서는 수명이 제한되어 있습니다. 더 좋아 보일지 모르지만, 아무도 잘못 된 것을 쉽게 볼 수 없습니다.
Uwe Geuder

> "그러나 이것은 많은 사람들이 혼동되는 다이아몬드 모양을 만듭니다." 음 ... 정교 할 수 있습니까?
Greg Maletic

@GregMaletic : 다이아몬드 모양은 비선형 역사입니다. 나는 당신에 대해 모른다. 그러나 나는 일반적으로 비선형적인 것을 좋아하지 않는다. 즉, 원하는 경우 다이아몬드와 병합을 사용하는 것이 좋습니다. 아무도 당신을 강요하지 않습니다.
mvp

1
이 답변은 매우 유용하지만 간단한 foo.txt 파일로 실제 git 명령을 추가하여 로컬로 재생하는 것이 좋습니다. 마지막 사용자가 말했듯이 누가 리베이스를하고 있는지는 분명하지 않습니다.
Vortex

1
@ pferrel : 나는 당신이 올바르게 생각하지 않습니다. git merge커밋을 인터리브하지 않습니다 (그러나 보았을 때 나타날 수 있습니다 git log). 대신, git mergeDan과 Ed의 개발 이력은 한 번에 하나의 관점에서 볼 때 그대로 유지됩니다. git rebaseDan이 먼저 작업 한 것처럼 보이고 Ed는 그를 따라갔습니다. 두 경우 모두 (병합 및 리베이스) 실제 결과 파일 트리는 완전히 동일합니다.
mvp

158

나는 git에 대해 내가 싫어하는 10 가지 발췌문을 정말 좋아합니다 (두 번째 예에서 rebase에 대한 간단한 설명을 제공합니다).

3. Crappy 문서

맨 페이지는 전능 한“f *** you” 1 입니다. 사용자가 아닌 컴퓨터 과학자의 관점에서 명령을 설명합니다. 지목 사항:

git-push – Update remote refs along with associated objects

인간에 대한 설명은 다음과 같습니다.

git-push – Upload changes from your local repository into a remote repository

업데이트, 다른 예 : (cgd 덕분에)

git-rebase – Forward-port local commits to the updated upstream head

번역:

git-rebase – Sequentially regenerate a series of commits so they can be 
             applied directly to the head node

그리고 우리는

git-merge - Join two or more development histories together

좋은 설명입니다.


1. 원본에서 무수정


문제는 언어가 아니거나 사용자가 컴퓨터 과학자인지 아닌지입니다. 다른 방법으로 단어를 바꾸면 목적 (즉, 발생하는 일)을 명확하게하는 데 도움이되지만 수단을 설명하는 데 실패합니다 (어떻게 발생하는지). 힘내는 목표를 이해하기 위해 수단을 이해해야합니다. Git을 어렵게 만드는 수단을 정확하게 이해하고 있습니다. Git은 작업에 필요한 노력을 단순화하거나 줄이는 데 사용되는 도구로서 끔찍하게 실패합니다. 안타깝게도 너무 많은 개발자들이 그것을 깨닫지 못합니다.
ATL_DEV

128

개인적으로 나는 표준 다이어그램 기법이 그다지 도움이되지 않는다고 생각합니다. 화살표는 항상 저에게 잘못된 길을 가리키는 것 같습니다. (일반적으로 각 커밋의 "부모"를 가리키며 시간이 지나면 이상합니다.)

단어로 설명하려면 :

  • 지점을 지점으로 리베이스 할 때 Git에게 지점을 깨끗하게 체크 아웃 한 것처럼 보이도록 지시 한 다음 거기서부터 모든 작업을 수행했습니다. 이를 통해 누군가가 검토 할 수있는 깨끗하고 개념적으로 간단한 변경 패키지를 만듭니다. 지점에 새로운 변경 사항이있을 때이 과정을 다시 반복 할 수 있으며 지점의 "팁"에 깨끗한 변경 사항이 항상 나타납니다.
  • 지점을 지점에 병합 하면 이 시점에서 두 지점 기록을 함께 묶습니다. 나중에 더 많은 변경 사항을 적용하여이 작업을 다시 수행하면 일부 변경 내용, 일부 변경 사항, 일부 변경 내용이 인터리브 된 기록 스레드를 만들기 시작합니다. 어떤 사람들은 이것이 지저분하거나 바람직하지 않다는 것을 알게됩니다.

내가 이해하지 못하는 이유 때문에 Git의 GUI 도구는 개별 병합을 추상화하여 병합 이력을보다 깔끔하게 제시하기 위해 많은 노력을 기울이지 않았습니다. "깨끗한 기록"을 원하면 리베이스를 사용해야합니다.

rebase 사용하는 프로그래머 와 rebase를 사용 하지 않는 다른 사람들의 블로그 게시물을 읽은 것을 기억 합니다.

나는 이것을 단지 단어로 설명하려고 노력할 것이다. 프로젝트의 다른 사람들이 사용자 인터페이스에서 작업하고 있으며 문서를 작성하고 있다고 가정 해 봅시다. 리베이스가 없으면 역사는 다음과 같이 보일 수 있습니다.

Write tutorial
Merge remote-tracking branch 'origin/master' into fixdocs
Bigger buttons
Drop down list
Extend README
Merge remote-tracking branch 'origin/master' into fixdocs
Make window larger
Fix a mistake in howto.md

즉, 문서 커밋 중에 병합 및 UI 커밋이 이루어집니다.

코드를 병합하지 않고 마스터에 리베이스하면 다음과 같습니다.

Write tutorial
Extend README
Fix a mistake in howto.md
Bigger buttons
Drop down list
Make window larger

모든 커밋은 맨 위 (최신)에 있고 나머지 master지점 은 그 뒤에 있습니다.

( 면책 조항 : 나는 다른 답변에서 언급 한 "Git에 대해 싫어하는 10 가지"의 저자입니다 )


42

인정되고 가장 많이 찬성 된 답변이 훌륭하지만, 나는 단어로만 차이점을 설명하는 것이 유용하다는 것을 알았습니다.

합병

  • “좋아요, 우리는 서로 다른 두 가지 저장소 상태를 얻었습니다. 그것들을 합치 자. 부모 두 명, 결과 아이 한 명.”

리베이스

  • “주 지점 (이름이 무엇이든)의 변경 사항을 기능 지점으로 변경하십시오. 사실 주요 지점의 현재 상태에서 나중에 시작된 기능 작업을 가장하여 그렇게하세요.”
  • "내 변화의 역사를 다시 써서 그것을 반영하십시오." (일반적으로 버전 관리는 주어진 기록을 무단 변경 하지 않기 때문에 강제로 푸시해야 함 )
  • "만약 내가 훔친 변화가 내 작업과 거의 관련이 없다면, 커밋 차이를 diff로 보면 역사는 실제로 크게 변하지 않을 것입니다 ( '패치'를 생각할 수도 있습니다)."

요약 : 가능하면 리베이스가 거의 항상 좋습니다. 메인 지점으로의 재 통합이 쉬워집니다.

때문에? feature 주요 작업과 관련하여 기능 작업을 하나의 큰 '패치 파일'(일명 diff) 로 표시 할 수 있으며 여러 부모를 '설명'할 필요가 없습니다. 두 개 이상, 하나의 병합에서 발생하지만 더 많은 경우 여러 번의 합병이있었습니다. 병합과 달리 여러 리베이스는 합산되지 않습니다. (또 다른 큰 플러스)


18

힘내 rebase는 병합에 더 가깝습니다. rebase의 차이점은 다음과 같습니다.

  • 로컬 커밋은 지점에서 일시적으로 제거됩니다.
  • 자식 풀을 실행
  • 모든 지역 커밋을 다시 삽입하십시오.

따라서 모든 원격 커밋 후에 모든 로컬 커밋이 끝으로 이동합니다. 병합 충돌이 있으면 해결해야합니다.


7

이해하기 쉽게 내 그림을 볼 수 있습니다.

Rebase는 커밋 해시를 변경하므로 많은 충돌을 피하려면 분기가 안정적으로 완료 / 완료 될 때 rebase를 사용하십시오.

여기에 이미지 설명을 입력하십시오


0

git rebase vs merge 에 대한 흥미로운 기사를 찾았 습니다 .

  • 과거와 완전히 동일한 기록을 보려면 병합을 사용해야합니다. 병합은 기록을 유지하지만 rebase는 기록을 다시 씁니다.
  • 병합하면 기록에 새로운 커밋이 추가됩니다.
  • 리베이스는 복잡한 히스토리를 능률화하는 것이 좋으며 대화식 리베이스를 통해 커밋 히스토리를 변경할 수 있습니다.
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.