git format-patch를 사용하여 커밋을 하나의 패치로 어떻게 스쿼시합니까?


163

나는 아직 깨달 지 않은 일부 사람들에게 이메일로 보내고 싶은 지점에 8 가지 커밋을 가지고 있습니다. 지금까지 내가하는 모든 일은 나에게 8 개의 패치 파일을 제공하거나 처음부터 브랜치 히스토리의 모든 커밋에 대해 패치 파일을 제공하기 시작합니다. 커밋을 스쿼시하기 위해 git rebase --interactive를 사용했지만 지금 시도하는 모든 것은 처음부터 수십억 개의 패치를 제공합니다. 내가 뭘 잘못하고 있죠?

git format-patch master HEAD # yields zillions of patches, even though there's 
                             # only one commit since master

아래 제안 중에서 어떤 방법을 사용하게 될지 궁금합니다. 알려주십시오;)
VonC

4
Rob Di Marco가 제안한대로 git diff를 사용합니다. 하지만 어제 밤에 두 번째 딸의 탄생을 목격한지 2 주 동안 일을하지 않아서 사용하기 전에 시간이 좀 걸릴 것입니다! :)
skiphoppy

2
git format-patch --squash master HEAD
schoetbi

1
master..HEAD를 사용하여 회전 범위를 지정하십시오.
Konrad Kleine

답변:


186

다음과 같이 버리기 지점 에서이 작업을 수행하는 것이 좋습니다. 커밋이 "newlines"브랜치에 있고 "master"브랜치로 이미 다시 전환 한 경우 트릭을 수행해야합니다.

[adam@mbp2600 example (master)]$ git checkout -b tmpsquash
Switched to a new branch "tmpsquash"

[adam@mbp2600 example (tmpsquash)]$ git merge --squash newlines
Updating 4d2de39..b6768b2
Fast forward
Squash commit -- not updating HEAD
 test.txt |    2 ++
 1 files changed, 2 insertions(+), 0 deletions(-)

[adam@mbp2600 example (tmpsquash)]$ git commit -a -m "My squashed commits"
[tmpsquash]: created 75b0a89: "My squashed commits"
 1 files changed, 2 insertions(+), 0 deletions(-)

[adam@mbp2600 example (tmpsquash)]$ git format-patch master
0001-My-squashed-commits.patch

도움이 되었기를 바랍니다!


2
패치를 편집해야 할 경우 히스토리를 로컬로 유지하려고 할 때 사용합니다. 그렇지 않으면 rebase -i를 사용하고 커밋을 스쿼시합니다.
sebnow

5
나를 위해, 그것은 더 안정적으로 작동 git comit -m "My squashed commits"하지 않으면 다른 추적되지 않은 파일을 추가합니다
Sebastian

또한 마스터 대신 특정 커밋으로 전환하여 커밋에서 커밋으로 패치를 만들 수 있습니다.git checkout 775ec2a && git checkout -b patch && git merge --squash branchname
Berry M.

131

냄비에 하나 이상의 솔루션을 추가하기 만하면됩니다. 대신 이것을 사용하는 경우 :

git format-patch master --stdout > my_new_patch.diff

그러면 여전히 8 패치가 될 것입니다 ...하지만 모두 단일 패치 파일에 있으며 다음과 같이 적용됩니다.

git am < my_new_patch.diff

13
나는이 해결책을 좋아한다. @Adam Alexander가 기술 한 방법보다 때때로 더 큰 패치를 생성 할 수 있습니다. 커밋을 통해 일부 파일을 두 번 이상 편집 할 수 있기 때문입니다. 이 메소드는 일부 파일이 복귀 된 경우에도 각 커밋을 개별적으로 처리합니다. 그러나 대부분의 경우 이것은 문제가되지 않습니다.
gumik

1
이 옵션은 병합을 피하려고 할 때 유용합니다! (예를 들어 커밋을 건너 뛰고 싶습니다). 당신은 여전히 git rebase -i ...하나를 모두 스쿼시 할 수 있습니다 .
Jorge Orpinel

21

나는 항상 당신의 예제에서 git diff를 사용합니다.

git diff master > patch.txt

15
커밋 메시지와 메타 데이터를 모두 잃는 것을 제외하고. git format-patch의 장점은 패치 세트에서 전체 브랜치를 재구성 할 수 있다는 것입니다.
mcepl

스쿼시 분기를 만들 앤 방법은 모든 하나에 커밋 메시지를 결합하는 장점이 있지만,이 방법은 훨씬 더 빨리 자신의 커밋 메시지를 작성하려는 경우입니다
woojoo666

