git pull이 기본적으로 rebase 대신 병합을 수행하는 이유는 무엇입니까?


71

다음 상황을 고려하십시오.

  • 자식 저장소의 복제본이 있습니다.
  • 로컬 커밋이 있습니다 (커밋되지 않은 커밋)
  • 원격 저장소에 아직 조정하지 않은 새 커밋이 있습니다.

그래서 이런 식으로 :

병합되지 않은 커밋

git pull기본 설정으로 실행 하면 다음과 같은 결과가 나타납니다.

병합 커밋

git이 병합을 수행했기 때문입니다.

그러나 대안이 있습니다. pull 대신 rebase를 수행하도록 지시 할 수 있습니다.

git pull --rebase

그리고 당신은 이것을 얻을 것입니다 :

재 기반

내 생각에, rebased 버전은 코드와 기록을 모두 깨끗하게 유지하는 데 주로 도움이되는 많은 장점이 있으므로 git이 기본적으로 병합을 수행한다는 사실에 약간 충격을 받았습니다. 예, 지역 커밋의 해시가 변경 될 것입니다. 그러나 이것은 당신이 얻는 더 간단한 역사를 지불하는 작은 가격 인 것 같습니다.

결코 이것이 나쁘거나 잘못된 기본이라고 제안하는 것은 아닙니다. 병합이 기본값보다 선호되는 이유를 생각하는 데 어려움을 겪고 있습니다. 왜 선택되었는지에 대한 통찰력이 있습니까? 기본값으로 더 적합하게 만드는 이점이 있습니까?

이 질문의 주된 동기는 우리 회사가 개발자가 이전에 작업하지 않은 저장소에 더 쉽게 접근 할 수 있도록 저장소를 구성하고 관리하는 방법에 대한 몇 가지 기준 표준 (가이드 라인과 유사 함)을 설정하려고한다는 것입니다. 나는 우리가 보통 이런 유형의 상황에서 리베이스 해야하는 경우에 관심이 있습니다 (그리고 아마도 개발자가 기본적으로 글로벌 구성을 리베이스하도록 설정하도록 권장하기 위해 권장합니다). 너무 큰 경우 기본값. 그래서 내가 놓친 것이 있는지 궁금합니다.

이 질문은 왜 많은 웹 사이트가“git merge”보다“git rebase”를 선호 하는가? ; 그러나 그 질문은 이것 의 반대 입니다. 병합보다 rebase의 장점을 논의하는 반면,이 질문은 병합보다 rebase의 이점에 대해 묻습니다. 거기에 대한 답변은 병합 문제와 rebase의 이점에 중점을 둔 이것을 반영합니다.


6
가능한 많은
gbjbaanb

다른 문제는 실수로 마스터에 커밋 한 다음 병합 된 풀을 수행하면 병합이 정상으로 보이더라도 두 마스터가 동기화되지 않을 수 있다는 것입니다. 이것이 바로 풀 별칭에 --ff-only가 포함 된 이유입니다.
Ixrec

소스 트리가 그래프보기를 변경하여 리베이스 / 병합이 다르게 표시되면 병합으로 전환 하시겠습니까?
Ewan

1
@Ewan SourceTree는 이것의 그래프 뷰를 변경해서는 안됩니다. 그래프를 정확하게 나타냅니다.
jpmc26

4
유권자 유권자의 경우, 내가 수락 한 답변의 내용이 귀하가 주장하는 질문에 가장 명확하게 존재 하지 않는다는 점에 유의하십시오 .
jpmc26

답변:


56

해당 결정을 내린 사람의 말을 듣지 않고 병합이 왜 기본이 아닌지 확실히 알기가 어렵습니다.

여기 이론이있다 ...

힘내는 모든 당김을 기절시키는 것이 좋다고 추정 할 수 없다. 어떻게 들리는 지 들어보세요. "모든 당김을 재조정하십시오." 풀 요청 또는 이와 유사한 것을 사용하면 잘못 들립니다. 풀 요청을 기반으로 하시겠습니까?

