git에서 merge --squash와 rebase의 차이점은 무엇입니까?


363

나는 git을 처음 사용하고 스쿼시와 rebase의 차이점을 이해하려고합니다. 알다시피 리베이스를 할 때 스쿼시를 수행합니다.

답변:


360

모두 git merge --squashgit rebase --interactive"숙청"커밋 생성 할 수 있습니다.
그러나 그들은 다른 목적으로 사용됩니다.

병합 관계를 표시하지 않고 대상 브랜치에서 스쿼시 커밋을 생성합니다.
(참고 : 커밋을 즉시 생성하지는 않습니다 : 추가가 필요합니다 git commit -m "squash branch")
소스 분기를 완전히 버리고 ( SO question 에서 가져온 스키마)에서 유용합니다 .

 git checkout stable

      X                   stable
     /                   
a---b---c---d---e---f---g tmp

에:

git merge --squash tmp
git commit -m "squash tmp"

      X-------------------G stable
     /                   
a---b---c---d---e---f---g tmp

그런 다음 tmp분기 를 삭제 합니다.


참고 : git merge--commit옵션을 있지만 사용할 수 없습니다 --squash. 없었다 결코 사용할 수 --commit--squash함께.
Git 2.22.1 (2019 년 3 분기) 이후이 비 호환성이 명시 적으로 나타납니다.

Vishal Verma ( )의 commit 1d14d0c (2019 년 5 월 24 일)를 참조하십시오 . ( Junio ​​C Hamano의해 병합 - 커밋 33f2790 , 2019 년 7 월 25 일)reloadbrain
gitster

merge: 쓰레기 --commit--squash

이전에는 --squash공급시 ' option_commit'가 자동으로 삭제되었습니다. 이는 --commit명시 적으로 스쿼시의 커밋 없음 동작을 무시하려고 시도한 사용자에게는 놀라운 일이 아닙니다 .

git/git builtin/merge.c#cmd_merge() 이제 다음이 포함됩니다 :

if (option_commit > 0)
    die(_("You cannot combine --squash with --commit."));

새로운 기반에서 커밋의 일부 또는 전부를 재생하여 스쿼시 (또는 최근에 "수정",이 SO 질문 참조 )하여 다음으로 바로 이동합니다.

git checkout tmp
git rebase -i stable

      stable
      X-------------------G tmp
     /                     
a---b

모든 커밋을 스쿼시하기로 선택한 경우 tmp(와 반대로 merge --squash일부를 재생하고 다른 스쿼시를 선택할 수 있습니다).

차이점은 다음과 같습니다.

  • squash소스 분기 ( tmp여기)를 건드리지 않고 원하는 곳에 단일 커밋을 만듭니다.
  • rebase다음을 사용 하여 동일한 소스 분기 (여전히 tmp) 를 진행할 수 있습니다 .
    • 새로운 기지
    • 더 깨끗한 역사

11
G되어 c--d--e--f--g함께 숙청?
Wayne Conrad

8
@Wayne : 예, 예에서 G는 tmp커밋 된 커밋을 나타냅니다 .
VonC

3
@ Th4wn : 모든 프로젝트의 스냅 샷이있는 Git 이유 때문에에서 도입 된 변경 사항으로 인해 G와 (과) 동일한 콘텐츠를 나타내지 않습니다 . gX
VonC

1
@VonC : 마지막 의견에 대해 잘 모르겠습니다. 당신이있는 경우 git merge --no-ff temp대신 git merge --squash temp에, 당신은 지저분 기록을 얻을 수 있지만, 당신은 또한 같은 일을 할 수있는 git revert e훨씬 더 쉽게. 지저분하지만 정직하고 실용적인 역사이며, 주요 지점은 여전히 ​​깨끗합니다.
naught101

2
동의합니다. 에서 설명하고있는 바와 같이 stackoverflow.com/a/7425751/6309 하지만, 그것은 또한 약 파괴하지 git bisectgit blame(같이 너무 자주 사용하는 경우 git pull --no-ff: stackoverflow.com/questions/12798767/... ). 어쨌든 하나의 접근 방식이
없으므로이

183

커밋 병합 : 브랜치에서 모든 커밋을 유지하고 기본 브랜치에서 커밋으로 인터리브여기에 이미지 설명을 입력하십시오

스쿼시 병합 : 변경 사항은 유지하지만 기록에서 개별 커밋을 생략합니다. 여기에 이미지 설명을 입력하십시오

Rebase : 이렇게하면 전체 기능 분기가 마스터 분기의 끝에서 시작하여 마스터에 모든 새로운 커밋을 효과적으로 통합합니다.

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

여기에


81

스쿼시 병합은 트리 (일련의 커밋)를 단일 커밋으로 병합합니다. 즉, n 확약 에서 작성된 모든 변경 사항을 단일 확약으로 스쿼시 합니다 .

Rebasing은 re-basing, 즉 트리에 대한 새로운 기본 (부모 커밋)을 선택하는 것입니다. 아마도 이것에 대한 수은 용어는 더 분명 할 것입니다. 그들은 단지 그것을 이식이라고 부릅니다. 나무에 대한 새로운 근거를 선택합니다.

대화식 리베이스를 수행 할 때 리베이스하려는 커밋을 스쿼시, 선택, 편집 또는 건너 뛸 수있는 옵션이 제공됩니다.

그 희망은 분명했다!


7
언제 리베이스하고 언제 스쿼시해야합니까?
Martin Thoma

31

다음 예제로 시작하겠습니다.

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

이제 기능 분기의 변경 사항 을 마스터 분기 로 병합하는 3 가지 옵션이 있습니다 .

  1. 커밋 병합 기능 분기
    의 모든 커밋 기록을 유지 하고 마스터 분기 로 이동합니다 . 더미 커밋이 추가됩니다.

  2. Rebase and merge 마스터 브랜치 앞의 기능 브랜치
    의 모든 커밋 히스토리를 추가합니다 . 더미 커밋을 추가하지 않습니다.

  3. 스쿼시 및 병합
    Will은 모든 기능 분기 커밋을 하나의 커밋으로 그룹화 다음 마스터 분기 앞에 추가합니다
    . 더미 커밋이 추가됩니다.

아래에서 마스터 브랜치 가 각 브랜치 를 어떻게 관리하는지 확인할 수 있습니다 .

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

모든 경우에 : 기능 분기를
안전하게 삭제할 수 있습니다 .


1
두 번째 그림에서 더미 커밋이 무엇인지 설명 할 수 있습니까 ?? 나는 자식의 초보자입니다.
Yusuf

1
@Yusuf, 그것은 두 가지 업데이트를 모두 포함하는 추가 커밋입니다. 기본 커밋 메시지 = "Megre branch XYZ to master"
ahmednabil88
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.