실제로, 결합 된 메시지를 사용하여 수행 할 수 있습니다 git log, 참조 내 대답 에 대한 예
woojoo666을

2
좋은 옵션이지만 'git diff'에는 이진 차이를 포함 할 수 없다는 것을 고려하십시오 (어쩌면 옵션이있을 수 있음).
산티아고 빌라 푸에르

18

변경 사항이 마스터 브랜치에있는 경우 Adam Alexander 답변이 수정되었습니다. 이것은 다음을 수행합니다.

  • 우리가 원하는 지점에서 새 런 어웨이 분기 "tmpsquash"를 생성합니다 ( "git --log"를 실행하거나 gitg를 사용하는 SHA 키를 찾으십시오. tmpsquash 헤드가 될 커밋을 선택하십시오. 커밋은 마스터에서 수행됩니다. 숙청 된 커밋).
  • master에서 tmpsquash로 변경 사항을 병합합니다.
  • 취소 된 변경 사항을 tmpsquash에 적용합니다.
  • 취소 된 커밋으로 패치를 만듭니다.
  • 마스터 지점으로 돌아갑니다

laura@rune:~/example (master)$ git branch tmpsquash ba3c498878054e25afc5e22e207d62eb40ff1f38
laura@rune:~/example (master)$ git checkout tmpsquash
Switched to branch 'tmpsquash'
laura@rune:~/example (tmpsquash)$ git merge --squash master
Updating ba3c498..40386b8
Fast-forward
Squash commit -- not updating HEAD

[snip, changed files]

11 files changed, 212 insertions(+), 59 deletions(-)
laura@rune:~/example  (tmpsquash)$ git commit -a -m "My squashed commits"
[test2 6127e5c] My squashed commits
11 files changed, 212 insertions(+), 59 deletions(-)
laura@rune:~/example  (tmpsquash)$ git format-patch master
0001-My-squashed-commits.patch
laura@rune:~/example  (tmpsquash)$ git checkout master
Switched to branch 'master'
laura@rune:~/example  (master)$

원격으로 변경하지 않으면 마스터에서 변경하는 것은 반 패턴입니다. 그리고 원한다면 패치 파일을 생성하지 않아도됩니다.
ivan_pozdeev

18

아시다시피 a git format-patch -8 HEAD는 8 개의 패치를 제공합니다.

8 개의 커밋이 하나로 나타나기를 원하고 분기 기록 ( o-o-X-A-B-C-D-E-F-G-H)을 다시 쓰지 않으려면 다음을 수행하십시오 .

git rebase -i
// squash A, B, C, D, E ,F, G into H

또는 더 나은 솔루션이 될 수 있습니다 . 새 분기에서 8 개의 커밋 (8 개의 커밋 전에 커밋)을 모두 재생하십시오.X

git branch delivery X
git checkout delivery
git merge --squash master
git format-patch HEAD

이렇게하면 "배달"분기에 단 하나의 커밋이 있으며 마지막 8 개의 커밋을 모두 나타냅니다.


git merge master단지 빨리 감기를 수행하고 커밋을 스쿼시하지 않습니다. git merge --squash master스테이지 영역에서 모든 커밋이 찌그러지고 보이도록 변경합니다 . 귀하의 흐름은이 변경으로 작동합니다. (git 버전 2.1.0을 사용하고 있습니다.)
Stunner

5

두 태그 사이의 형식 패치 :

git checkout <source-tag>
git checkout -b <tmpsquash>
git merge --squash <target-tag>
git commit -a -m "<message>"
git format-patch <source-tag>

5

가장 쉬운 방법은을 사용 하고 스쿼시 메소드가 출력하는 결합 된 커밋 메시지를 원하는 경우 git diff추가 git log하는 것입니다. 예를 들어, commit abcd1234: 사이에 패치를 작성하려면

git diff abcd..1234 > patch.diff
git log abcd..1234 > patchmsg.txt

그런 다음 패치를 적용 할 때 :

git apply patch.diff
git add -A
git reset patch.diff patchmsg.txt
git commit -F patchmsg.txt

텍스트 파일이 아닌 파일 (예 : 이미지 또는 비디오)을 다룰 때 의 --binary주장을 잊지 마십시오 git diff.


0

Adam Alexander의 답변을 바탕으로 :

git checkout newlines
## must be rebased to master
git checkout -b temporary
# squash the commits
git rebase -i master
git format-patch master
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.