다른 지점의 모든 변경 사항을 단일 커밋으로 병합 (스쿼시 포함)


479

Git에는 한 지점에서 다른 지점으로 모든 변경 사항을 병합하지만 동시에 단일 커밋으로 스쿼시하는 방법이 있습니까?

나는 종종 별도의 브랜치에서 새로운 기능을 수행하며 정기적으로 커밋 / 푸시합니다-주로 백업 또는 내가 작업중 인 것을 다른 머신으로 전송합니다. 대부분의 커밋은 "Feature xxx WIP"또는 무엇인가 중복이라고 말합니다.

해당 작업이 완료되고 WIP 분기를 다시 마스터로 병합하려면 모든 중간 커밋을 삭제하고 하나의 클린 커밋을 삭제하고 싶습니다.

이 작업을 수행하는 쉬운 방법이 있습니까?

또는 분기가 시작된 시점부터 분기에 대한 모든 커밋을 축소하는 명령은 어떻습니까?

답변:


601

다른 옵션은 git merge --squash <feature branch>마지막으로을 수행하는 것 git commit입니다.

에서 힘내 병합

--squash

--no-squash

진짜 병합 (병합 정보 제외) 일어난 것처럼 작업 트리와 인덱스 상태를 생산하지만, 실제로 커밋 만들거나 이동하지 HEAD않으며, 기록은 $GIT_DIR/MERGE_HEAD다음 원인이 git commit명령은 머지 커밋을 만들 수 있습니다. 이를 통해 현재 분기 위에 단일 커밋을 만들 수 있으며 그 효과는 다른 분기를 병합하는 것과 동일합니다 (또는 문어의 경우 더 많음).


1
멋진 기능! 나는 자식을 좋아한다. 앞으로 확실히 이것을 사용할 것이지만 rebase -i와 관련하여 귀하의 길을 아는 것이 좋습니다. 하나 이상의 커밋을 실제로 만들고 싶을 경우를 대비하여 좋은 기술입니다.
Will Buck

4
주의 사항 : 이것은 작동하지만 기본 커밋 메시지에는 병합중인 분기의 로그가 포함됩니다. 문제는 일반적으로 표시된 전체 텍스트가 실제로 커밋 메시지의 일부가 아닌 형식과 비슷해 보이지만이 경우에는 그렇지 않습니다. 따라서 모든 것을 원하지 않으면 커밋 메시지에서 모든 것을 수동으로 제거해야합니다. 이것을 사용하기 전에 이것을 테스트
했어야했는데

23
즉, 분기가 병합 된 것으로 표시되지 않습니다. stackoverflow.com/questions/19308790/…
Ryan

3
IMHO 이것이 호출되어야합니다rebase --squash
앤디

(실제로 기능 분기를 병합하지 않기 때문에) 이것은 커밋 후 기능 분기를 삭제하려는 경우 적합합니다. 그 맞습니까? (나는 git 전문가가 아니다)
Andrew Spencer

214

그것을 발견! 병합 명령에는 --squash옵션이 있습니다

git checkout master
git merge --squash WIP

이 시점에서 모든 것이 병합되고 충돌 할 수 있지만 커밋되지는 않습니다. 그래서 지금 할 수 있습니다 :

git add .
git commit -m "Merged WIP"

2
무엇을 git add .합니까?
Michael Potter

1
@MichaelPotter 그것은 모든 파일과 변경 사항을 추가합니다
Daksh Shah

2
git add .무시되지 않은 모든 파일을 현재 디렉토리에 추가하면 의도하지 않은 파일을이 방법으로 선택하는 것에주의해야합니다.
Jake Cobb

7
다른 방법으로 트리에 이미 추가 된 파일 만 추가 git add .할 수 있습니다 git add -u.
Brandon Ogle

19
"git add."제안 또한 혼란 스럽습니다. "git merge --squash WIP"를 수행하면 이미 인덱스가 변경되었습니다. 필요한 것은 그것들을 커밋하는 것입니다. "git add."하기 작업 디렉토리에 발생하지만 기능 분기의 일부가 아닌 변경 사항을 추가합니다. 문제는 기능 브랜치의 변경 사항을 하나의 커밋으로 커밋하는 방법이었습니다.
John Pankowicz

30

git rebase -i master기능 지점에서 시도하십시오 . 그런 다음 커밋을 결합하기 위해 하나의 'pick'을 제외하고 모두 'squash'로 변경할 수 있습니다. 리베이스로 스쿼시 커밋 보기

마지막으로 마스터 브랜치에서 병합을 수행 할 수 있습니다.


