2011-10-24 3 views
78

나는 나의 자식 목록에 자식 하위 모듈이있다. 내가 이해할 수 있듯이, 메인 레포는 SHA 값 (어딘가에 ...)을 저장하고 서브 모듈의 특정 커밋을 가리켜 "링크"되어 있습니다.Git Submodule 포인터를 포함 저장소에 저장된 커밋으로 되돌리려면 어떻게해야합니까?

내 서브 모듈로 들어가서 git checkout some_other_branch을 입력했습니다. 나는 내가 어디에서 왔는지 전혀 모른다.

메인 레포와 서브 모듈이 다시 동기화되도록 포인터를 되돌리고 싶습니다.

첫 번째 (아마 순진한) 본능은 다른 모든 것에서 효과가있는 것으로 보이는 git reset --hard입니다. 놀랍게도,이 시나리오에서는 작동하지 않았습니다.

git diff을 입력 할 수 있다고 생각했는데, 서브 모듈 포인터가 가지고 있던 SHA ID를 메모 한 다음 서브 모듈과 git checkout [SHA ID]으로 향합니다 ...하지만 확실한 방법이 있어야합니까?

내가 아직도 자식 서브 모듈에 대해 배우고 있기 때문에 모를 개념에 대한 단어가 있으면 내 용어를 수정하십시오.

답변

112

당신이 부모 저장소가 있어야합니다 믿고 무엇을 동기화에 귀하의 서브 모듈을 업데이트 할 : 명령 레벨은) 아래 서브 모듈에 CD를 가진 건너 뛸 수 있습니다. 이 모두 잘해야

 
Update the registered submodules, i.e. clone missing submodules and 
checkout the commit specified in the index of the containing 
repository. This will make the submodules HEAD be detached unless 
--rebase or --merge is specified or the key submodule.$name.update 
is set to rebase or merge. 

실행 : 서브 모듈의 맨 페이지에서

다음 "superproject"폴더에

git submodule update 
+2

어떻게 든 : 서브 모듈에서

git reset --hard git submodule update 

: 부모에서

: 나는 완전히 내 부모와 서브 모듈 모두 unstaged 변경 사항을 취소하려는 경우 그래서, 다음을 수행 '--init'을 추가하십시오. 그것이 없다면, 서브 모듈은'(새로운 커밋들)'상태를 유지할 것이다. 내 서브 모듈이 이미 초기화되었지만. – Ambidex

+0

@Ambidex 예 --init' 옵션은이 모든면에서 결정적입니다. 내 하위 모듈이 https를 통해 복제 된 이후 사용자 이름과 비밀번호를 묻는 메시지가 표시되었습니다. 나는 두 폴더에 들어가서 체크 아웃을 위해'ssh' 프로토콜을 사용하도록 리모트를 설정했다. –

14

하위 모듈이 가리키는 커밋을 변경하려면 해당 하위 모듈에서 해당 버전을 체크 아웃 한 다음 포함 된 저장소로 돌아가서 변경 내용을 추가하고 커밋해야합니다.

또는 하위 모듈이 위쪽 repo가 ​​가리키는 버전에 있도록하려면 git submodule update --recursive을 수행하십시오. 방금 복제 한 경우 --init을 추가하십시오.

또한 submodule 명령이없는 git submodule은 사용자가 가리키는 커밋을 표시합니다. 동기화되지 않은 경우 커밋 앞에 - 또는 +가 표시됩니다.

하위 모듈이있는 트리를 보면 하위 모듈이 모양 또는 나무가 아닌 commit으로 표시되어 있음을 알 수 있습니다.

git ls-tree <some sha1, or branch, etc> Submodule/path 

그런 다음 커밋 볼 수 있습니다 또는 다른 어떤 당신이 자식에서 로그에 등을합니다 (git-dir 옵션을 그 전달하여 좋아하는 경우 :

은 특정 당신이 할 수있는 서브 모듈에 포인트를 WRT를 저지 것을 볼 수

git --git-dir=Submodule/path log -1 $(<the above statement>) 
4

사용 git ls-tree HEAD보고이의 업데이트 명령은 무엇인가 당신의 서브 모듈을 원래 커밋 한 것은 무엇입니까? 그런 다음 하위 모듈 디렉토리로 변경하고 git log --oneline --decorate을 사용하여 원래 커밋이 수행 된 분기를 확인합니다. 마지막으로 git checkout original-commit-branch.

$ git --version 
git version 1.7.4.1 
$ git status 
# On branch master 
# Changes not staged for commit: 
# (use "git add <file>..." to update what will be committed) 
# (use "git checkout -- <file>..." to discard changes in working directory) 
# 
# modified: sm2 (new commits) 
# 
no changes added to commit (use "git add" and/or "git commit -a") 
$ git ls-tree HEAD 
100644 blob 76813a07ae558db274cefc6d903ec24323fdeb0d .gitmodules 
100644 blob e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 main 
160000 commit 7c5889497938cd5699a9234a98ee93947e52b1ed sm1 
160000 commit f68bed61cba6f94cef57554f2cf46a45a4a0d337 sm2 
$ cd sm2 
$ git log --oneline --decorate 
5b8d48f (HEAD, foo1) foo1.1 
f68bed6 (origin/master, origin/HEAD, master) Initial commit. 
$ git checkout master 
Switched to branch 'master' 
$ cd .. 
$ git status 
# On branch master 
nothing to commit (working directory clean) 

은 "superproject"는 SM2 서브 모듈을 보여줍니다에서 f68bed6을 커밋하지만 SM2 그것이 5b8d48f에 머리를 가지고

여기, 내가 설정 몇 가지 테스트 디렉토리를 사용하면 명령이 어떻게 보이는지입니다. 서브 모듈 커밋 f68bed6에는 서브 모듈 디렉토리의 체크 아웃에 사용될 수있는 세 개의 분기가 있습니다.

+0

감사합니다! – Alec

2

내가 마주 친 또 다른 경우는 버리고 싶은 하위 모듈에 무단 변경이있는 경우입니다. git submodule update는 그 변경 사항을 제거하지 않을 것이고, 부모 디렉토리에서 -hard를 재설정하지 않을 것이다. 당신은 서브 모듈 디렉토리로 가서 git reset -hard를 할 필요가있다. 내가 필요 나를 위해,

git reset --hard 
관련 문제