중앙 집중식 소스 제어를 위해 Git을 사용하지 않는 팀에서 ...

  • 상류와 하류에서 끌어 올 수 있습니다. 일부 사람들은 다운 스트림, 컨트 리뷰 터 등에서 많은 노력을 기울입니다.

  • 다른 개발자와 긴밀하게 협력하여 기능을 공유하거나 공유 주제 지점에서 가져 와서 때때로 업스트림에서 업데이트 할 수 있습니다. 항상 리베이스하면 재미있는 충돌주기를 언급하지 않고 공유 기록을 변경하게됩니다.

Git은 모든 사람이 하나의 중앙 저장소로 끌어 당기지 않는 대규모 분산 팀을 위해 설계되었습니다 . 따라서 기본값은 의미가 있습니다.

  • 언제 리베이스해야하는지 모르는 개발자는 기본적으로 병합됩니다.
  • 개발자는 원하는 때 리베이스 할 수 있습니다.
  • 끌어 당기는 횟수가 많고 끌어 당기는 횟수가 많은 커밋은 가장 적합한 기본값을 얻습니다.

의도의 증거를 위해, 리누스 토발즈 (Rinus Torvalds)가 리베이스하지 말아야 할 시점에 대한 그의 견해와 잘 알려진 이메일에 대한 링크가 있습니다. Dri-devel git pull 이메일

전체 스레드를 따르면 한 개발자가 다른 개발자로부터 당기고 Linus가 두 개발자 모두에서 당기고 있음을 알 수 있습니다. 그는 자신의 의견을 매우 명확하게한다. 그는 아마도 Git의 기본값을 결정했을 것이므로 이유를 설명 할 수 있습니다.

많은 사람들이 이제 중앙 집중식으로 Git을 사용합니다. 소규모 팀의 모든 사람이 업스트림 중앙 저장소에서만 가져와 동일한 리모컨으로 밀어냅니다. 이 시나리오는 리베이스가 좋지 않은 상황을 피하지만 일반적으로 제거하지는 않습니다.

제안 : 기본값을 변경하는 정책을 만들지 마십시오. Git을 큰 개발자 그룹과 함께 만들 때마다 일부 개발자는 Git을 깊이 이해하지 못합니다 (자체 포함). 그들은 Google에 가서 요리 책 조언을 얻은 다음 왜 작동하지 않는 이유, 예를 들어 git checkout --ours <path>파일의 잘못된 버전을 얻는 이유를 궁금해 합니다. 당신은 항상 당신의 취향에 맞게 지역 환경을 수정하고, 별칭을 만들 수 있습니다.


5
+1 기본값을 변경하지 않는 -보다는이 존재 하나를 잡기 위해 아마 더 나은 자신의 자식 워크 플로우를 압연 (예 : 골드 피처의 문서화 사람의 atlassian.com/git/tutorials/comparing-workflows/... )
롭 교회

1
답변 해주셔서 감사합니다. 하류에서 당기는 것에 대한 정보는 내가 놓친 것입니다. 또한, 흥미롭게도, 당신이 준 링크 내가 달성하고자하는 것을 정확히 장려 : "사람들은 (그리고 아마도해야한다) 그 리베이스 수 있습니다 개인 . 나무 (자신의 일을)"
jpmc26

2
@jpmc 좋아요. 과연. 개인 나무를 rebasing하면 공유 역사에서 많은 혼란을 피할 수 있습니다. 내가한다. 중요하지 않은 것은 명확하지 않습니다.
joshp

"일부 개발자들은 Git을 깊이 이해하지 못합니다." Rebase는 Git의 고급 기능 ( "깊은"등)이 아닙니다. 정말로 이해하기 어려운 것을 생각하십니까? 나는 이것이 무능한 개발자를 부르는 방아쇠라고 생각합니다.
빅터 Yarema

15

rebase에 대한 git 맨 페이지를 읽으면 다음과 같이 표시됩니다 .

