2016-12-27 8 views
1

. 내 이해는 현재 브랜치와 mybranch에 대한 공통 기본 커밋을 찾을 때까지 커밋 트리에서 다시 검색하는 것입니다. 그런 다음 기본 노드의 모든 커밋을 mybranch의 헤드까지 현재 분기 헤드로 다시 적용 (리베이스)합니다. 그러나이를 인덱스/작업 공간으로 옮겨서 단일 커밋으로 적용 할 수 있습니다. 완료되면 병합 된 두 가지 분기를 표시하는 정상적인 병합이 있으므로 병합 노드가 없습니다. 나는 정확한 이해가 있나?git가 병합되지 않습니다 - 스쿼시가 실제로 rebase-squash입니까? 수행하는 작업이 더 병합보다 REBASE처럼 많이 보이기 때문에 명령</p> <pre><code>git merge --squash mybranch </code></pre> <p>이</p> <pre><code>git rebase -squash mybranch </code></pre> <p>호출되지 않는 이유를 이해하려고 노력

+0

'merge --squash'는 브랜치의 모든 커밋을 하나로 스쿼시합니다. 기록을 수정하지 않습니다. –

+0

앤디 (Andy)가 말한 바에 따르면 병합이 발생하기 전에 스쿼시가 발생하기 때문에 대상 분기의 관점에서 여전히 병합이 발생합니다. –

+0

내 포인트는 정규 병합 후였습니다. 그래프는 병합 된 2 개의 분기가 1 병합 노드로 결합되었지만 병합 후에 - 스쿼시 및 커밋 후에 그래프는 두 개의 분기가 여전히 분리되어 있지만 mybranch의 변경 사항이 단일 커밋으로 스쿼시되었음을 보여줍니다 현재 분기에. 나에게 그것은 하나의 커밋으로 찌그러 뜨린 rebase처럼 보인다.그러나 내가 물어 보는 진정한 질문은 스쿼시 병합에 대한 개념이 근본적으로 정확하고 @torek의 확장 된 답변에서 배울 점이 더 복잡한 세부 사항이지만 결론에 도달했다는 것입니다. – JonN

답변

2

글쎄, 병합 및 리베이스는 근본적으로 다른 작업입니다. 병합-로하는 나는 새로운 병합 커밋 않습니다 실제로 일반적인 가장 최근의 커밋의 커밋 그래프를 통해 다시 검색 생성하는 일반 git merge을 의미 :

...--o--*--o--o--A <-- mainbr 
     \ 
      B--C--D--E <-- sidebr 

을 여기에, 일반적인 가장 최근의 커밋은 *입니다. 병합 프로세스는 git diff과 같이 *을 커밋하여 A을 커밋하고 "수행 한 작업"을 확인하고 E에 대해 *을 대조하여 "수행 한 작업"을 찾습니다. M* diffing의 것은 "중 하나를 제공하도록, 두 역사를 조인하고,"그들이 무슨 짓을했는지 ""우리가 무슨 짓을했는지 "와 결합

...--o--*--o--o--A---M <-- mainbr 
     \  /
      B--C--D--E <-- sidebr 

: 그런 다음 새로운 하나의 병합은 두 부모, 커밋한다 각 변화 ".

여기 병합 기준을 선택할 수 없다는 점에 유의하십시오. 힘내다는 사실을 알아 내십시오.

Rebase는 복사 할 커밋과 복사 할 커밋 모두를 말할 수 있습니다. 기본적으로 커밋은 *입니다. 다시 입니다. 그렇지만 복사본 복사본을 하나씩 git cherry-pick 또는 그와 동등한 코드를 사용하여 커밋합니다. 마지막으로 지점 을 마지막으로 복사 된 커밋을 가리 키도록 이동합니다.

...--o--*--o--o--A <-- mainbr 
     \  \ 
      \  B'-C'-D'-E' <-- sidebr 
      \ 
      B--C--D--E 

(이 경우 B-C-D-E) 커밋 원래 체인은 여전히 ​​검색 가능 저장소에 아직이고 : 그들은 해시 ID 발견하고 sidebr 대한 reflog에 될 수있는 임의의 다른 경우 지점 또는 태그 이름을 사용하면 도달 할 수 있고 그 이름으로 도달 할 수 있습니다. 무엇 git merge --squash

그냥 약간 병합 프로세스를 수정하는 것입니다 : 대신 M을 커밋 병합 만드는, 힘내 병합 기계를 통과 평소와 같이, 병합 기초 - 당신이하지 않는 diffing의 것은 선택-에 대해 할 수있는 현재 커밋과 다른 커밋, 그리고 인덱스와 작업 트리의 변경 내용을 결합합니다.그것은 다음-에 대한 명백한 이유 2 -stops하고 결과를 커밋 git commit를 실행하고 당신이 할 때, 그것은 보통, 비 병합, 커밋있어 수 있도록이 같은 전체 그래프 조각 외모 :

이제

...--o--*--o--o--A--F <-- mainbr 
     \ 
      B--C--D--E <-- sidebr 
목차로 인한 커밋 F 년 - 스냅 샷 트리 우리가 실제 병합을 수행 할 때 M 커밋의 내용과 같은 병합-이며, - 여기 진짜 키커 - 그것 또한 있어입니다 우리가 리베이스 할 때 커밋 E'의 내용과 같습니다.

또한, 사이드 브랜치 sidebr에 커밋 (B)이 하나만 있다고 가정합니다. 이제 merge, merge --squashrebase의 세 당신에게 우리가 이런 식으로 그릴 수있는 뭔가로 끝나는 사진을 줄 것이다 :

...--o--*--o--o--A--B' <-- ??? 
     \   ? 
      B????????? <-- ??? 

을하고 내용이 새의B', 최종 스냅 샷을 커밋한다 세 가지 경우 모두 동일합니다. 그러나 git merge의 경우 새 커밋은 mainbr 브랜치에 있고 AB을 가리키며 sidebrB을 가리 킵니다. git merge --squash의 경우, 새로운 커밋은 mainbr에 있으며 A으로 만 되돌아갑니다. 및 git rebase를 들어, 커밋 새로운 전혀 B에 아무것도 명백한 가리키는, sidebr에있을 것입니다, 우리는이 같은 그린다 :

...--o--*--o--o--A <-- mainbr 
     \  \ 
      B  B' <-- sidebr 

mainbr 이후 A을 커밋 가리 키도록 계속됩니다.

결국 이것은 리베이스 (rebase)처럼 병합하는 것처럼 보입니다. (이 모든에서 "스쿼시 병합"라는되지 않은 경우 그러나, 나는 행복 할 것입니다.)


1 힘내 *를 발견하는 방법은 다소 다르다 : 실제로 하나의 커밋이 아니다, 오히려 (보통) 아주 커다란 커밋 집합의 마지막 부분, 즉 <upstream> 인수에서부터 git rebase에 도달 할 수있는 모든 커밋들입니다. (혼동, 병합의 기본은 커밋의 집합이 될 수 있지만, 그것은 훨씬 더 제한된 세트입니다. 최상의 아직 그래프 이론에 뛰어하지. :-))

2 우리가 를 원하는 경우 중지하려면 --no-commit을 일반 스펀지가 아닌 git merge처럼 사용할 수 있습니다. 그렇다면 이 자동으로 중지되는 이유는 무엇입니까?