Git 리포지토리 내에서 기존 Git 하위 모듈을 어떻게 이동합니까?


356

내 Git 수퍼 프로젝트에서 Git 하위 모듈의 디렉토리 이름을 변경하고 싶습니다.

.gitmodules파일에 다음과 같은 항목이 있다고 가정 합니다.

[submodule ".emacs.d/vimpulse"]  
path = .emacs.d/vimpulse  
url = git://gitorious.org/vimpulse/vimpulse.git

나는 이동 입력해야 할 무엇 .emacs.d/vimpulse에 디렉토리를 .emacs.d/vendor/vimpulse먼저 삭제하지 않고 (설명 여기여기 ) 한 다음-추가 다시.

Git은 실제로 서브 모듈 태그에 전체 경로가 필요합니까?

[submodule ".emacs.d/vimpulse"]

또는 하위 프로젝트의 이름 만 저장할 수도 있습니까?

[submodule "vimpulse"]

참고 : OP git mv는 질문에서 바로 명령으로 자신의 질문 에 답변합니다.
Dan Rosenstark

그러나 git mv이렇게 사용할 수 없습니다 . 사용 deinitrm 지정된 stackoverflow.com/a/18892438/8047 .
Dan Rosenstark

14
@Yar : 적어도 git 2.0.0에서는 하위 모듈 git mv 에서만 작동 하며 다른 것은 필요하지 않습니다.
Pedro Romano

9
Git 1.8.5이동 서브 모듈로 시작 하는 것은 git mv명령을 사용하여 기본적으로 지원됩니다 ( 릴리스 노트 에서 @thisch가 직접 링크 함). 또한 여기에 답변
dennisschagt

git mv작업 영역에서 하위 모듈을 이동하고 하위 모듈 .git 파일을 올바르게 업데이트하지만 부모 저장소의 .git / modules 폴더 내 하위 폴더는 동일하게 유지됩니다. (저는 Windows에서 git 2.19.0을 사용하고 있습니다)
yoyo

답변:


377

참고 : 주석에서 언급 했듯이이 답변은 이전 버전의 git에 필요한 단계를 나타냅니다. Git은 이제 서브 모듈 이동을 기본적으로 지원합니다.

git 1.8.5부터 git mv old/submod new/submod예상대로 작동하고 모든 배관을 수행합니다. 하위 모듈 이동에 대한 수정 사항이 포함되어 있으므로 git 1.9.3 이상을 사용할 수 있습니다.


프로세스는 하위 모듈을 제거하는 방법과 유사합니다 (하위 모듈을 제거하는 방법 참조 ).

  1. .gitmodules서브 모듈의 경로를 적절하게 편집 하고 변경하고로 색인에 넣으십시오 git add .gitmodules.
  2. 필요한 경우 서브 모듈 ( mkdir -p new/parent) 의 새 위치에 대한 상위 디렉토리를 작성하십시오 .
  3. 모든 컨텐츠를 이전 디렉토리에서 새 디렉토리 ( mv -vi old/parent/submodule new/parent/submodule)로 이동하십시오.
  4. Git이이 디렉토리를 추적하는지 확인하십시오 ( git add new/parent).
  5. 로 이전 디렉토리를 제거하십시오 git rm --cached old/parent/submodule.
  6. .git/modules/old/parent/submodule모든 내용이 있는 디렉토리를 로 이동하십시오 .git/modules/new/parent/submodule.
  7. .git/modules/new/parent/config파일을 편집하고 작업 트리 항목이 새 위치를 가리키는 지 확인하십시오. 따라서이 예제에서는이어야합니다 worktree = ../../../../../new/parent/module. 일반적으로 ..해당 위치의 직접 경로에는 두 개 이상의 디렉토리 가 있어야합니다 .
  8. 파일을 편집하고 파일 new/parent/module/.git의 경로 .git가이 예에서와 같이 주 프로젝트 폴더 내의 올바른 새 위치를 가리키는 지 확인하십시오 gitdir: ../../../.git/modules/new/parent/submodule.

    git status 나중에 출력이 다음과 같이 보입니다.

    # On branch master
    # Changes to be committed:
    #   (use "git reset HEAD <file>..." to unstage)
    #
    #       modified:   .gitmodules
    #       renamed:    old/parent/submodule -> new/parent/submodule
    #
    
  9. 마지막으로 변경 사항을 커밋하십시오.


37
.gitmodules를 업데이트 할 때 해당 path구성과 하위 모듈의 이름을 모두 업데이트하십시오 . 예를 들어, foo / module을 bar / module로 이동하는 경우 .gitmodules에서 섹션 [submodule "foo/module"]을로 변경 [submodule "bar/module"]하고 같은 섹션에서 path = foo/module로 변경해야합니다 path = bar/module. 또한 .git / config에서 섹션 [submodule "foo/module"]을로 변경해야합니다 [submodule "bar/module"].
wilhelmtell

