깃 상위 포인터를 다른 상위 포인터로 설정
만약 제가 과거에 한 부모를 가리키는 약속을 가지고 있지만, 그것이 가리키는 부모를 바꾸고 싶다면, 어떻게 해야 할까요?
를 사용합니다. Git의 일반적인 "take commit(s) and plop it/them on a different parent(base)" 명령어입니다.
그러나 알아야 할 몇 가지 사항:
커밋 SHA에는 부모가 포함되므로 특정 커밋의 부모를 변경하면 해당 SHA도 변경됩니다. 개발 단계에서 커밋 이후에 발생하는 모든 커밋의 SHA도 변경됩니다.
다른 사람들과 함께 작업하고 있는데 문제가 되는 커밋을 이미 공개적으로 그들이 어디로 끌고 갔는지 알려면 커밋을 수정하는 것은 아마도 나쁜 생각일 것입니다™.이는 #1 때문이며, 따라서 귀하의 SHA가 "동일한" 커밋에 대해 더 이상 자신의 SHA와 일치하지 않아 발생한 일을 파악하려고 할 때 다른 사용자의 리포지토리에서 발생하는 혼란이 발생합니다.(자세한 내용은 링크된 관리 페이지의 "RECOVERING FROM UPSTREBASE" 섹션을 참조하십시오.)
즉, 현재 지점에서 새 상위로 이동하려는 몇 가지 커밋이 있는 경우 다음과 같이 나타납니다.
git rebase --onto <new-parent> <old-parent>
그것은 이후에 모든 것을 움직일 것입니다. <old-parent>
위에 앉을 현재 지점에서<new-parent>
대신.
이후 커밋의 기본 재배치를 피해야 하는 경우(예: 기록을 다시 쓰는 것이 불가능하기 때문), Git replace(Git 1.6.5 이상에서 사용 가능)를 사용할 수 있습니다.
# …---o---A---o---o---…
#
# …---o---B---b---b---…
#
# We want to transplant B to be "on top of" A.
# The tree of descendants from B (and A) can be arbitrarily complex.
replace_first_parent() {
old_parent=$(git rev-parse --verify "${1}^1") || return 1
new_parent=$(git rev-parse --verify "${2}^0") || return 2
new_commit=$(
git cat-file commit "$1" |
sed -e '1,/^$/s/^parent '"$old_parent"'$/parent '"$new_parent"'/' |
git hash-object -t commit -w --stdin
) || return 3
git replace "$1" "$new_commit"
}
replace_first_parent B A
# …---o---A---o---o---…
# \
# C---b---b---…
#
# C is the replacement for B.
위의 대체가 설정되면 객체 B에 대한 모든 요청은 객체 C를 실제로 반환합니다.C의 내용은 첫 번째 부모(첫 번째 부모 제외), 같은 트리, 같은 커밋 메시지를 제외하고는 B의 내용과 정확히 동일합니다.
기능은되지만 를 할 수 .--no-replace-objects
git 옵션(명령 이름 앞) 또는 설정을 통해GIT_NO_REPLACE_OBJECTS
환경 변수입니다.푸시를 통해 대체품을 공유할 수 있습니다.refs/replace/*
(일반추가여하에))에 추가)refs/heads/*
) .
커밋 멍이 마음에 들지 않으면(위의 sed에서 수행) 상위 수준 명령을 사용하여 대체 커밋을 만들 수 있습니다.
git checkout B~0
git reset --soft A
git commit -C B
git replace B HEAD
git checkout -
큰 차이점은 B가 병합 커밋인 경우 이 시퀀스가 추가 부모를 전파하지 않는다는 것입니다.
Git에서 커밋을 변경하려면 커밋을 따르는 모든 커밋도 변경해야 합니다.만약 여러분이 역사의 이 부분을 출판했다면, 그리고 누군가가 변화 이전의 역사에 대한 그들의 연구를 구축했을지도 모릅니다.
의 대체 git rebase
앰버의 응답에서 언급된 것은 이식 메커니즘을 사용하는 것입니다(Git Glossary의 Git 이식의 정의 및 문서 참조)..git/info/grafts
Git Repository Layout 문서의 파일)을 사용하여 커밋의 상위 항목을 변경하고 일부 기록 뷰어에서 올바른 작업을 수행했는지 확인합니다.gitk
,git log --graph
등)을 사용한 다음 (맨 페이지의 "예" 섹션에 설명된 대로)를 사용하여 영구적으로 만듭니다(그리고 그라프트를 제거하고 선택적으로 백업된 원래 참조를 제거합니다).git filter-branch
또는 reclone 저장소):
echo "$commit-id $commit-id" >> .git/info/sysgit filter-filter $slot-id..머리
참고!!!이 솔루션은 리베이스 솔루션과는 다릅니다.git rebase
변경 사항을 재배치/이식하는 반면, 이식 기반 솔루션은 이전 상위 항목과 새 상위 항목 간의 차이를 고려하지 않고 단순히 커밋을 그대로 재지정합니다!
위의 답변을 명확하게 하고 뻔뻔스럽게 내 대본을 꽂기 위해:
기본값을 "기본값"으로 할지 "부모"로 할지에 따라 달라집니다.앰버가 제안한 바와 같이 베이스는 디프 주위로 이동합니다.Jakub과 Chris가 제안한 것처럼 부모는 나무 전체의 스냅샷 주위를 이동합니다.만약 당신이 부모를 다시 하고 싶다면, 저는 그 일을 수동으로 하는 것보다 를 사용하는 것을 제안합니다.
비교
왼쪽에 그림이 있고 오른쪽에 그림과 같은 모양을 원한다고 가정합니다.
C'
/
A---B---C A---B---C
기본 재배치와 재양육 모두 동일한 그림을 생성하지만, 정의는C'
다르다.와 함께git rebase --onto A B
,C'
에는 에의 도입변사포않습함다니지에서 소개한 사항이 .B
.와 함께git reparent -p A
,C'
과 .C
외에는)B
기록에 없을 것).
확실히 @Jakub의 대답은 제가 OP와 정확히 같은 것을 시도하던 몇 시간 전에 저에게 도움이 되었습니다.
하만지,git replace --graft
이식에 관한 더 쉬운 해결책입니다.또한 이 솔루션의 주요 문제는 필터 브랜치로 인해 HEAD 브랜치에 통합되지 않은 모든 브랜치가 풀렸다는 것입니다.그리고나서,git filter-repo
완벽하고 완벽하게 일을 해냈습니다.
$ git replace --graft <commit> <new parent commit>
$ git filter-repo --force
제가 얼마 전에 이런 질문을 한 적이 있기 때문에 여기에서 완전한 답을 찾을 수 있습니다.
자세한 내용은 문서에서 "기록 재작성" 섹션을 확인하십시오.
언급URL : https://stackoverflow.com/questions/3810348/setting-git-parent-pointer-to-a-different-parent
'source' 카테고리의 다른 글
Excel vba 새로 고침 대기 (0) | 2023.05.01 |
---|---|
자동 크기 조정 기능을 유지하여 WPF에서 텍스트를 회전하는 방법 (0) | 2023.05.01 |
WPF 데이터 그리드 선택 행 클릭 이벤트? (0) | 2023.05.01 |
MongoDB: 끔찍한 맵성능 저하 (0) | 2023.05.01 |
WPF 콤보 상자 디스플레이 구성원 경로 (0) | 2023.05.01 |