programing

Git 하위 모듈 헤드 '참조가 트리가 아닙니다' 오류

muds 2023. 6. 30. 22:38
반응형

Git 하위 모듈 헤드 '참조가 트리가 아닙니다' 오류

잘못된 커밋을 가리키는 하위 모듈이 있는 프로젝트가 있습니다. 하위 모듈 커밋은 로컬로 유지되며 다른 보고서에서 가져오려고 하면 다음과 같은 메시지가 표시됩니다.

$ git submodule update
fatal: reference is not a tree: 2d7cfbd09fc96c04c4c41148d44ed7778add6b43
Unable to checkout '2d7cfbd09fc96c04c4c41148d44ed7778add6b43' in submodule path 'mysubmodule'

서브모듈 HEAD가 무엇이어야 하는지 알고 있습니다. 커밋된 레포를 누르지 않고 로컬로 변경할 수 있는 방법이 있습니까?2d7cfbd09fc96c04c4c41148d44ed7778add6b43?

제가 확실히 하고 있는지는 모르겠습니다만...여기 제가 찾은 비슷한 상황이 있습니다.

슈퍼 프로젝트의 현재 상태에서 참조되는 커밋과 달리 하위 모듈의 리포지토리에 사용할 커밋이 있다고 가정하면 두 가지 방법이 있습니다.

첫 번째는 사용할 하위 모듈의 커밋을 이미 알고 있어야 합니다.서브모듈을 직접 조정한 후 슈퍼 프로젝트를 업데이트하여 "내부, 외부"에서 작동합니다.두 번째는 서브모듈을 수정한 슈퍼 프로젝트 커밋을 찾은 다음 다른 서브모듈 커밋을 참조하도록 슈퍼 프로젝트의 인덱스를 재설정함으로써 "외부, 에서" 작업합니다.

내부, 외부

이미 ,cd 커밋을 후, "commit", "commit"을 확인합니다.git add그리고.git commit슈퍼 프로젝트에서 말입니다.

예:

$ git submodule update
fatal: reference is not a tree: e47c0a16d5909d8cb3db47c81896b8b885ae1556
Unable to checkout 'e47c0a16d5909d8cb3db47c81896b8b885ae1556' in submodule path 'sub'

.sub어떻게든, 우리는 이미 서브모듈이 커밋되기를 원한다는 것을 알고 있습니다.5d5a3ee314476701a20f2c6ec4a53f88d651df6c그곳에 가서 직접 확인해 보세요.

하위 모듈에서 체크아웃

$ cd sub
$ git checkout 5d5a3ee314476701a20f2c6ec4a53f88d651df6c
Note: moving to '5d5a3ee314476701a20f2c6ec4a53f88d651df6c' which isn't a local branch
If you want to create a new branch from this checkout, you may do so
(now or later) by using -b with the checkout command again. Example:
  git checkout -b <new_branch_name>
HEAD is now at 5d5a3ee... quux
$ cd ..

커밋을 체크아웃하기 때문에 하위 모듈에 헤드가 분리됩니다. 확인하고 " 하모분사있고확다사다음용니합을면려인하는위지용기하듈를이"를 사용합니다.git checkout -b newbranch <commit>커밋에서 지점을 만들고 체크아웃하거나 원하는 지점(예: 끝에 원하는 커밋이 있는 지점)을 체크아웃합니다.

슈퍼 프로젝트 업데이트

하위 모듈의 체크아웃은 작업 트리의 변경 사항으로 슈퍼 프로젝트에 반영됩니다.그래서 우리는 슈퍼 프로젝트의 인덱스에 변화를 준비하고 결과를 검증해야 합니다.

$ git add sub

결과 확인

$ git submodule update
$ git diff
$ git diff --cached
diff --git c/sub i/sub
index e47c0a1..5d5a3ee 160000
--- c/sub
+++ i/sub
@@ -1 +1 @@
-Subproject commit e47c0a16d5909d8cb3db47c81896b8b885ae1556
+Subproject commit 5d5a3ee314476701a20f2c6ec4a53f88d651df6c

하위 모듈이 이미 지정된 커밋에 있기 때문에 하위 모듈 업데이트가 자동으로 수행되었습니다.첫 번째 diff는 인덱스와 작업 트리가 같다는 것을 보여줍니다.세 번째 차이는 유일한 단계적 변화가 이동하는 것임을 보여줍니다.sub다른 커밋의 하위 모듈.

저지르다

git commit

그러면 고정 하위 모듈 항목이 커밋됩니다.


외부, 내부

서브모듈에서 어떤 커밋을 사용해야 할지 모르는 경우 슈퍼 프로젝트의 기록을 확인하여 안내할 수 있습니다.슈퍼 프로젝트에서 직접 재설정을 관리할 수도 있습니다.

$ git submodule update
fatal: reference is not a tree: e47c0a16d5909d8cb3db47c81896b8b885ae1556
Unable to checkout 'e47c0a16d5909d8cb3db47c81896b8b885ae1556' in submodule path 'sub'