8
예, 작동하지만 번거로운 대화 형 rebase를 원하지 않습니다. 지점이 평평해진 이후로 모든 것을 원합니다.
브래드 로빈슨

2
+1 이것은 깨끗한 역사를 만듭니다. 커밋을 개별 패치, 카드, 스토리 등으로 식별하고 관리하는 것이 훨씬 쉽습니다.
Ryan

2

수락 된 답변git merge --squash <feature branch> 으로 사용 하면 트릭이 제안되지만 병합 된 분기는 실제로 병합 된 것으로 표시되지 않습니다.

따라서 더 나은 해결책은 다음과 같습니다.

  • 최신 마스터에서 새 브랜치를 만듭니다
  • <feature branch>사용하여 위의 병합git merge --squash
  • 새로 만든 브랜치를 마스터로 병합

이 위키 는 절차를 자세히 설명합니다.


0

정확히 이것을하기 위해 내 자신의 자식 별칭을 만들었습니다. 나는 그것을 부르고있다 git freebase! 기존의 지저분하고 복구 할 수없는 기능 분기를 가져 와서 다시 작성하여 커밋이 하나의 커밋으로 스 쿼치되고 지정한 분기 (기본적으로 마스터)에 기반한 동일한 이름의 새 분기가됩니다. 마지막에는 새로 "무료 기반"브랜치에 원하는 커밋 메시지를 사용할 수 있습니다.

.gitconfig에 다음 별명을 배치하여 설치하십시오.

[alias]
  freebase = "!f() { \
    TOPIC="$(git branch | grep '\\*' | cut -d ' ' -f2)"; \
    NEWBASE="${1:-master}"; \
    PREVSHA1="$(git rev-parse HEAD)"; \
    echo "Freebaseing $TOPIC onto $NEWBASE, previous sha1 was $PREVSHA1"; \
    echo "---"; \
    git reset --hard "$NEWBASE"; \
    git merge --squash "$PREVSHA1"; \
    git commit; \
  }; f"

다음을 실행하여 기능 분기에서 사용하십시오. git freebase <new-base>

나는 이것을 몇 번만 테스트 했으므로 먼저 읽고 그것을 실행하고 있는지 확인하십시오. 작은 안전 조치로 시작 sha1을 인쇄하므로 문제가 발생하면 이전 분기를 복원 할 수 있어야합니다.

github의 내 도트 파일 저장소에서 유지 관리합니다 : https://github.com/stevecrozz/dotfiles/blob/master/.gitconfig



-1

git merge --squash <feature branch> "git commit"은 모든 기능 브랜치 커밋 메시지를 유지하도록 선택합니다.

커밋 병합을 줄입니다.

git merge x 번 --git reset HEAD ^ --soft git commit.

위험 요소가 삭제 된 파일이 다시 나타날 수 있습니다.


-5

"rebase"명령으로이를 수행 할 수 있습니다. 브랜치를 "main"과 "feature"라고하자 :

git checkout feature
git rebase main

rebase 명령은 "feature"에 대한 모든 커밋을 "main"과 같은 부모를 가진 하나의 커밋으로 재생합니다.

"feature"가 생성 된 이후 (또는 가장 최근의 병합 이후) "main"이 변경된 경우 git merge main이전 에 실행할 수 있습니다 git rebase main. 이렇게하면 병합 충돌이 발생한 경우에도 전체 기록이 유지됩니다.

리베이스 후에 브랜치를 main으로 병합하면 빨리 병합됩니다.

git checkout main
git merge feature

좋은 개요는 개념적 으로 Git 이해rebase 페이지를 참조하십시오.


이것은 나를 위해 작동하지 않았습니다. 방금 WIP 분기를 사용하여 간단한 테스트 저장소를 만들고 위를 시도하고 병합 충돌이 발생했습니다 (마스터에서 변경하지 않은 경우에도).
브래드 로빈슨

기능이 main (git checkout -b feature main)에서 생성되었고 main과 최근에 병합 된 경우 rebase와 충돌하지 않아야합니다.
NamshubWriter

알았어, 다시 해봐 이번에는 갈등이 없었지만 역사는 찌그러지지 않았습니다.
브래드 로빈슨

git-merge 문서를 다시 살펴보면 커밋 중 일부가 유지됩니다. "main"에서 "feature"로 이전 병합을 수행 한 경우 rebase는 일부를 제거하지만 전부는 아닙니다.
NamshubWriter

기능 분기가 이전에 게시 된 경우 리베이스 작업이 매우 위험 할 수 있습니다. 이 SO 질문에 대한 추가 정보 .
Robert Rossmann
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.