git merge --squash를 사용하는 방법?


1208

원격 Git 서버가 있습니다. 수행하려는 시나리오는 다음과 같습니다.

  • 각 버그 / 기능마다 다른 Git 브랜치를 만듭니다.

  • 비공식 Git 메시지가있는 Git 브랜치에서 코드를 계속 커밋합니다.

  • 최상위 저장소에서 공식 Git 메시지를 사용하여 하나의 버그에 대해 하나의 커밋을 수행해야합니다.

그렇다면 모든 체크인에 대해 단 하나의 커밋을 얻도록 분기를 원격 분기로 병합하려면 어떻게해야합니까 (이 커밋 메시지를 제공하고 싶습니다)?


1
당신을 완전히 이해했는지는 모르겠지만 "문어 병합"을 원할 수도 있습니다.
MatrixFrog

26
나는 일반적으로 git rebase -i 를 사용 하여 모든 커밋을 하나의 커밋으로 축소하고 커밋 메시지를 다시 씁니다. 그런 다음 업스트림으로 보냅니다.
Edward Falk

17
git merge --squash한 번에 명령 줄에서 모두 수행하고 작동하기를 바랍니다. git rebase -i편집기를 불러오고 리베이스를 미세 조정할 수 있습니다. 속도는 느리지 만 수행중인 작업을 볼 수 있습니다. 또한 rebase와 merge의 차이점은 주석에 언급하기에는 너무 복잡합니다.
Edward Falk

4
이 모든 대답의 문제점은 로컬에서 마스터 분기에 있고 merge --squash 명령을 실행해야한다는 것입니다 ... 나는 마스터 분기가 아닌 기능 분기에서 merge --squash를 실행하고 싶습니다. 완료되면 기능 분기를 원격으로 푸시하고 PR을 제출할 수 있습니까? 가능합니까?
Alexander Mills

2
@ AlexanderMills, 두 번째 기능 분기 (마스터 분기에서 복제)가 필요하다고 생각합니다. 할 일 merge --squash새에 이전부터 한 다음 마스터에 새로운 지점을 병합합니다. 오래된 지점은 더 이상 사용되지 않습니다.
자이로 마이트

답변:


1998

버그 수정 지점이 호출 bugfix되었고 다음과 병합하려고 한다고 가정하십시오 master.

git checkout master
git merge --squash bugfix
git commit

이것은 bugfix지점 에서 모든 커밋을 가져 와서 1 개의 커밋으로 스쿼시하고 브랜치와 병합합니다 master.


설명 :

git checkout master

사용자로 전환 master지점.

git merge --squash bugfix

bugfix지점 에서 모든 커밋을 가져 와서 현재 지점과 병합합니다.

git commit

병합 된 변경 사항에서 단일 커미트를 작성합니다.

-m매개 변수를 생략하면 커밋을 완료하기 전에 스쿼시 된 커밋의 모든 메시지를 포함하는 초안 커밋 메시지를 수정할 수 있습니다.


222
이전 커밋 메시지에 대한 참조를 유지하려면 git commit( -m매개 변수 없이 ) 쓸 수 있으며 스쿼시 한 ​​모든 커밋 메시지가 포함 된 드래프트 된 커밋 메시지를 수정하게됩니다.
Alex

12
git commit --amend -m '...'나중에 수행하여 동일한 결과를 얻을 수 있습니다 .
Janusz Lenar

19
병합 충돌이 발생하여 이러한 충돌을 해결 git commit하면 더 이상 커밋 된 모든 커밋 메시지가 포함 된 유용한 커밋 메시지가 표시되지 않습니다. 이 경우 stackoverflow.com/a/11230783/923560을git commit --file .git/SQUASH_MSG 통해 시도하십시오 .
Abdull

23
쿼싱은 기본적으로 커밋이 스 쿼셔에 기여 한다는 것을 명심하십시오 . 원래 저자를 유지하려면 다음과 같이 명시 적으로 지정해야합니다.git commit -a --author="Author" --message="Issue title #id"
gaborous

5
git merge --squash현재 브랜치 위에 다른 커밋을 병합하는 것과 동일한 효과를 갖는 단일 커밋을 만들 수 있습니다. 그러나 병합 레코드를 생성하지 않으므로 결과로 풀 요청이 변경되지 않지만 병합으로 표시되지 않습니다! 따라서 해당 분기를 삭제하기 만하면됩니다.
am0wa

