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.