전체 저장소를 첫 번째 커밋까지 어떻게 스쿼시합니까?
첫 번째 커밋에 리베이스 할 수는 있지만 2 개의 커밋이 남습니다. 첫 번째 커밋 전에 커밋을 참조하는 방법이 있습니까?
--root
은 아닙니다 ( 실제로 스쿼시에 많은 커밋이있는 경우 모든 커밋 을 스쿼시하는 가장 좋은 솔루션은 아닙니다 ) : Git 저장소의 처음 두 커밋을 결합 하시겠습니까? .
전체 저장소를 첫 번째 커밋까지 어떻게 스쿼시합니까?
첫 번째 커밋에 리베이스 할 수는 있지만 2 개의 커밋이 남습니다. 첫 번째 커밋 전에 커밋을 참조하는 방법이 있습니까?
--root
은 아닙니다 ( 실제로 스쿼시에 많은 커밋이있는 경우 모든 커밋 을 스쿼시하는 가장 좋은 솔루션은 아닙니다 ) : Git 저장소의 처음 두 커밋을 결합 하시겠습니까? .
답변:
아마도 가장 쉬운 방법은 현재 작업 복사본의 상태로 새 저장소를 만드는 것입니다. 모든 커밋 메시지를 유지하려면 먼저 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 rebase -i --root
있습니다. 참조 : stackoverflow.com/a/9254257/109618
현재 자식 1.6.2 , 당신은 사용할 수 있습니다 git rebase --root -i
.
첫 번째 커밋을 제외한 각 커밋에 대해로 변경 pick
하십시오 squash
.
squash
모든 커밋에 사용하지 마십시오 . 첫 번째는이어야 pick
합니다.
별칭을 만들었습니다 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
"는 예일 뿐이며, 자신의 언어를 자유롭게 사용하십시오.
스쿼시 할 필요가 없으며 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 push -f
전파에 사용 합니다.
git clone
. 추가하는 경우 --hard
에 git reset
및 스위치 HEAD
와 FETCH_HEAD
에 git commit-tree
당신은 초기 템플릿의 REPO를 가져 오는 한 후 커밋 만들 수 있습니다. 이것을 보여주는 마지막 부분에서 답을 편집했습니다.
${1?Please enter a message}
당신이하고 싶은 모든 커밋을 루트 커밋으로 스쿼시하는 것입니다.
git rebase --interactive --root
리베이스 작업은 대화식 리베이스 편집기 커밋 목록을 생성하고 리베이스 자체를 실행하기 위해 매우 느리게 실행될 것이기 때문에 많은 수의 커밋 (예 : 수백 개의 커밋)에는 비실용적입니다.
많은 커밋을 스쿼시 할 때보다 빠르고 효율적인 두 가지 솔루션은 다음과 같습니다.
현재 브랜치의 끝 (예 : 가장 최근의 커밋)에서 새 고아 브랜치를 만들 수 있습니다. 이 고아 브랜치는 완전히 새로운 별도의 커밋 히스토리 트리의 초기 루트 커밋을 형성하며, 이는 모든 커밋을 스쿼시하는 것과 실질적으로 같습니다.
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
선적 서류 비치:
또 다른 효율적인 솔루션은 단순히 루트 커밋에 혼합 또는 소프트 재설정을 사용하는 것입니다 <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
선적 서류 비치:
git push origin master --force
.
git push --force
echo "message" | git commit-tree HEAD^{tree}
HEAD 트리를 사용하여 고아 커밋을 만들고 stdout에 이름 (SHA-1)을 출력합니다. 그런 다음 지점을 재설정하십시오.
git reset SHA-1
git reset $(git commit-tree HEAD^{tree} -m "commit message")
더 쉬울 것입니다.
echo "message" | git commit-tree "HEAD^{tree}"
다른 사람을 위해 작동하는 경우를 대비하여 내가 이렇게 한 방법은 다음과 같습니다.
이와 같은 일을 할 때는 항상 위험이 있으며 시작하기 전에 저장 브랜치를 만드는 것은 결코 나쁜 생각이 아닙니다.
로깅으로 시작
git log --oneline
첫 번째 커밋으로 스크롤하고 SHA를 복사하십시오.
git reset --soft <#sha#>
<#sha#>
로그에서 복사 한 SHA로 교체
git status
모든 것이 녹색인지 확인하고 그렇지 않으면 실행 git add -A
git commit --amend
모든 현재 변경 사항을 현재 첫 커밋으로 수정
이제이 분기를 강제로 밀면 거기에있는 내용을 덮어 씁니다.
먼저을 사용하여 모든 커밋을 단일 커밋으로 스쿼시하십시오 git rebase --interactive
. 이제 스쿼시를위한 두 가지 커밋이 남았습니다. 그렇게하려면
git checkout --orphan new_root_branch && git commit
git help checkout
에 대해--orphan
백업을 만들
git branch backup
지정된 커밋으로 재설정
git reset --soft <#root>
그런 다음 모든 파일을 준비에 추가
git add .
메시지를 업데이트하지 않고 커밋
git commit --amend --no-edit
뭉친 커밋으로 새 지사를 밀다
git push -f
<root>
다시 커밋합니다. 커밋 메시지를 편집 할 필요없이 git commit --amend --no-edit
현재 커밋에 대한 모든 변경 사항을 <root>
커밋합니다.
이 답변 작성 외에 하나 (노 부모가 더-역사), 커밋 없다고 가정, (그들을 투표하십시오) 위의 몇 향상 또한 그의 커밋 커밋 모든 데이터를 유지하려면 없습니다 :
물론 새로운 / 단일 커밋의 commit-SHA는 새로운 (비) 역사를 나타내므로 부모없는 / 루트 커밋이되기 때문에 변경됩니다.
에 git log
대한 일부 변수를 읽고 설정하면 git commit-tree
됩니다. 위의 커밋 데이터를 유지하면서 master
새 브랜치에서 단일 커밋을 생성한다고 가정합니다 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
')
이를 위해 로컬 git 리포지토리를 첫 번째 커밋 해시 태그로 재설정 할 수 있으므로 해당 커밋 이후의 모든 변경 사항이 준비되지 않은 다음 --amend 옵션을 사용하여 커밋 할 수 있습니다.
git reset your-first-commit-hashtag
git add .
git commit --amend
그런 다음 필요한 경우 첫 번째 커밋 이름을 편집하고 파일을 저장하십시오.
나를 위해 다음과 같이 일했습니다 : 총 4 개의 커밋이 있었고 대화 형 rebase를 사용했습니다.
git rebase -i HEAD~3
첫 번째 커밋이 남아 있으며 3 개의 최신 커밋을했습니다.
다음에 나타나는 편집기에 갇혀 있으면 다음과 같이 표시됩니다.
pick fda59df commit 1
pick x536897 commit 2
pick c01a668 commit 3
먼저 커밋하고 다른 사람들을 스쿼시해야합니다. 당신이해야 할 것은 :
pick fda59df commit 1
squash x536897 commit 2
squash c01a668 commit 3
이를 위해 INSERT 키를 사용하여 '삽입'및 '편집'모드를 변경하십시오.
편집기를 저장하고 종료하려면을 사용하십시오 :wq
. 커서가 커밋 라인 사이 또는 다른 곳에 있으면 ESC를 누르고 다시 시도하십시오.
결과적으로 두 가지 커밋이 발생했습니다. 첫 번째는 남았고 두 번째는 "이것은 3 개의 커밋의 조합입니다."라는 메시지가 표시됩니다.
자세한 내용은 여기를 참조하십시오 : https://makandracards.com/makandra/527-squash-several-git-commits-into-a-single-commit
나는 보통 다음과 같이합니다 :
모든 것이 커밋되었는지 확인하고 문제가 발생할 경우 최신 커밋 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
변경 사항을 강제로 실행