作为detach-subdirectory之前已经提出的问题的一个子集,并考虑到这样一个事实,即尽管有很多关于拆分和合并git存储库的过程的问题,但我找不到触及该主题的问题。当子模块存在时分裂。
所以在以下场景中:
.git/
.gitmodules
folder/
data/
content/
other_data/
submoduleA/
submoduleB/
我想获得两个具有以下结构的存储库:
.git/
data/
和
.git/
.gitmodules
content/
other_data/
submoduleA/
submoduleB/
第一种情况不是问题,可以使用detach-subdirectory中描述的方法轻松解决。
第二个不是那么多。子模块的存在以及.gitmodules包含folder/content/submoduleA
和folder/content/submoduleB
的完整路径这一事实导致部分历史记录不一致,因为.gitmodules引用了一个不存在的目录结构(一旦使用了filter-branch) )。
所以我想知道是否有办法在不造成历史不一致的情况下做到这一点。
答案 0 :(得分:6)
我遇到与Unode完全相同的问题,并设法使用以下过程解决它:
git clone git@github.com:kdeldycke/kev-code.git
cd kev-code
git filter-branch --tree-filter "test -f ./.gitmodules && mv ./.gitmodules ./cool-cavemen/gitmodules || echo 'No .gitmodules file found'" -- --all
git filter-branch --force --prune-empty --subdirectory-filter cool-cavemen --tag-name-filter cat -- --all init..HEAD
git filter-branch --force --tree-filter "test -f ./gitmodules && mv ./gitmodules ./.gitmodules || echo 'No gitmodules file found'" -- --all
git filter-branch --force --tree-filter "test -f ./.gitmodules && sed -i 's/cool-cavemen\///g' ./.gitmodules || echo 'No .gitmodules file found'" -- --all
git remote rm origin
rm -rf .git/refs/original/
git reflog expire --all
git gc --aggressive --prune
git remote add origin git@github.com:kdeldycke/cool-cavemen.git
git push -u origin master --force --tags
如您所见,诀窍是暂时重命名.gitmodules
文件并使用sed
重写其内容。您可以获取所有详细信息和context of this procedure on my blog。
答案 1 :(得分:1)
我怀疑(未经测试)第二个git filter-branch
将有机会修改新回购的每个提交的.gitmodules
内容。
但实际上是git submodule split
command was in discussion early 2009。
建议用法:
git submodule split [--url submodule_repo_url] submodule_dir \
[alternate_dir...]
将
submodule_dir
替换为新创建的子模块,保留submodule_dir
的所有历史记录。
此命令还会重写当前存储库历史记录中的每个提交,以包含正确的sumodule_dir
版本和相应的.gitmodules
条目。
但是,我在latest what's cooking中没有看到它
建议的补丁中的脚本可以让您了解更新.gitmodules
文件所需的树重写类型。
答案 2 :(得分:0)
详细说明Kevin的答案:假设cool/cavemen
以外没有子模块 - 正在分离的文件夹(否则需要更精细的编辑.gitmodules来删除那些额外的部分),这可以使用index-filter
:
$ git filter-branch --subdirectory-filter cool/cavemen --index-filter $'
hash=$(git rev-parse --verify $GIT_COMMIT:.gitmodules 2>/dev/null) &&
git update-index --add --cacheinfo 100644 $(git cat-file -p $hash |
sed \'s/cool\\/cavemen\\///g\' | git hash-object -w --stdin) .gitmodules ||
true' --tag-name-filter cat --prune-empty -- --all
另外一个好处是,如果每个修订或分支中都不存在cool/cavemen
,则只会查看包含cool/cavemen
的修订或分支。
如果是这种情况,您可能需要运行以下命令来删除未更改的引用:
$ git for-each-ref --format='%(refname)' |
grep -vF "$(git for-each-ref --format='%(refname)' refs/original |
sed 's/refs\/original\///g')" | xargs -n 1 git update-ref -d