정확합니다. 불행히도 Git에는 "옳은 길"을 구현하기위한 어떤 것도 내장되어 있지 않습니다. 을 염두에두고 특정 시점에이를 수행하는 프로그램을 작성하기는했지만 은을 "올바르게"정의하는 것이 다소 어렵습니다. 이상한 모든 경우에 너무 어려워서 버렸습니다.
여기에 근본적인 문제가 git cherry-pick
경우와 같은 복사 커밋에 의해 git rebase
작품 (대화 형 REBASE와 당신이 길을 따라 몇 가지 추가 변경시키는) 것입니다. 새 사본에는 새롭고 다른 해시 ID가 있습니다. 복사본이 만들어지면 브랜치 이름 현재 브랜치 (그 중 마지막 복사 된 커밋까지 시작한 항목)를 다시 가리 킵니다. 점에서
0c8487b - foo
5ce596d - (stage0) go to stage 0
3ca2d7d - do something
- ...
505421e - (HEAD -> stage4) go to stage 4
: 즉
,이 경우, 당신은 망할 놈의 복사본이 주문 (가장 초기부터 최신까지) 한 번에 하나씩. 첫 번째 단계에서 일부를으로 변경하십시오. 변경 사항이있는 경우 새로운 내용이 새로운 해시 ID (예 : cccccc1
)를 얻게되므로 실제로 변경 사항이 없으면 실제로 무엇이든 상관 없습니다. 우리는 이것을 "새로운 커밋 1"이라고 부른다.) 이 새로운 커밋의 부모 커밋은 bar
이라고 표시된 커밋 인 ccfb7c9
이므로 새 기록은 해당 시점의 이전 기록에 다시 포함됩니다.
그러면 Git은 두 번째 커밋 인 5ce596d - (stage0) go to stage 0
을 복사합니다.이 커밋은 cccccc2
이됩니다. cccccc2
의 부모는 cccccc1
이며, 이것은 다른 커밋이되도록 강제로 5ce596d
과 완전히 다릅니다. 자식은 계속해서 8 개의 모든 커밋을 복사하고 마지막 커밋은 cccccc8
이된다. Git은 stage4
이라는 이름을 변경하여 이름이 cccccc8
이되도록합니다.
따라서 Git이 발견 한 커밋 (예 : stage4
)에서 시작하여 내역을 보면 새 메시지 번호이 표시됩니다. 그러나 Git은 다른 이름을 변경하지 않았습니다. 예를 들어, stage3
은 여전히 커밋을 확인합니다. 307978f
stage0
은 커밋을 확인하고 여전히 커밋을 확인합니다. 5ce596d
.따라서 의 이름에서 시작하여 해당 기록을 보면이라는 이름을 사용하면 원래 일련의 커밋을 볼 수 있습니다.
필요한 것은 각 라벨을 원래 해시에서 새로운 해시로 이동시키는 것입니다. 문제는이 모든 것을 식별하는 데서 오는 것입니다 : 어떤 레이블 은이되어야합니까? (일부는 이전의 커밋을 의도적으로 유지하고 일부는 이전하는 것이 바람직 할 수 있습니다.) 어떤 커밋이 올바른 커밋입니까? 대화 형 리베이스 중에 커밋을 분할하고 다른 것을 결합하는 경우 어떻게해야합니까?
간단하고 강력한 솔루션은 변경하려는 이름을 수동으로 강제 실행하여 새 커밋을 가리키는 것입니다.
git branch -f stage0 newhash0
git branch -f stage1 newhash1
git branch -f stage2 newhash2
git branch -f stage3 newhash3
을하면됩니다 : git log --all --decorate --oneline --graph
를 실행하고 각각의 이름에 대한 이전 및 커밋 새로운 ID를 기록해, 다음 실행합니다. 또는 자동으로 이동하는 stage4
에서 시작하여 거꾸로 작업하여 커밋을 찾을 수 있기 때문에 분기 이름 중 일부만 완전히 삭제하십시오. 이름은 그냥 "커밋 원시 포인터"보다 더 많은 의미를 가질 수 있도록
1 내가 좋아하는 정의는 구조화 지점 이름을 포함한다. 이 구조화의 양식도 어렵습니다. 이름 계층 구조를 사용해야합니까? 아니면 분기 이름을 "슈퍼 브랜치"로 그룹화하는 git config
항목이 있어야합니까?
일부 git rebase
명령은 문자 그대로 git cherry-pick
으로 실행되고 일부는 실행하지 않습니다. 대화 형 리베이스는 실제로 git cherry-pick
과 git commit --amend
및 기타 까다로운 항목과 함께 실행되는 경우 중 하나입니다.
3 임의 힘내 오브젝트의 해시 ID 엄격 내용에 의해 결정된다 "복사"-가 동일한 동일한 해시 ID, 즉으로 바람 비트의 원래 비트에 100 % 동일한 경우 이렇게 , 당신은 단순히 원본을 다시 사용합니다. 그러나 모든 변경 작업을 수행하자마자 순서에있는 일부 커밋의 해시 ID가 변경되므로 "다운 스트림"(자식) 커밋마다 다른 부모 해시 ID가 있어야하며 이는 다운 스트림 커밋도 변경됩니다.
https://stackoverflow.com/a/45844847/6309는 유망 해 보입니다. – VonC
일반적으로 구조를 유지하는 것은 불가능합니다. 예를 들어, 3ca2를 5ce5로 채우면 어떨까요? 그 다음에'stage0' 포인트가 있어야합니까? –
@DavisHerring : 논리적으로 올바른 대답은'git filter-branch'와 같은 방식으로 처리하는 것입니다 : old => 새로운 커밋 해시 맵을 만들고지도 항목을 기반으로 레이블을 바꿉니다. 두 개의 커밋을 수행하면 이전 커밋과 두 개의 커밋 모두 새로운 커밋으로 매핑됩니다. 커밋을 분할하면 이전 커밋이 새로운 커밋 중 첫 번째 커밋에 매핑됩니다. 기존 리베이스 코드는 이러한 맵을 만드는 데 도움이되지 않습니다. – torek