3
내가 찾은 가장 가까운 솔루션은 하위 모듈 (고통)을 삭제 한 다음 다른 위치에 다시 추가하는 것입니다.
Pablo Olmos de Aguilera C.

33
매우 중요한 참고 사항 : fatal: 'git status --porcelain' failed in...하위 모듈에서 .git 파일이나 디렉토리를 삭제하면됩니다.
독성

19
이 게시물은 편집과 같은 몇 가지 단계, 그리워 것 같습니다 .git/modules/old/parent/submodule업데이트, 새로운 위치로 이동 gitdir로를 old/parent/submodule/.git...이
SZX

38
git 1.8.5부터 git mv old/submod new/submod예상대로 작동하고 모든 배관을 수행합니다. 하위 모듈 이동에 대한 수정 사항이 포함되어 있으므로 git 1.9.3+를 사용하고 싶을 것입니다.
Valloric

232

위의 Valloric의 의견에서 가져온 가장 현대적인 답변 :

  1. Git 1.9.3으로 업그레이드 (또는 서브 모듈에 중첩 된 서브 모듈이 포함 된 경우 2.18 )
  2. git mv old/submod new/submod
  3. 그 후에 .gitmodules 및 하위 모듈 디렉토리는 이미 커밋을 위해 준비되었습니다 (이것을 확인할 수 git status있습니다).
  4. 와 함께 변경 사항을 커밋하면 git commit좋습니다.

끝난!


3
이것은 실제로 이동 된 서브 모듈 내부의 서브 모듈 을 1.9.3 제외하고 함께 작동했습니다 . 수동 정리가 필요했습니다.
Pascal

3
이것은 릴리스 노트에1.8.5 설명 된대로 이미 버전에서 작동해야 합니다 .
dennisschagt

6
이 대답은 1000 upvotes를 가져와야하며 위의 단계를 수행하는 내 저장소와 거의 엉망이되었습니다. 실제로 StackOverflow는이 상황에 대한 유스 케이스가 있어야합니다.
MGP

5
와우, 이것은 매력처럼 작동했습니다 (git 1.9.5), 나는 그것이 선택된 답이기를 바랍니다.
Alex Ilyaev

7
이것이 수행하지 않는 한 가지는 서브 모듈의 초기 레이블을 변경하지 않는다는 것입니다. .gitmodules파일 을 확인하면 old/submod경로가 변경되는 동안 여전히 하위 모듈의 레이블로 사용됩니다. 레이블도 변경하려면 실제로 모듈 디렉토리 경로를 안으로 이동 .git한 다음에서 수동으로 레이블을 변경해야합니다 .gitmodules.
CMCDragonkai

55

필자의 경우 하위 모듈을 한 디렉토리에서 하위 디렉토리 (예 : "AFNetworking"-> "ext / AFNetworking")로 옮기고 싶었습니다. 다음은 내가 따르는 단계입니다.

  1. 하위 모듈 이름과 경로를 "ext / AFNetworking"으로 변경하는 .gitmodules 편집
  2. 서브 모듈의 git 디렉토리를 ".git / modules / AFNetworking"에서 ".git / modules / ext / AFNetworking"으로 이동
  3. 라이브러리를 "AFNetworking"에서 "ext / AFNetworking"으로 이동
  4. ".git / modules / ext / AFNetworking / config"를 편집하고 [core] worktree라인을 수정하십시오 . 광산에서 ../../../AFNetworking에서../../../../ext/AFNetworking
  5. "ext / AFNetworking / .git"를 편집하고 수정하십시오 gitdir. 광산에서 ../.git/modules/AFNetworking에서../../git/modules/ext/AFNetworking
  6. git add .gitmodules
  7. git rm --cached AFNetworking
  8. git submodule add -f <url> ext/AFNetworking

마지막으로 자식 상태를 보았습니다.

matt$ git status
# On branch ios-master
# Changes to be committed:
#   (use "git reset HEAD <file>..." to unstage)
#
#   modified:   .gitmodules
#   renamed:    AFNetworking -> ext/AFNetworking

에일 라 위의 예제는 디렉토리 깊이를 변경하지 않고 작업의 복잡성과 큰 차이를 만들고 서브 모듈의 이름을 변경하지 않습니다 (실제로 필요하지 않을 수도 있지만 필자는 일치하지 않았습니다. 해당 경로에 새 모듈을 추가하면 발생합니다.)


4
고마워 매트. 나는 받아 들인 대답에서 길을 잃었다. 기본 케이스 이상을 다루어 주셔서 감사합니다. 이것은 매력처럼 작동했습니다.
Andrew Hubbs