다른 사람이 작업 한 브랜치를 리베이스 (또는 다른 형태의 재 작성)하는 것은 나쁜 생각입니다. 이 섹션에서는 다운 스트림 관점에서 수정을 수행하는 방법에 대해 설명합니다. 그러나 실제 수정은 처음부터 업스트림을 리베이스하지 않는 것입니다.

나는 리브를 전혀 사용하지 않는 이유로서 충분하다고 말합니다. 어떤 사람들은 rebase가 해롭다 고 생각 합니다. 아마도 그것은 git에 전혀 들어 가지 않았을 것입니다. 역사상 가장 중요한 것은 역사를 보존하는 것이기 때문에 SCM에는 필요하지 않은 역사를 보존하는 것입니다.

'역사를 깨끗하게 유지하라'고 말할 때 자신이 틀렸다고 생각하십시오. 더 좋아 보일지 모르지만 개정 내역을 유지하도록 설계된 도구의 경우 모든 커밋을 유지하는 것이 훨씬 깔끔하여 어떤 일이 발생했는지 확인할 수 있습니다. 나중에 역사를 살균하는 것은 푸른 녹을 닦는 것과 같습니다.


3
@Ewan IMHO는 "작동하지 않지만 예쁘게 보인다"는 IT가 아닌 패션 산업만을 위해 예약해야하는 것입니다. IMHO git은 너무 많은 사람들이 스타일이 물질보다 중요하다고 생각하기 때문에 그것을 제거해야합니다.
gbjbaanb

12
나는 역사를 깨끗하게 유지하는 것이 쓸모 없다는 당신의 제안에 반박 할 것입니다. 그렇지 않습니다. 리포지토리 기록은 사람이 사용하도록 만들어 졌으므로 읽을 수있게 만드는 데 많은 가치가 있습니다. 필자의 특정 유스 케이스에서는 개발자아닌 프로젝트 관리자가 기록을 읽을 수 있기를 원합니다. 클린 히스토리는 그것만으로 도움이 될 수 있으며 코드베이스를 보지 못했고 다이빙을하고 버그를 수정 해야하는 새로운 개발자가 특정 코드 영역에서 발생한 일을 이해하는 데 도움이 될 수 있습니다.
jpmc26

3
코드는 가장 먼저 기계에 의해 실행됩니다 (아마 컴파일 된 후). 위의 철학을 적용하면 코드의 가독성이 중요하지 않다는 결론을 내릴 것입니다. 가독성이 충분하지 않으면 코드를 이해하기가 어렵습니다. 나는 무엇이든 찌그러 뜨리라고 제안한 적이 없다. 나는 단지 많은 교차로로 분기되는 복잡한 그래프를 따르기가 어렵다고 말하고 있기 때문에 역사를 깨끗하게 유지하는 데 약간의 투자 가치가 있습니다. 선형 이력은 비난이나 이등분과 같은 자식 도구를 활용하는 데 더 도움이됩니다.
jpmc26

6
문서는 "리베이스하지 마십시오"라고 말하지 않습니다. " 다른 사람들의 업스트림에있는 변경 사항을 리베이스하지 마십시오 ." 이 둘 사이에는 차이가 있습니다. 리누스 자신은 받아 들여진 대답의 링크에서 볼 수 있듯이 역사 조직에 대한 일부 근거를 권고합니다 . 그리고 어떤 툴이 어떤 커밋이 관련이 없는지 (특히 툴이 비선형 히스토리를 분석하는 데 어려움이있는 경우) 어떻게 알 수 있습니까? (특히 히스토리를 파헤칠 수없는) 커밋하려는 커밋을 어떻게 알 수 있습니까? 특정 상황에 대해 독단적으로 극단주의를 기울이고 있습니다.
jpmc26

4
개발자가 한 모든 커밋이 포함되어 있다면 "수정 기록 유지"를 원하지 않을 것입니다. 이 논리에 따라 백 스페이스 키를 누를 때마다 원래 코드 버전도 기록해야합니다. 모든 커밋은 전체 프로젝트를 안정적으로 유지 하는 최소한의 완전한 변경 이어야합니다 . 원래 커밋이 나중에 버그로 판명되면 다른 커밋을 만드는 것보다 커밋을 리베이스 / 편집 / 수정하는 것이 좋습니다. 그러나 mail-archive.com/dri-devel@lists.sourceforge.net/msg39091.html
Mikko Rantalainen