이것은 위와 같은 상황입니다.하지만 이번에는 서브 모듈에 담그는 대신 슈퍼 프로젝트에서 수정하는 데 초점을 맞출 것입니다.

슈퍼 프로젝트의 오류 커밋 찾기

$ git log --oneline -p -- sub
ce5d37c local change in sub
diff --git a/sub b/sub
index 5d5a3ee..e47c0a1 160000
--- a/sub
+++ b/sub
@@ -1 +1 @@
-Subproject commit 5d5a3ee314476701a20f2c6ec4a53f88d651df6c
+Subproject commit e47c0a16d5909d8cb3db47c81896b8b885ae1556
bca4663 added sub
diff --git a/sub b/sub
new file mode 160000
index 0000000..5d5a3ee
--- /dev/null
+++ b/sub
@@ -0,0 +1 @@
+Subproject commit 5d5a3ee314476701a20f2c6ec4a53f88d651df6c

좋아요, 안에서 상한 것 같아요.ce5d37c입니다.ce5d37c~).

수 .5d5a3ee314476701a20f2c6ec4a53f88d651df6c를 사용하고 대신 위의 "실행, 출력" 프로세스를 사용합니다.

슈퍼 프로젝트에서 체크아웃

$ git checkout ce5d37c~ -- sub

" " "의 됩니다.sub그것이 약속한 바와 같이.ce5d37c~슈퍼 프로젝트에서.

하위 모듈 업데이트

$ git submodule update
Submodule path 'sub': checked out '5d5a3ee314476701a20f2c6ec4a53f88d651df6c'

하위 모듈 업데이트가 정상으로 전환되었습니다(헤드가 분리되었음을 나타냄).

결과 확인

$ git diff ce5d37c~ -- sub
$ git diff
$ git diff --cached
diff --git c/sub i/sub
index e47c0a1..5d5a3ee 160000
--- c/sub
+++ i/sub
@@ -1 +1 @@
-Subproject commit e47c0a16d5909d8cb3db47c81896b8b885ae1556
+Subproject commit 5d5a3ee314476701a20f2c6ec4a53f88d651df6c

첫 번째 차이점은sub이제 에도 마찬가지입니다.ce5d37c~두 번째 차이는 인덱스와 작업 트리가 같다는 것을 보여줍니다.세 번째 차이는 유일하게 단계적으로 변화하는 것이 이동하는 것임을 보여줍니다.sub다른 커밋의 하위 모듈.

저지르다

git commit

그러면 고정 하위 모듈 항목이 커밋됩니다.

사용해 보십시오.

git submodule sync
git submodule update

이 오류는 하위 모듈에 커밋이 없음을 의미할 수 있습니다.즉, 저장소(A)에는 하위 모듈(B)이 있습니다.A는 특정 커밋(B)을 가리키도록 B를 로드하려고 합니다.해당 커밋이 누락된 경우 오류가 발생합니다.한 번 가능한 원인: 커밋에 대한 참조는 A에서 푸시되었지만 실제 커밋은 B에서 푸시되지 않았습니다.그래서 저는 거기서 시작했습니다.

권한 문제가 있을 가능성이 낮고 커밋을 풀할 수 없습니다(git+ssh를 사용하는 경우 가능).

.git/config 및 .git 모듈에서 하위 모듈 경로가 정상인지 확인합니다.

마지막으로 시도해야 할 한 가지 - 하위 모듈 디렉토리 내: git reset HEAD --hard

의 지점은 수도 , 이 될 수도 있지만, 당신의 지점을 시도해 .git fetch

가능한 원인

이 문제는 다음과 같은 경우에 발생할 수 있습니다.

  1. 하위 모듈이 제자리에서 편집되었습니다.
  2. 커밋된 하위 모듈, 가리키는 하위 모듈의 해시를 업데이트합니다.
  3. 하위 모듈을 누르지 않았습니다.

예를 들어, 다음과 같은 일이 발생했습니다.

$ cd submodule
$ emacs my_source_file  # edit some file(s)
$ git commit -am "Making some changes but will forget to push!"

이 시점에서 하위 모듈을 눌렀어야 합니다.

$ cd .. # back to parent repository
$ git commit -am "updates to parent repository"
$ git push origin master

결과적으로 누락된 커밋은 여전히 로컬 디스크에 있으므로 원격 사용자가 찾을 수 없습니다.

해결책

푸시하도록 서브모듈을 수정한 사람에게 알려줍니다.

$ cd submodule
$ git push

다음을 수행할 때 이 오류가 발생했습니다.

$ git submodule update --init --depth 1

그러나 상위 프로젝트의 커밋은 이전 커밋을 가리키고 있었습니다.

하위 모듈 폴더 삭제 및 실행:

$ git submodule update --init

문제를 해결하지 못했습니다.레포를 삭제하고 깊이 플래그 없이 다시 시도해보니 효과가 있었습니다.

이 오류는 Ubuntu 16.04 git 2.7.4에서 발생하지만 Ubuntu 18.04 git 2.17에서는 발생하지 않습니다.