129

마침내 나를 위해 이것을 정리 한 것은 그것을 보여주는 주석 이었습니다 .

git checkout main
git merge --squash feature

수행하는 것과 같습니다.

git checkout feature
git diff main > feature.patch
git checkout main
patch -p1 < feature.patch
git add .

105 (!!) 커밋으로 기능 분기를 병합하고 모두 하나로 스쿼시하고 싶을 때 중간 커밋 (또는 적어도 커밋) 마다git rebase -i origin/master 병합 충돌을 별도로 해결해야하기 때문에 원하지 않습니다. 자식은 스스로 알아낼 수 없습니다). 를 사용 하면 전체 기능 분기를 병합하기위한 단일 커밋의 결과 를 얻을 수 있습니다. 그리고 최대 하나의 수동 충돌 해결 만하면됩니다.git merge --squash


75
먼저 기능 분기에서 병합을 수행 git merge master한 다음 git merge --squash feature마스터 분기 에서만 병합을 수행하는 것이 좋습니다 .
dotancohen

8
@dotancohen 오래된 코멘트를 준발해서 죄송합니다. :) git merge --squash feature마스터 브랜치에서 수행하기 전에 기능 브랜치에서 병합하면 어떤 이점이 있습니까?
bitsmack

57
먼저 마스터를 기능 분기로 병합하고 기능 분기의 수동 수정 사항을 처리하려고합니다. 또한 테스트를 실행하고 기능 분기가 올바르게 작동하는지 확인할 수 있습니다. 그런 다음 기능 분기를 마스터로 자동 병합 할 수 있습니다.
Dan Kohn

4
@dankohn 위의 설명에 대한 설명을 답변에 추가하는 것이 좋습니다.
guntbert

3
@bitsmack : 먼저 master를 기능으로 병합합니다. 이를 통해 기능을 마스터에 병합하기 전에 기능의 충돌을 해결할 수 있습니다.
Mike

97

스쿼시 옵션과 병합하려고합니다. 한 번에 하나의 지점을 만들고 싶을 때입니다.

git merge --squash feature1

단일 커밋과 동시에 모든 브랜치를 병합하려면 먼저 대화식으로 리베이스하고 각 기능을 스쿼시 한 ​​다음 문어 병합 :

git checkout feature1
git rebase -i master

한 커밋으로 스쿼시 한 ​​다음 다른 기능에 대해 반복하십시오.

git checkout master
git merge feature1 feature2 feature3 ...

마지막 병합은 한 번에 많은 분기를 병합하기 때문에 "문어 병합"입니다.

도움이 되었기를 바랍니다


3
왜 당신은 rebasing입니까?
Umair A.

12
@UmairAshraf 그것은 당신이 당신의 지점 내에서 스쿼시를 할 수있는 옵션을 제공하는 대화 형 rebase입니다.
andho

1
리베이스는 나쁜 생각입니다. 이미 게시 된 커밋을 리베이스하지 마십시오
Sebi2020

1
@ Sebi2020 git merge --squash는 이미 게시 된 커밋을 대화 형 리베이스보다 나쁜 방식으로 리베이스합니다. (피처 브랜치에서) 대화 형 리베이스는 부작용이 거의 없거나 전혀 없습니다.
xiix

1
@xiix 기능 분기를 사용하는 유일한 사람인 경우에만 적용됩니다. 이것은 당신이 할 수있는 가정이 아닙니다. Git-SCM 에서의 rebasing과 관련된 페이지를 읽는 것이 좋습니다 . " 저장소 외부에 존재하는 커밋을 리베이스하지 말고 사람들이 그에 대한 작업을 수행했을 수 있습니다. "라고 말합니다 . 자식의 본질) 당신은 그렇게하지 않아야합니다.
Sebi2020 년

23

이미 git merge bugfix켜져 있는 경우 다음을 사용 main하여 병합 커밋을 스쿼시 할 수 있습니다.

git reset --soft HEAD^1
git commit

git reset --soft HEAD^1적어도 병합이 빨리 진행되는 경우 병합 전에 수행 된 마지막 커밋을 취소하는 것 같습니다 .
Jesper Matthiesen

빨리 감기의 경우 @JesperMatthiesen은 병합 커밋을 얻지 않으므로 그렇게 할 것 git reset --soft HEAD^<number-of-commits-to-squash>입니다.
qwertzguy

