Git 저장소의 처음 두 커밋을 결합 하시겠습니까?


197

세 개의 커밋 A, BC를 포함하는 히스토리가 있다고 가정하십시오 .

A-B-C

두 커밋 AB 를 하나의 커밋 AB 에 결합하고 싶습니다 .

AB-C

나는 시도했다

git rebase -i A

다음 내용으로 편집기가 열립니다.

pick e97a17b B
pick asd314f C

나는 이것을 다음으로 바꾼다.

squash e97a17b B
pick asd314f C

그런 다음 Git 1.6.0.4는 다음과 같이 말합니다.

Cannot 'squash' without a previous commit

방법이 있습니까 아니면 불가능한가요?



답변:


168

사용 git rebase -i --root 망할 놈의 같은 버전 1.7.12 .

대화식 리베이스 파일에서 커밋 B 의 두 번째 줄 을 스쿼시로 변경 하고 다른 줄은 pick으로 둡니다 .

pick f4202da A
squash bea708e B
pick a8c6abc C

이것은 두 커밋 AB 를 하나의 커밋 AB에 결합합니다. .

이 답변 에서 발견되었습니다 .


126

당신은 시도:

git rebase -i A

다음과 같이 계속 edit하지 않으면 다음과 같이 시작할 수 있습니다 squash.

edit e97a17b B
pick asd314f C

그런 다음 실행

git reset --soft HEAD^
git commit --amend
git rebase --continue

끝난.


4
github gist를 자동으로 수정하기 위해이 작업을 수행하는 경우 커밋에 -m "initial"을 추가해야합니다. ;-)
Bruno Bronosky

1
git rebase --abort다시 시작하고 올바른 방법으로 (편집기의 첫 커밋을 스쿼시하지 않음)
oma

66

A초기 커밋 이었지만 이제는 초기 커밋이되고 싶습니다 B. git commit은 전체 트리이며, 일반적으로 그들이 소개하는 diff로 설명되고 보더라도 diff가 아닙니다.

이 레시피는 A와 B, B와 C 사이에 여러 커밋이있는 경우에도 작동합니다.

# Go back to the last commit that we want
# to form the initial commit (detach HEAD)
git checkout <sha1_for_B>

# reset the branch pointer to the initial commit,
# but leaving the index and working tree intact.
git reset --soft <sha1_for_A>

# amend the initial tree using the tree from 'B'
git commit --amend

# temporarily tag this new initial commit
# (or you could remember the new commit sha1 manually)
git tag tmp

# go back to the original branch (assume master for this example)
git checkout master

# Replay all the commits after B onto the new initial commit
git rebase --onto tmp <sha1_for_B>

# remove the temporary tag
git tag -d tmp

1
이 작업을 수행하면 대규모 대화식 리베이스가 시작됩니다.git rebase --onto tmp <sha1_for_B>
Alex

두 개의 커밋 (하나로 롤링하고 싶음)이있는 새로운 리포지토리를 고려할 때 이것은 완벽하게 작동했습니다. 감사합니다 @CB Bailey
RominRonin

10

대화식 리베이스의 경우 목록이 다음이되도록 A 전에 수행해야합니다.

pick A
pick B
pick C

될 :

pick A
squash B
pick C

A가 초기 커밋 인 경우 A 이전에 다른 초기 커밋을 가져와야합니다. 따라서 스쿼시는 귀하의 모범에서 작동하지 않습니다.


9

kostmo의 대답 을 사용하여 수백 또는 수천 개의 커밋이있는 경우

git rebase -i --root

rebase 스크립트가 두 번 처리 해야하는 커밋이 많기 때문에 실용적이지 않고 느릴 수 있습니다.대화식 rebase 편집기 목록 (각 커밋에 대해 수행 할 작업을 선택하는 위치)을 생성하기 위해 한 , . 커밋을 다시 적용하십시오.

여기 에 대화식 rebase를 사용하지 않음으로써 대화식 rebase 편집기 목록을 생성하는 데 드는 시간 비용을 피할 수 있는 대체 솔루션 이 있습니다. 이런 방식으로 Charles Bailey의 솔루션 과 유사합니다 . 당신은 단순히 만들 고아 지점 두 번째 커밋에서 한 다음 그 위에 모든 자손 커밋을 리베이스 :

git checkout --orphan orphan <second-commit-sha>
git commit -m "Enter a commit message for the new root commit"
git rebase --onto orphan <second-commit-sha> master

선적 서류 비치



0

분대를위한 힘내 명령 : git rebase -i HEAD ~ [커밋 수]

git commit history 아래에 있다고 가정 해 봅시다.


pick 5152061 feat : 이미지 저장 지원 추가. (A)
39c5a04 수정 : 버그 수정을 선택하십시오. (비)
선택 839c6b3 수정 : 충돌이 해결되었습니다. (씨)

이제 A와 B를 AB로 스쿼시하고 다음 단계를 수행하십시오.


pick 5152061 feat : 이미지 저장 지원 추가. (A)
39c5a04 수정 : 버그 수정. (B)
선택 839c6b3 수정 : 충돌이 해결되었습니다. (씨)

참고 : 스쿼시 커밋에는 squash 또는 s를 사용할 수 있습니다. 최종 결과는 다음과 같습니다.
pick 5152061 feat : 이미지 저장 지원 추가. (AB)
pick 839c6b3 수정 : 충돌이 해결되었습니다. (씨)


-1

약간의 명령 줄 마술을 수행해야합니다.

git checkout -b a A
git checkout B <files>
git commit --amend
git checkout master
git rebase a

커밋으로 AB와 C가있는 브랜치를 남겨 두어야합니다.


이전 및 새로운 초기 커밋에는 공통 조상이 없으므로 git은 공통 트리가 있지만 마스터의 전체 기록을 a에 적용하려고 할 때 불필요한 충돌이 발생할 수 있습니다. --onto 옵션을 사용하여 git rebase를 사용하면 git에게 올바른 위치를 지정하여 적용을 시작할 수 있습니다.
CB Bailey
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.