如何在 Git 存储库中移动现有的 Git 子模块?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/4604486/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How do I move an existing Git submodule within a Git repository?
提问by thisch
I would like to change the directory name of a Git submodule in my Git superproject.
我想在我的 Git 超级项目中更改 Git 子模块的目录名称。
Lets suppose I have the following entry in my .gitmodules
file:
假设我的.gitmodules
文件中有以下条目:
[submodule ".emacs.d/vimpulse"]
path = .emacs.d/vimpulse
url = git://gitorious.org/vimpulse/vimpulse.git
What do I have to type to move the .emacs.d/vimpulse
directory to .emacs.d/vendor/vimpulse
without deleting it first (explained
hereand here) and then re-adding it.
我必须输入什么才能将.emacs.d/vimpulse
目录移动到.emacs.d/vendor/vimpulse
而不先删除它(在此处和此处解释
)然后重新添加它。
Does Git really need the whole path in the submodule tag
Git 是否真的需要子模块标签中的整个路径
[submodule ".emacs.d/vimpulse"]
or is it also possible to store just the name of the subproject?
或者也可以只存储子项目的名称?
[submodule "vimpulse"]
回答by Axel Beckert
Note:As mentioned in the comments this answer refers to the steps needed with older versions of git. Git now has native support for moving submodules:
注意:如评论中所述,此答案指的是旧版本 git 所需的步骤。Git 现在原生支持移动子模块:
Since git 1.8.5,
git mv old/submod new/submod
works as expected and does all the plumbing for you. You might want to use git 1.9.3 or newer, because it includes fixes for submodule moving.
从 git 1.8.5 开始,
git mv old/submod new/submod
按预期工作并为您完成所有管道工作。您可能想要使用 git 1.9.3 或更新版本,因为它包括子模块移动的修复。
The process is similar to how you'd remove a submodule (see How do I remove a submodule?):
该过程类似于您如何删除子模块(请参阅如何删除子模块?):
- Edit
.gitmodules
and change the path of the submodule appropriately, and put it in the index withgit 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 beworktree = ../../../../../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 examplegitdir: ../../../.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.
.gitmodules
适当编辑和更改子模块的路径,并将其放在索引中git add .gitmodules
。- 如果需要,创建子模块新位置的父目录 (
mkdir -p new/parent
)。 - 将所有内容从旧目录移动到新目录 (
mv -vi old/parent/submodule new/parent/submodule
)。 - 确保 Git 跟踪此目录 (
git add new/parent
)。 - 删除旧目录
git rm --cached old/parent/submodule
。 - 将目录
.git/modules/old/parent/submodule
及其所有内容移动到.git/modules/new/parent/submodule
. - 编辑
.git/modules/new/parent/config
文件,确保工作树项指向新位置,因此在本例中它应该是worktree = ../../../../../new/parent/module
. 通常..
在那个地方的直接路径中应该有两个以上的目录。 编辑文件
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 #
最后,提交更改。
回答by phatmann
The most modern answer, taken from Valloric's comment above:
最现代的答案,取自以上 Valloric 的评论:
- Upgrade to Git 1.9.3 (or 2.18 if the submodule contains nested submodules)
git mv old/submod new/submod
- Afterwards the .gitmodules and the submodule directory are already staged for a commit (you can verify this with
git status
.) - Commit the changes with
git commit
and you're good to go!
- 升级到 Git 1.9.3(如果子模块包含嵌套子模块,则升级到2.18)
git mv old/submod new/submod
- 之后 .gitmodules 和子模块目录已经准备好提交(您可以使用
git status
.验证这一点) - 提交更改,
git commit
您就可以开始了!
Done!
完毕!
回答by Matt Connolly
In my case, I wanted to move a submodule from one directory into a subdirectory, e.g. "AFNetworking" -> "ext/AFNetworking". These are the steps I followed:
就我而言,我想将一个子模块从一个目录移动到一个子目录中,例如“AFNetworking”->“ext/AFNetworking”。这些是我遵循的步骤:
- Edit .gitmodules changing submodule name and path to be "ext/AFNetworking"
- Move submodule's git directory from ".git/modules/AFNetworking" to ".git/modules/ext/AFNetworking"
- Move library from "AFNetworking" to "ext/AFNetworking"
- Edit ".git/modules/ext/AFNetworking/config" and fix the
[core] worktree
line. Mine changed from../../../AFNetworking
to../../../../ext/AFNetworking
- Edit "ext/AFNetworking/.git" and fix
gitdir
. Mine changed from../.git/modules/AFNetworking
to../../git/modules/ext/AFNetworking
git add .gitmodules
git rm --cached AFNetworking
git submodule add -f <url> ext/AFNetworking
- 编辑 .gitmodules 将子模块名称和路径更改为“ext/AFNetworking”
- 将子模块的 git 目录从“.git/modules/AFNetworking”移动到“.git/modules/ext/AFNetworking”
- 将库从“AFNetworking”移动到“ext/AFNetworking”
- 编辑“.git/modules/ext/AFNetworking/config”并修复该
[core] worktree
行。我的从../../../AFNetworking
变成../../../../ext/AFNetworking
- 编辑“ext/AFNetworking/.git”并修复
gitdir
. 我的从../.git/modules/AFNetworking
变成../../git/modules/ext/AFNetworking
git add .gitmodules
git rm --cached AFNetworking
git submodule add -f <url> ext/AFNetworking
Finally, I saw in the git status:
最后在git status中看到:
matt$ git status
# On branch ios-master
# Changes to be committed:
# (use "git reset HEAD <file>..." to unstage)
#
# modified: .gitmodules
# renamed: AFNetworking -> ext/AFNetworking
Et voila. The above example doesn't change the directory depth, which makes a big difference to the complexity of the task, and doesn't change the name of the submodule (which may not really be necessary, but I did it to be consistent with what would happen if I added a new module at that path.)
等等。上面的例子并没有改变目录深度,这对任务的复杂性有很大的不同,并且没有改变子模块的名称(这可能不是真正必要的,但我这样做是为了与什么一致如果我在该路径上添加了一个新模块,就会发生这种情况。)
回答by Mark Mikofski
[Update: 2014-11-26] As Yarsummarizes nicely below, before you do anything, make sure you know the URL of the submodule.If unknown, open .git/.gitmodules
and examine the keysubmodule.<name>.url
.
[更新:2014-11-26] 正如Yar在下面很好地总结的那样,在你做任何事情之前,确保你知道子模块的 URL。如果未知,打开.git/.gitmodules
并检查密钥submodule.<name>.url
。
What worked for me was to remove the old submoduleusing git submodule deinit <submodule>
followed by git rm <submodule-folder>
. Then add the submodule again with the new folder name and commit. Checking git status before committing shows the old submodule renamed to the new name and .gitmodule modified.
对我有用的是使用git submodule deinit <submodule>
后跟删除旧的子模块git rm <submodule-folder>
。然后使用新文件夹名称再次添加子模块并提交。在提交之前检查 git status 会显示旧的子模块重命名为新名称,并且 .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"
回答by Paul Gideon Dann
The trick seems to be understanding that the .git
directory for submodules are now kept in the master repository, under .git/modules
, and each submodule has a .git
file that points to it. This is the procedure you need now:
诀窍似乎是理解.git
子模块的目录现在保存在主存储库中,在 下.git/modules
,并且每个子模块都有一个.git
指向它的文件。这是您现在需要的程序:
- Move the submodule to its new home.
- Edit the
.git
file in the submodule's working directory, and modify the path it contains so that it points to the right directory in the master repository's.git/modules
directory. - Enter the master repository's
.git/modules
directory, and find the directory corresponding to your submodule. - Edit the
config
file, updating theworktree
path so that it points to the new location of the submodule's working directory. - Edit the
.gitmodules
file in the root of the master repository, updating the path to the working directory of the submodule. git add -u
git add <parent-of-new-submodule-directory>
(It's important that you add the parent, and not the submodule directory itself.)
- 将子模块移动到它的新家。
- 编辑
.git
子模块工作目录中的文件,并修改它包含的路径,使其指向主存储库目录中的正确.git/modules
目录。 - 进入主仓库的
.git/modules
目录,找到你的子模块对应的目录。 - 编辑
config
文件,更新worktree
路径,使其指向子模块工作目录的新位置。 - 编辑
.gitmodules
主存储库根目录中的文件,更新子模块工作目录的路径。 git add -u
git add <parent-of-new-submodule-directory>
(重要的是添加parent,而不是子模块目录本身。)
A few notes:
一些注意事项:
- The
[submodule "submodule-name"]
lines in.gitmodules
and.git/config
must match each other, but don't correspond to anything else. - The submodule working directory and
.git
directory must correctly point to each other. - The
.gitmodules
and.git/config
files should be synchronised.
- 在
[submodule "submodule-name"]
以行.gitmodules
和.git/config
必须相互匹配,但不符合任何东西。 - 子模块工作目录和
.git
目录必须正确指向彼此。 - 在
.gitmodules
和.git/config
文件应该是同步的。
回答by Lance Rushing
You can just add a new submodule and remove the old submodule using standard commands. (should prevent any accidental errors inside of .git)
您可以使用标准命令添加新的子模块并删除旧的子模块。(应该防止 .git 中的任何意外错误)
Example setup:
示例设置:
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>
Examle move 'jquery' to 'vendor/jquery/jquery' :
示例将 '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}"
Bonus method for large submodules:
大型子模块的奖励方法:
If the submodule is large and you prefer not to wait for the clone, you can create the new submodule using the old as origin, and then switch the origin.
如果子模块很大并且不想等待克隆,则可以使用旧的作为原点创建新的子模块,然后切换原点。
Example (use same example setup)
示例(使用相同的示例设置)
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
...
回答by Bob Bell
The string in quotes after "[submodule" doesn't matter. You can change it to "foobar" if you want. It's used to find the matching entry in ".git/config".
"[submodule" 后引号中的字符串无关紧要。如果需要,您可以将其更改为“foobar”。它用于在“.git/config”中查找匹配的条目。
Therefore, if you make the change before you run "git submodule init", it'll work fine. If you make the change (or pick up the change through a merge), you'll need to either manually edit .git/config or run "git submodule init" again. If you do the latter, you'll be left with a harmless "stranded" entry with the old name in .git/config.
因此,如果您在运行“git submodule init”之前进行更改,它将正常工作。如果您进行更改(或通过合并获取更改),您将需要手动编辑 .git/config 或再次运行“git submodule init”。如果您选择后者,您将在 .git/config 中留下一个带有旧名称的无害“搁浅”条目。
回答by arand
The given solution did not work for me, however a similar version did...
给定的解决方案对我不起作用,但是类似的版本确实...
This is with a cloned repository, hence the submodule git repos are contained in the top repositories .git dir. All cations are from the top repository:
这是一个克隆的存储库,因此子模块 git repos 包含在顶级存储库 .git 目录中。所有阳离子都来自顶级存储库:
Edit .gitmodules and change the "path =" setting for the submodule in question. (No need to change the label, nor to add this file to index.)
Edit .git/modules/name/config and change the "worktree =" setting for the submodule in question
run:
mv submodule newpath/submodule git add -u git add newpath/submodule
编辑 .gitmodules 并更改相关子模块的“path =”设置。(无需更改标签,也无需将此文件添加到索引。)
编辑 .git/modules/name/config 并更改相关子模块的“worktree =”设置
跑:
mv submodule newpath/submodule git add -u git add newpath/submodule
I wonder if it makes a difference if the repositories are atomic, or relative submodules, in my case it was relative (submodule/.git is a ref back to topproject/.git/modules/submodule)
我想知道如果存储库是原子的还是相对的子模块,在我的情况下它是相对的(submodule/.git 是对 topproject/.git/modules/submodule 的引用)
回答by Flimm
Just use the shell script git-submodule-move.
只需使用 shell 脚本git-submodule-move。
回答by Dan Rosenstark
I just went through this ordeal yesterday and this answerworked perfectly. Here are my steps, for clarity:
我昨天刚刚经历了这场磨难,这个答案非常有效。为了清楚起见,这是我的步骤:
- Ensure that submodule is checked in and pushed to its server. You also need to know what branch its on.
- You need the URL of your submodule!Use
more .gitmodules
because once you delete the submodule it's not going to be around - Now you can use
deinit
,rm
and thensubmodule add
- 确保子模块已签入并推送到其服务器。您还需要知道它位于哪个分支。
- 您需要子模块的 URL!使用,
more .gitmodules
因为一旦你删除了子模块,它就不会存在了 - 现在您可以使用
deinit
,rm
然后submodule add
EXAMPLE
例子
- Git submodule is in: Classes/lib/mustIReally
- Moving to: lib/AudioBus
- URL: http://developer.audiob.us/download/SDK.git
- Git 子模块位于:Classes/lib/mustIReally
- 移动到:lib/AudioBus
- 网址:http: //developer.audiob.us/download/SDK.git
COMMANDS
命令
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
NOTE:git mv doesn't do this. At all.
注意:git mv 不会这样做。在所有。