12

로컬 / 변경된 저장소가 하나만 있다고 가정하면 정확합니다. 그러나 예를 들어 두 번째 로컬 PC가 있다고 생각하십시오.

로컬 / 수정 된 사본을 다른 곳으로 밀면 다른 곳으로 이동하면 해당 사본이 손상됩니다. 물론 강제로 밀어 붙일 수는 있지만 빨리 복잡해집니다. 이 중 하나 이상에 완전히 새로운 커밋이 있으면 어떻게됩니까?

보시다시피, 매우 상황이 좋지만 비 전략적 / 공동 작업의 경우 기본 전략이 훨씬 실용적입니다.


두 번째 차이점 : 병합 전략은 명확하고 시간 일관성있는 구조를 유지합니다. 리베이스 한 후에는 이전 커밋이 새로운 변경 사항을 따를 수 있으므로 전체 기록과 흐름을 이해하기 어려울 수 있습니다.


1
"리베이스 후에는 이전 커밋이 새로운 변경 사항을 따를 가능성이 큽니다."-하지만 병합에서도 발생하므로이를 이해하려면 예쁜 그래프가 필요할 수 있습니다. 커밋이 이루어진 시점이이 분기로 커밋을 합병하기 오래 전일 수 있습니다.
Steve Jessop

6

가장 큰 이유는 아마도 기본 동작이 공개 리포지토리에서 "작동"해야하기 때문일 것입니다. 다른 사람들이 이미 합병 한 역사를 재건하면 문제를 일으킬 것입니다. 나는 당신이 당신의 개인 저장소에 대해 이야기하고 있다는 것을 알고 있지만 일반적으로 git은 개인 또는 공공의 것을 알거나 신경 쓰지 않으므로 선택한 기본값이 둘 다의 기본값이됩니다.

나는 git pull --rebase내 개인 저장소에서 꽤 많이 사용 하지만 잠재적 인 단점이 있습니다. 즉, HEAD실제로 작업했을 때 내 역사에 더 이상 나무가 반영되지 않는다는 것입니다.

큰 예를 들어, 항상 테스트를 실행하고 커밋을 수행하기 전에 테스트를 통과한다고 가정합니다. 이것은 git pull --rebase각 커밋의 트리가 테스트를 통과했다는 사실이 더 이상 사실이 아니기 때문에 관련성이 적습니다 . 변경 사항이 어떤 식 으로든 방해받지 않고 내가 뽑은 코드가 테스트 된 경우 테스트를 통과 했을 것 입니다 .하지만 시도하지 않았기 때문에 알 수 없습니다. 지속적인 통합이 워크 플로의 중요한 부분이라면 CI를 사용하는 리포지토리의 모든 종류의 리베이스가 문제입니다.

나는 이것을 정말로 신경 쓰지 않지만 일부 사람들을 귀찮게합니다 : git의 역사는 실제로 작업 한 코드를 반영하는 것을 선호합니다 (또는 아마도 그것을 밀 때까지, 사용 후 진실의 단순화 된 버전) "수정").

특히이 문제가 Linus가 기본적으로 리베이스하지 않고 병합하기로 선택한 이유인지는 모르겠습니다. 내가 겪지 않은 다른 단점이있을 수 있습니다. 그러나 코드에 자신의 의견을 표현하는 데 부끄러워하지 않기 때문에 자신이 생각하는 것을 너무 많이 생각하지 않는 사람들 (특히 공공 장소에서 일하는 사람들)에게 적합한 워크 플로우라고 생각합니다. 개인 저장소보다). 예를 들어 병렬 개발을 나타내지 않는 깨끗한 직선을 선호하여 예쁜 그래프에서 평행선을 피하는 것은 아마도 당신의 것이더라도 그의 최우선 순위가 아닙니다 :-)

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.