.git / modules 경로를 뒤섞거나 서브 모듈의 이름을 변경할 필요가 없습니다 (arand 및 Bob Bell 언급). 그러나 그렇게하면 물건을 더 깨끗하게 유지할 수 있습니다.
gatoatigrado

하위 서브 모듈에 대해 2, 3, 4 및 5 단계를 재귀 적으로 수행하는 것을 잊지 마십시오.
herzbube

22

[업데이트 : 2014-11-26] Yar가 아래에 잘 요약 한 것처럼, 무엇이든하기 전에 하위 모듈의 URL을 알고 있어야합니다. 알 수없는 경우 .git/.gitmodules키를 열고 검사하십시오 submodule.<name>.url.

무엇 나를 위해 일하는 것이었다 이전 서브 모듈 제거 하여 git submodule deinit <submodule>다음을 git rm <submodule-folder>. 그런 다음 새 폴더 이름으로 서브 모듈을 다시 추가하고 커밋하십시오. 커밋하기 전에 자식 상태를 확인하면 이전 하위 모듈의 이름이 새 이름으로 바뀌고 .gitmodule이 수정 된 것으로 표시됩니다.

$ git submodule deinit foo
$ git rm foo
$ git submodule add https://bar.com/foo.git new-foo
$ git status
renamed:    foo -> new-foo
modified:   .gitmodules
$ git commit -am "rename foo submodule to new-foo"

1
git 1.8.3 이상이 필요합니다. git을 업그레이드하려면이 게시물을 참조하십시오 : evgeny-goldin.com/blog/3-ways-install-git-linux-ubuntu
Michael Cole

1
또는 더 나은 방법 : sudo add-apt-repository ppa : git-core / ppa sudo apt-get 업데이트 sudo apt-get 설치 git
Michael Cole

@MichaelCole 감사합니다! 맞아! Git-1.8.3 릴리즈 노트를 참조하십시오 . 참고 : Ubuntu-13.10 (Saucy Salamander)에는 Git-1.8.3.2 가 있지만 ppa 가 있다는 것을 아는 것이 좋습니다 . 또한 IMHO 자식 하위 트리 병합 전략 이 더 나은 방법입니다. 내 프로젝트의 하위 모듈을 포기했습니다. 기존 프로젝트를 이해하는 것이 좋습니다.
Mark Mikofski

나는 여러 가지 해결책을 시도했지만 당신의 것이 가장 좋습니다. 커맨드 라인 만 사용하면 git 파일을 수정할 필요가 없으며해서는 안됩니다. 감사!
nahung89

12

트릭은 .git서브 모듈 의 디렉토리가 이제 마스터 저장소의 아래 .git/modules에 유지되고 각 서브 모듈은 .git그것을 가리키는 파일을 가지고 있음을 이해하는 것 같습니다 . 이것은 지금 필요한 절차입니다.

  • 서브 모듈을 새 집으로 옮깁니다.
  • .git서브 모듈의 작업 디렉토리에서 파일을 편집하고 포함 된 경로를 수정하여 마스터 저장소 디렉토리의 올바른 디렉토리를 가리 키십시오 .git/modules.
  • 마스터 저장소의 .git/modules디렉토리를 입력하고 서브 모듈에 해당하는 디렉토리를 찾으십시오.
  • 서브 모듈 작업 디렉토리의 새 위치를 가리 키도록 경로를 config갱신 하여 파일을 편집하십시오 worktree.
  • .gitmodules마스터 저장소의 루트 에서 파일을 편집하여 서브 모듈의 작업 디렉토리 경로를 업데이트하십시오.
  • git add -u
  • git add <parent-of-new-submodule-directory> (추가하는 것이 중요합니다 하위 모듈 디렉토리 자체가 아닌 parent 합니다.)

몇 가지 참고 사항 :

  • 그만큼 [submodule "submodule-name"]의 행 .gitmodules.git/config서로 일치해야하지만, 무엇에 해당하지 않습니다.
  • 서브 모듈 작업 디렉토리와 .git디렉토리는 서로를 올바르게 가리켜 야합니다.
  • .gitmodules.git/config파일이 동기화되어야한다.

9

"[submodule"다음에 따옴표로 묶인 문자열은 중요하지 않습니다. 원하는 경우 "foobar"로 변경할 수 있습니다. ".git / config"에서 일치하는 항목을 찾는 데 사용됩니다.

따라서 "git submodule init"를 실행하기 전에 변경하면 제대로 작동합니다. 변경하거나 병합을 통해 변경을 수행하는 경우 .git / config를 수동으로 편집하거나 "git submodule init"를 다시 실행해야합니다. 후자를 수행하면 .git / config에 이전 이름을 가진 무해한 "가닥"항목이 남게됩니다.


