我想在我的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"]

当前回答

只需使用shell脚本git-submodule-move。

其他回答

我遇到同样的问题并成功地解决了它。感谢您在Github发布delete_git_submodule.md

要移除一个子模块,你需要:

从.gitmodules文件中删除相关的部分。 阶段。gitmodules的变化,git添加。gitmodules 从.git/config中删除相关的部分。(也许并不存在) 运行git rm——cached path_to_submodule(没有后面的斜杠)。 执行rm -rf .git/modules/path_to_submodule(没有后面的斜杠)。 Commit -m "已删除的子模块" 删除现在不跟踪的子模块文件rm -rf path_to_submodule

最现代的答案来自Valloric的评论:

升级到Git 1.9.3(如果子模块包含嵌套子模块,则升级到2.18) Git mv old/submod new/submod 之后.gitmodules和子模块目录已经被提交(你可以用git status来验证这一点)。 使用git Commit提交更改-你就可以开始了!

完成了!

“[submodule”后面引号中的字符串并不重要。如果你愿意,你可以把它改成“foobar”。它用于在“.git/config”中查找匹配的条目。

因此,如果你在运行"git submodule init"之前进行更改,它会正常工作。如果你做了更改(或通过合并进行更改),你需要手动编辑.git/config或再次运行"git submodule init"。如果您选择后者,您将在.git/config中留下一个带有旧名称的无害的“搁浅”条目。

更新版本的git

Git现在支持移动子模块:

从git 1.8.5开始,git mv old/submod new/submod就像预期的那样工作,并为你做了所有的管道工作。您可能希望使用git 1.9.3或更新版本,因为它包含了针对子模块移动的修复。

git的旧版本

正如评论中提到的,这个答案指的是旧版本git所需的步骤。

这个过程类似于如何删除子模块(参见如何删除子模块?):

Edit .gitmodules and change the path of the submodule appropriately, and put it in the index with git add .gitmodules. If needed, create the parent directory of the new location of the submodule (mkdir -p new/parent). Move all content from the old to the new directory (mv -vi old/parent/submodule new/parent/submodule). Make sure Git tracks this directory (git add new/parent). Remove the old directory with git rm --cached old/parent/submodule. Move the directory .git/modules/old/parent/submodule with all its content to .git/modules/new/parent/submodule. Edit the .git/modules/new/parent/config file, make sure that worktree item points to the new locations, so in this example it should be worktree = ../../../../../new/parent/module. Typically there should be two more .. than directories in the direct path in that place. Edit the file new/parent/module/.git, make sure that the path in it points to the correct new location inside the main project .git folder, so in this example gitdir: ../../../.git/modules/new/parent/submodule. git status output looks like this for me afterwards: # On branch master # Changes to be committed: # (use "git reset HEAD <file>..." to unstage) # # modified: .gitmodules # renamed: old/parent/submodule -> new/parent/submodule # Finally, commit the changes.

您只需添加一个新的子模块,并使用标准命令删除旧的子模块。(应该防止.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
...