我有以下git结构
- git-repo a
-- subdirectory 2015
--- git-submodule b
-- git-submodule c
--- git-submodule d
我想将git子模块c移动到文件夹2015。 我知道这样做的“脏方法”(涉及修改.git / config和更改.git / modules文件中几个文件中的gitdir)
我最近读到git mv应该能够做到这一点,即运行
git mv c 2015/
这适用于没有嵌套子模块的存储库(在我的例子中为d)。但是,当我在我的目录上运行此命令时,我收到的错误如
fatal: Not a git repository: d/../../.git/modules/c/modules/d
fatal: 'git status --porcelain' failed in submodule 2015/c
(注意,执行上述移动后,git状态会出现此错误)
是否有人知道这种移动的干净方法(即,不涉及手动更改.git / modules文件中的路径的方法)?
编辑:(6/10/2015)
我目前最好的解决方案是不涉及对任何git配置文件的修改(首先要确保对d的所有更改都已提交并推送到某处)
rm c/d -rf
git mv c 2015
cd 2015/c
git submodule update
编辑:(8/10/2015)
更具侵入性的解决方法
git mv c 2015
rm 2015/c/d/.git
cd 2015/c
git submodule update
编辑:(21/9/2018)
自git 2.19以来。这已得到修复,git mv
的行为符合预期。
答案 0 :(得分:6)
更新2018年第二季度和Git 2.18:
移动一个子模块,其中子模块中包含“git mv
”,忘记对嵌套的子子模块进行必要的调整;
现在代码路径学会了递归到子模块。
commit 6856077见Jonathan Tan (jhowtan
)(2018年3月28日)
commit da62f78见commit 0c89fdd,commit 3b8fb39,commit f793b89,commit 61aad92,Stefan Beller (stefanbeller
)(2018年3月28日)。
(由Junio C Hamano -- gitster
--合并于commit 0c7ecb7,2018年5月8日)
子模块:移动子模块后修复嵌套子模块
由于子模块本身可以嵌套子模块,因此我们还要在需要时修复嵌套的子模块。添加一个选项以递归到嵌套的子模块中并连接它们。
子模块由其名称标识(确定它们的git 内部与其超级项目的git目录相关的目录 通过他们在超级项目工作树中的路径,我们需要 确保
name <-> path
的映射保持不变。我们可以做的 在git-mv
命令中首先写出.gitmodules
文件 然后强制重新加载子模块配置机制。
2017年第四季度更新:
最新的Git 2.14.x / 2.15(2017年第4季度)记录了该错误
commit c514167见Heiko Voigt (hvoigt
)(2017年9月15日)
(Junio C Hamano -- gitster
--合并于commit 450b908,2017年9月25日)
将
git-mv
与子模块一起使用时,它会检测到并更新 其配置的路径(.gitmodules
,worktree和gitfile) 这不适用于用户重命名根的递归子模块 子模块。强>
2015年原始答案
我刚用git 2.6.0(在Windows上)测试过它,移动带有自己嵌套子模块的子模块似乎有问题:
C:\Users\vonc\prog\git\tests\submove>git clone --recursive a a1
Cloning into 'a1'...
done.
Submodule '2015/b' (C:/Users/vonc/prog/git/tests/submove/b) registered for path '2015/b'
Submodule 'c' (C:/Users/vonc/prog/git/tests/submove/c) registered for path 'c'
Cloning into '2015/b'...
done.
Submodule path '2015/b': checked out 'dc18955ec7b9ad0c04245968e2474646e4d593b2'
Cloning into 'c'...
done.
Submodule path 'c': checked out 'fb4722eaca17ac171b7a2c8c5a1ac1e697f0ee85'
Submodule 'd' (C:/Users/vonc/prog/git/tests/submove/d) registered for path 'd'
Cloning into 'd'...
done.
Submodule path 'c/d': checked out '73cd7b8ff82519720b2fcca18df5ed00dd618b71'
我有:
a1
c
d
2015
b
如果我尝试在2015子文件夹中移动子模块c
:
C:\Users\vonc\prog\git\tests\submove\a1>git mv c 2015/c
C:\Users\vonc\prog\git\tests\submove\a1>git status
fatal: Not a git repository: d/../../.git/modules/c/modules/d
fatal: 'git status --porcelain' failed in submodule 2015/c
我发现我需要修改嵌套模块中的两件事d
:
1 /手动修改.git/modules/c/modules/d/config
以注入正确的路径:
git config -f .git/modules/c/modules/d/config core.worktree ../../../../../2015/c/d
^^^^
2 /修改d
工作树:
git config -f .git/modules/c/modules/d/config core.worktree ../../../../../2015/c/d
从那里,git status
有效,但我喜欢(确定)添加git submodule sync --recursive
:
C:\Users\vonc\prog\git\tests\submove\a1>git submodule sync --recursive
Synchronizing submodule url for '2015/b'
Synchronizing submodule url for '2015/c'
Synchronizing submodule url for '2015/c/d'
git status
确实显示了预期的结果:
C:\Users\vonc\prog\git\tests\submove\a1>git status
On branch master
Your branch is up-to-date with 'origin/master'.
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
modified: .gitmodules
renamed: c -> 2015/c
我添加并提交更改:
C:\Users\vonc\prog\git\tests\submove\a1>git add .
C:\Users\vonc\prog\git\tests\submove\a1>git commit -m "move sub c in 2015/c"
[master 8289632] move sub c in 2015/c
2 files changed, 1 insertion(+), 1 deletion(-)
rename c => 2015/c (100%)
C:\Users\vonc\prog\git\tests\submove\a1>gl
* 8289632 - (HEAD -> master) move sub c in 2015/c (3 seconds ago) <VonC>
* 7ebb8e0 - (origin/master, origin/HEAD) a with sub c (38 minutes ago) <VonC>
我现在克隆那个回购以检查移动确实已正确注册:
C:\Users\vonc\prog\git\tests\submove>git clone --recursive a1 a2
Cloning into 'a2'...
done.
Submodule '2015/b' (C:/Users/vonc/prog/git/tests/submove/b) registered for path '2015/b'
Submodule 'c' (C:/Users/vonc/prog/git/tests/submove/c) registered for path '2015/c'
Cloning into '2015/b'...
done.
Submodule path '2015/b': checked out 'dc18955ec7b9ad0c04245968e2474646e4d593b2'
Cloning into '2015/c'...
done.
Submodule path '2015/c': checked out 'fb4722eaca17ac171b7a2c8c5a1ac1e697f0ee85'
Submodule 'd' (C:/Users/vonc/prog/git/tests/submove/d) registered for path 'd'
Cloning into 'd'...
done.
Submodule path '2015/c/d': checked out '73cd7b8ff82519720b2fcca18df5ed00dd618b71'
如您所见,c
和c/d
位于预期的2015/
子文件夹中:
C:\Users\vonc\prog\git\tests\submove>cd a2
C:\Users\vonc\prog\git\tests\submove\a2>dir 2015\c
Directory of C:\Users\vonc\prog\git\tests\submove\a2\2015\c
03/10/2015 18:10 <DIR> .
03/10/2015 18:10 <DIR> ..
03/10/2015 18:10 29 .git
03/10/2015 18:10 40 .gitmodules
03/10/2015 18:10 <DIR> d
2 File(s) 69 bytes
3 Dir(s) 23 656 910 848 bytes free
C:\Users\vonc\prog\git\tests\submove\a2>dir 2015\c\d
Directory of C:\Users\vonc\prog\git\tests\submove\a2\2015\c\d
03/10/2015 18:10 <DIR> .
03/10/2015 18:10 <DIR> ..
03/10/2015 18:10 42 .git
03/10/2015 18:10 3 d.txt
2 File(s) 45 bytes
2 Dir(s) 23 656 910 848 bytes free
答案 1 :(得分:4)
正如https://stackoverflow.com/a/32924692/2274140中的@VonC所证实的,这是git mv中的一个错误。
有几种可能的解决方法。最简单的一个不需要对.git文件进行复杂的修改(自从提出问题以来,我一直在使用这个)。它的工作原理如下:
git mv c 2015
rm 2015/c/d/.git
cd 2015/c
git submodule update
它暂时删除d
子子模块中的.git文件。然后git子模块更新再次修复此.git文件。
对于避免临时删除gitdir的其他解决方法,请参阅以下答案:https://stackoverflow.com/a/32924692/2274140