이것은 정말로 성가 시지만, 당신 말이 맞습니다. 최악의 부분은 URL을 변경하고 git init을 실행해도 업데이트되지 않는 것 같습니다 .git / config를 수동으로 편집해야합니다.
crimson_penguin

1
이 경우 git submodule sync변경 사항을 .git/config자동으로 전파합니다.
CharlesB

9

표준 명령을 사용하여 새 하위 모듈을 추가하고 이전 하위 모듈을 제거하면됩니다. (.git 내부의 우발적 인 오류를 방지해야 함)

설정 예 :

mkdir foo; cd foo; git init; 
echo "readme" > README.md; git add README.md; git commit -m "First"
## add submodule
git submodule add git://github.com/jquery/jquery.git
git commit -m "Added jquery"
## </setup example>

'jquery'를 'vendor / jquery / jquery'로 이동하십시오.

oldPath="jquery"
newPath="vendor/jquery/jquery"
orginUrl=`git config --local --get submodule.${oldPath}.url`

## add new submodule
mkdir -p `dirname "${newPath}"`
git submodule add -- "${orginUrl}" "${newPath}"

## remove old submodule
git config -f .git/config --remove-section "submodule.${oldPath}"
git config -f .gitmodules --remove-section "submodule.${oldPath}"
git rm --cached "${oldPath}"
rm -rf "${oldPath}"              ## remove old src
rm -rf ".git/modules/${oldPath}" ## cleanup gitdir (housekeeping)

## commit
git add .gitmodules
git commit -m "Renamed ${oldPath} to ${newPath}"

대형 서브 모듈에 대한 보너스 방법 :

하위 모듈이 크고 복제를 기다리지 않으려면 이전을 원점으로 사용하여 새 하위 모듈을 만든 다음 원점을 전환 할 수 있습니다.

예 (동일한 예 설정 사용)

oldPath="jquery"
newPath="vendor/jquery/jquery"
baseDir=`pwd`
orginUrl=`git config --local --get submodule.${oldPath}.url`

# add new submodule using old submodule as origin
mkdir -p `dirname "${newPath}"`
git submodule add -- "file://${baseDir}/${oldPath}" "${newPath}"

## change origin back to original
git config -f .gitmodules submodule."${newPath}".url "${orginUrl}"
git submodule sync -- "${newPath}"

## remove old submodule
...

헤드를 사용하지 않는 경우에서 모듈의 올바른 버전을 확인해야 할 수도 있습니다 newPath.
paulmelnikow

2

주어진 솔루션이 나를 위해 작동하지 않았지만 비슷한 버전이 ...

이것은 복제 된 저장소를 사용하므로 하위 모듈 git repos는 최상위 저장소 .git dir에 포함됩니다. 모든 양이온은 최상위 저장소에서 가져옵니다.

  1. .gitmodules를 편집하고 해당 서브 모듈의 "path ="설정을 변경하십시오. 레이블을 변경하거나이 파일을 색인에 추가 할 필요가 없습니다.

  2. .git / modules / name / config를 편집하고 문제가있는 서브 모듈에 대한 "worktree ="설정을 변경하십시오

  3. 운영:

    mv submodule newpath/submodule
    git add -u
    git add newpath/submodule
    

리포지토리가 원자 또는 상대 하위 모듈인지 여부에 차이가 있는지 궁금합니다. 제 경우에는 하위 모듈입니다 (서브 모듈 / .git은 topproject / .git / modules / submodule에 대한 참조입니다)



2

나는 어제이 시련을 겪었고이 답변 은 완벽하게 작동했습니다. 명확성을 위해 내 단계는 다음과 같습니다.

  1. 서브 모듈이 체크인되어 해당 서버로 푸시되었는지 확인하십시오. 또한 어떤 분기가 켜져 있는지 알아야합니다.
  2. 서브 모듈의 URL이 필요합니다! more .gitmodules일단 서브 모듈을 삭제하면 주변에 있지 않기 때문에 사용하십시오.
  3. 지금 당신은 사용할 수 있습니다 deinit, rm다음과submodule add

명령

    git submodule deinit Classes/lib/mustIReally
    git rm foo
    git submodule add http://developer.audiob.us/download/SDK.git lib/AudioBus

    # do your normal commit and push
    git commit -a 

참고 : git mv는 이것을하지 않습니다. 조금도.


3
좋은 요약입니다. git mvGit의 마지막 버전에서는 +1 이 더 좋습니다.
VonC

@VonC 나는 git 1.8.5에서 테스트했는데, 그것이 얻는 것만 큼 좋은지 확신한다 mv. 감사!
Dan Rosenstark
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.