이를 통해 다운 스트림 병합 후 모든 것을 단일 커밋으로 스쿼시 할 수있었습니다.
killjoy

18

커스텀 커밋 newFeature으로 브랜치를 병합하십시오 master.

git merge --squash newFeature && git commit -m 'Your custom commit message';

대신에, 당신은

git merge --squash newFeature && git commit

커밋 메시지는 모든 newFeature브랜치 커밋을 포함하며 커스터마이징 할 수 있습니다.

나는 여기에 철저히 설명합니다 : https://youtu.be/FQNAIacelT4


10

나는이 질문이 Github에 관한 것이 아니라는 것을 알고 있지만 Github이 널리 사용되며 이것이 내가 찾던 대답이므로 여기에서 공유 할 것입니다.

Github은 리포지토리에 활성화 된 병합 옵션에 따라 스쿼시 병합을 수행 할 수 있습니다.

스쿼시 병합이 활성화 된 경우 "스쿼시 및 병합"옵션이 "병합"버튼 아래 드롭 다운에 나타납니다.

"스쿼시 및 병합"Github 기능의 스크린 샷


GitHub는 계정과 관련된 기본 이메일을 사용합니다. 여러 개의 전자 메일 주소가 있고 보조 전자 메일 주소를 사용해야하는 경우 GH UI를 사용할 수 없습니다.
루카 구이 디

4

여러 커밋으로 feature / task1에서 작업했다고 가정합니다.

  1. 프로젝트 지점으로 이동하십시오 (project / my_project)

    git checkout project/my_project
    
  2. 새로운 브랜치 생성 (feature / task1_bugfix)

    git checkout -b feature/task1_bugfix
    
  3. --squash옵션으로 마지

    git merge --squash feature/task1
    
  4. 단일 커밋 만들기

    git commit -am "add single comments"
    
  5. 당신의 지점을 밀어

    git push --set-upstream origin feature/task1_bugfix
    

1

힘내

새로운 기능 만들기

터미널 / 쉘을 통해 :

git checkout origin/feature/<featurename>
git merge --squash origin/feature/<featurename>

이것은 커밋하지 않으므로 먼저 검토 할 수 있습니다.

그런 다음이 새 브랜치에서 기능을 커미트하고 완료 한 후 이전 브랜치 (개발 한 브랜치)를 삭제 / 무시하십시오.


@Melebius 태그 또는 이전 질문 인 경우 "SourceTree"에 대한 유일한 참조는 문장에 있습니다. 더 이상 존재하지 않습니다.
Jordan Stefanelli

1
@JordanStefanelli SourceTree는 이 답변원본 버전 에서 사용되었습니다 . 수정되었음을 알려 주셔서 감사합니다!
Melebius 2019

1

오류가 발생하면 병합되지 않은 파일이 있으므로 커밋 할 수 없습니다.

git checkout master
git merge --squash bugfix
git add .
git commit -m "Message"

모든 충돌 파일을 수정했습니다.

git add . 

당신은 또한 사용할 수 있습니다

git add [filename]

0

밀기 전에 지역 지점을 스쿼시하려면 :

  1. 체크 아웃되지 않은 경우 문제의 분기를 점검하십시오.

  2. 지키고 싶은 가장 오래된 커밋의 샤를 찾으십시오.

  3. 해당 커밋에서 새 분기 (tmp1)를 생성 / 체크 아웃합니다.

    git checkout -b tmp1 <sha1-of-commit>

  4. 원래 브랜치를 새 스 쿼싱으로 병합하십시오.

    git merge --squash <original branch>

  5. 요약 커밋 메시지와 함께 병합으로 작성된 변경 사항을 커미트하십시오.

    git commit -m <msg>

  6. 스쿼시하려는 원래 지점을 확인하십시오.

    git checkout <branch>

  7. 유지하려는 원래 커밋 sha로 재설정하십시오.

    git reset --soft <sha1>

  8. 새 tmp1 분기를 기반으로이 분기를 리베이스하십시오.

    git rebase tmp1

  9. 그게 다야-이제 모든 것이 잘되면 임시 tmp1 분기를 삭제하십시오.


0

내가 만든 도구를 사용하면이 과정을 쉽게 할 수 있습니다 : git-squash . 예를 들어, 마스터 브랜치에서 브랜치 된 기능 브랜치에서 모든 커밋을 스쿼시하려면 다음과 같이 작성하십시오.

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