모든 자식 커밋을 하나로 스쿼시하는 방법은 무엇입니까?
전체 저장소를 첫 번째 커밋까지 어떻게 스쿼시합니까?
첫 번째 커밋에 리베이스 할 수는 있지만 2 개의 커밋이 남습니다. 첫 번째 커밋 전에 커밋을 참조하는 방법이 있습니까?
아마도 가장 쉬운 방법은 현재 작업 복사본의 상태로 새 저장소를 만드는 것입니다. 모든 커밋 메시지를 유지하려면 먼저 git log > original.log
새 리포지토리에서 초기 커밋 메시지에 대한 커밋 메시지를 편집하고 편집하십시오.
rm -rf .git
git init
git add .
git commit
또는
git log > original.log
# edit original.log as desired
rm -rf .git
git init
git add .
git commit -F original.log
최신 버전의 git에서는을 사용할 수 있습니다 git rebase --root -i
.
첫 번째 커밋을 제외한 각 커밋에 대해로 변경 pick
하십시오 squash
.
최신 정보
별칭을 만들었습니다 git squash-all
.
사용법 예 : git squash-all "a brand new start"
.
[alias]
squash-all = "!f(){ git reset $(git commit-tree HEAD^{tree} -m \"${1:-A new start}\");};f"
주의 사항 : 주석을 제공해야합니다. 그렇지 않으면 기본 커밋 메시지 "A new start"가 사용됩니다.
또는 다음 명령으로 별명을 작성할 수 있습니다.
git config --global alias.squash-all '!f(){ git reset $(git commit-tree HEAD^{tree} -m "${1:-A new start}");};f'
짧막 한 농담
git reset $(git commit-tree HEAD^{tree} -m "A new start")
참고 : 여기 " A new start
"는 예일 뿐이며, 자신의 언어를 자유롭게 사용하십시오.
TL; DR
스쿼시 할 필요가 없으며 git commit-tree
고아 커밋을 만들고 함께 사용하십시오.
설명
통해 단일 커밋을 만들
git commit-tree
무엇입니까
git commit-tree HEAD^{tree} -m "A new start"
:제공된 트리 오브젝트를 기반으로 새 커미트 오브젝트를 작성하고 stdout에서 새 커미트 오브젝트 ID를 생성합니다. -m 또는 -F 옵션이 제공되지 않으면 표준 입력에서 로그 메시지를 읽습니다.
표현식
HEAD^{tree}
은에 해당하는 트리 개체HEAD
, 즉 현재 분기의 끝을 의미합니다. Tree-Objects 및 Commit-Objects를 참조하십시오 .현재 분기를 새로운 커밋으로 재설정
그런 다음
git reset
현재 분기를 새로 만든 커밋 개체로 재설정하십시오.
이런 식으로, 작업 공간의 어떤 것도 건드리지 않으며 리베이스 / 스쿼시가 필요하지 않아서 정말 빠릅니다. 그리고 필요한 시간은 저장소 크기 또는 기록 깊이와 관련이 없습니다.
변형 : 프로젝트 템플릿의 새로운 저장소
이것은 다른 저장소를 템플릿 / 아키 타입 / 시드 / 스켈레톤으로 사용하여 새 프로젝트에서 "초기 커밋"을 생성하는 데 유용합니다. 예를 들면 다음과 같습니다.
cd my-new-project
git init
git fetch --depth=1 -n https://github.com/toolbear/panda.git
git reset --hard $(git commit-tree FETCH_HEAD^{tree} -m "initial commit")
이렇게하면 템플릿 저장소를 원격 ( origin
또는 기타) 으로 추가하지 않아도 되고 템플릿 저장소의 기록이 초기 커밋으로 축소됩니다.
당신이하고 싶은 모든 커밋을 루트 커밋으로 스쿼시하는 것입니다.
git rebase --interactive --root
리베이스 작업은 대화식 리베이스 편집기 커밋 목록을 생성하고 리베이스 자체를 실행하기 위해 매우 느리게 실행되기 때문에 많은 수의 커밋 (예 : 수백 개의 커밋)에는 비실용적입니다.
많은 커밋을 스쿼시 할 때 두 가지 더 빠르고 효율적인 솔루션은 다음과 같습니다.
대체 솔루션 # 1 : 고아 지점
현재 브랜치의 끝 (예 : 가장 최근의 커밋)에서 새 고아 브랜치를 만들 수 있습니다. 이 고아 브랜치는 완전히 새로운 커밋 히스토리 트리의 초기 루트 커밋을 형성하는데, 이는 커밋을 모두 스쿼시하는 것과 실질적으로 같습니다.
git checkout --orphan new-master master
git commit -m "Enter commit message for your new initial commit"
# Overwrite the old master branch reference with the new one
git branch -M new-master master
선적 서류 비치:
대체 솔루션 # 2 : 소프트 리셋
또 다른 효율적인 솔루션은 단순히 루트 커밋에 혼합 또는 소프트 재설정을 사용하는 것입니다 <root>
.
git branch beforeReset
git reset --soft <root>
git commit --amend
# Verify that the new amended root is no different
# from the previous branch state
git diff beforeReset
선적 서류 비치:
echo "message" | git commit-tree HEAD^{tree}
HEAD 트리를 사용하여 고아 커밋을 만들고 stdout에 이름 (SHA-1)을 출력합니다. 그런 다음 지점을 재설정하십시오.
git reset SHA-1
다른 사람을 위해 작동하는 경우를 대비하여 내가 이렇게 한 방법은 다음과 같습니다.
이와 같은 일을 할 때는 항상 위험이 있으며 시작하기 전에 저장 브랜치를 만드는 것은 결코 나쁜 생각이 아닙니다.
로깅으로 시작
git log --oneline
첫 번째 커밋으로 스크롤하고 SHA를 복사하십시오.
git reset --soft <#sha#>
<#sha#>
로그에서 복사 한 SHA로 교체
git status
모든 것이 녹색인지 확인하고 그렇지 않으면 실행 git add -A
git commit --amend
모든 현재 변경 사항을 현재 첫 커밋으로 수정
이제이 분기를 강제로 밀면 거기에있는 내용을 덮어 씁니다.
가장 쉬운 방법은 'plumbing'명령 update-ref
을 사용하여 현재 분기를 삭제하는 것입니다.
git branch -D
현재 분기 삭제를 중지하는 안전 밸브가 있으므로 사용할 수 없습니다 .
그러면 새로운 초기 커밋으로 시작할 수있는 '초기 커밋'상태로 돌아갑니다.
git update-ref -d refs/heads/master
git commit -m "New initial commit"
이식편 사용에 대한 내용을 읽었지만 많이 조사하지는 않았습니다.
어쨌든, 마지막 2 개의 커밋을 수동으로 다음과 같이 스쿼시 할 수 있습니다.
git reset HEAD~1
git add -A
git commit --amend
먼저을 사용하여 모든 커밋을 단일 커밋으로 스쿼시하십시오 git rebase --interactive
. 이제 스쿼시를위한 두 가지 커밋이 남았습니다. 그렇게하려면
한 줄에 6 단어
git checkout --orphan new_root_branch && git commit
이식편을 사용하여 스쿼시하려면
파일을 추가하고 .git/info/grafts
루트가되고 싶은 커밋 해시를 넣으십시오.
git log
이제 그 커밋에서 시작합니다
'실제'실행되도록 git filter-branch
백업을 만들
git branch backup
지정된 커밋으로 재설정
git reset --soft <#root>
그런 다음 모든 파일을 준비에 추가
git add .
메시지를 업데이트하지 않고 커밋
git commit --amend --no-edit
뭉친 커밋으로 새 지사를 밀다
git push -f
이 답변 작성 외에 하나 (노 부모가 더-역사), 커밋 없다고 가정, (그들을 투표하십시오) 위의 몇 향상 또한 그의 커밋 커밋 모든 데이터를 유지하려면 없습니다 :
- 저자 (이름 및 이메일)
- 작성일
- 커미터 (이름과 이메일)
- 확정 된 날짜
- 커밋 로그 메시지
물론 새로운 / 단일 커밋의 commit-SHA는 새로운 (비) 역사를 나타내며 부모가없는 / 루트 커밋이되기 때문에 변경 될 것입니다.
에 git log
대한 일부 변수를 읽고 설정하면 git commit-tree
됩니다. 위의 commit-data를 유지하면서 master
새 브랜치에서 단일 commit을 작성한다고 가정하십시오 one-commit
.
git checkout -b one-commit master ## create new branch to reset
git reset --hard \
$(eval "$(git log master -n1 --format='\
COMMIT_MESSAGE="%B" \
GIT_AUTHOR_NAME="%an" \
GIT_AUTHOR_EMAIL="%ae" \
GIT_AUTHOR_DATE="%ad" \
GIT_COMMITTER_NAME="%cn" \
GIT_COMMITTER_EMAIL="%ce" \
GIT_COMMITTER_DATE="%cd"')" 'git commit-tree master^{tree} <<COMMITMESSAGE
$COMMIT_MESSAGE
COMMITMESSAGE
')
나는 보통 다음과 같이합니다 :
모든 것이 커밋되었는지 확인하고 문제가 발생할 경우 최신 커밋 ID를 기록하거나 백업으로 별도의 분기를 만듭니다.
git reset --soft `git rev-list --max-parents=0 --abbrev-commit HEAD`
머리를 첫 커밋으로 재설정하기 위해 실행 하지만 인덱스는 변경하지 마십시오. 첫 번째 커밋 이후의 모든 변경 사항은 커밋 준비가되었습니다.실행
git commit --amend -m "initial commit"
하여 커밋을 수정하는 최초의 커밋과 메시지를 저지하거나 기존의 커밋 메시지를 유지하려는 경우, 당신은 실행할 수 변경git commit --amend --no-edit
git push -f
변경 사항을 강제로 실행
참고 URL : https://stackoverflow.com/questions/1657017/how-to-squash-all-git-commits-into-one
'development' 카테고리의 다른 글
Apache2 : 'AH01630 : 클라이언트가 서버 구성에 의해 거부되었습니다' (0) | 2020.02.20 |
---|---|
자바 스크립트에서 float 형식을 지정하는 방법은 무엇입니까? (0) | 2020.02.20 |
ASP.Net MVC modelState에서 모든 오류를 얻는 방법? (0) | 2020.02.19 |
Android에서 화면 너비 및 높이 가져 오기 (0) | 2020.02.19 |
파일 끝에 줄 바꿈이 없습니다. (0) | 2020.02.19 |