@commentan kumar는 다음과 같이 언급했습니다.

이전 커밋을 포함하도록 깊이 카운트를 늘렸고 효과가 있었습니다.

이 문제는 재조정된 리포지토리를 가리키는 하위 모듈이 있고 지정된 커밋이 "종료"된 경우에도 발생할 수 있습니다.커밋이 여전히 원격 리포지토리에 있을 수 있지만 분기에는 없습니다.새 분기를 만들 수 없는 경우(예: 리포지토리가 아닌 경우) 슈퍼 프로젝트를 업데이트하여 새 커밋을 지정해야 합니다.또는 하위 모듈의 복사본 중 하나를 다른 곳에 푸시한 다음 슈퍼 프로젝트를 업데이트하여 해당 리포지토리를 가리키도록 할 수 있습니다.

이 답변은 터미널 git 경험이 제한된 SourceTree 사용자를 위한 것입니다.

Git 프로젝트(슈퍼 프로젝트) 내에서 문제가 있는 하위 모듈을 엽니다.

가져오기를 수행하고 '모든 태그 가져오기'가 선택되어 있는지 확인합니다.

Git 프로젝트를 다시 시작합니다.

이렇게 하면 '참조는 나무가 아닙니다' 문제가 10번 중 9번 해결됩니다.그 한 번은 그렇지 않을 것이며, 상단 답변에서 설명한 대로 터미널 수정입니다.

하위 모듈 기록은 하위 모듈 비트에 안전하게 보존됩니다.

그렇다면 서브모듈을 삭제하고 다시 추가하는 것은 어떨까요?

그렇지 않으면 수동으로 편집하려고 했습니까?HEAD 는또.refs/master/head .git

만약을 위해 업데이트를 시도해 보십시오.git바이너리

버전인 GitHub이 있습니다.git version 1.8.4.msysgit.0통해 업데이트를 통해 해결되었습니다.

저의 경우, 위의 어떤 답변도 좋은 답변임에도 불구하고 문제를 해결하지 못합니다.그래서 저는 제 솔루션을 게시합니다(저의 경우 두 개의 Git 클라이언트, 즉 클라이언트 A와 B).

  1. 하위 모듈의 dir로 이동합니다.

    cd sub
    
  2. 마스터 체크아웃:

    git checkout master
    
  3. 두 클라이언트 모두 볼 수 있는 커밋 코드로 리베이스

  4. 부모의 dir로 돌아갑니다.

  5. 주인에게 맡기다

  6. 다른 클라이언트로 변경합니다.rebase다시.

  7. 마침내 그것은 지금 잘 작동합니다!몇 번의 커밋을 잃을지도 모르지만 효과가 있습니다.

  8. 참고로, 서브모듈을 제거하려고 하지 마십시오. 서브모듈은 그대로 유지됩니다..git/modules활성화된 로컬 모듈이 아니면 이 하위 모듈을 다시 읽을 수 없습니다.

Git repo를 서브모듈의 헤드와 동기화하기 위해 서브모듈을 제거한 후 다시 읽기를 수행하면 기록을 수정할 필요가 없습니다.안타깝게도 서브모듈을 제거하려면 단일 git 명령이 아닌 해킹이 필요하지만 실행 가능합니다.

https://gist.github.com/kyleturner/1563153 에서 영감을 받아 서브모듈을 제거하기 위해 수행한 단계:

  1. Run gitrm --캐시됨
  2. .git 모듈 파일에서 관련 행을 삭제합니다.
  3. .git/config에서 관련 섹션을 삭제합니다.
  4. 추적되지 않은 하위 모듈 파일을 삭제합니다.
  5. .git/modules/ 디렉토리를 제거합니다.

다시 말씀드리지만, 서브모듈의 헤드를 다시 가리키기만 하면 되고 서브모듈의 로컬 복사본을 그대로 유지하여 복잡한 작업을 수행할 필요가 없는 경우에 유용합니다.여기에서는 서브모듈이 어디에서 시작되었든 상관없이 서브모듈을 자체 레포로 "옳다"고 가정하고 서브모듈로 올바르게 포함하기를 원할 뿐입니다.

참고: 이러한 종류의 조작이나 단순한 커밋 또는 푸시 이외의 git 명령을 수행하기 전에 항상 프로젝트의 전체 복사본을 만듭니다.저는 다른 모든 답변과 함께 일반적인 지침으로도 조언하고 싶습니다.

이 문제를 우연히 발견했는데, 어떤 해결책도 저에게 효과가 없었습니다.제 문제에 대한 해결책으로 밝혀진 것은 사실 훨씬 더 간단합니다. Git 업그레이드입니다.제 것은 1.7.1이었고, 2.16.1(최신)로 업그레이드한 후 문제가 흔적도 없이 사라졌습니다!여기 두고 가는 거 같은데, 도움이 됐으면 좋겠네요.

언급URL : https://stackoverflow.com/questions/2155887/git-submodule-head-reference-is-not-a-tree-error

반응형