Git子树和多个目录

问题描述 投票:9回答:3

我有一个相当大的git存储库,它有一个我维护库代码的目录。该目录包含许多子目录。

repo
+--- lib
|    +--- A
|    +--- B
...
|    +--- Z

现在让我们假设我想开源子目录A,...,M并保持子目录N,...,Z close sourced。我们还假设我想:

  • A,...,M保存在一个开源存储库中。原因是目录A,...,M具有相互依赖性,将它们分成单独的存储库会很困惑。
  • 保持我的封闭源存储库的结构不变。例如,我可以创建子目录lib/publib/pvt,但这会产生级联效果,需要在其他地方更改引用,或者需要大量的符号链接(lib/A -> lib/pub/A)。
  • 有一个类似于git subtree的解决方案,我可以在我的封闭源代码库或开源代码库中修改代码,我可以轻松地同步两个存储库之间的更改。

我已经在stackoverflow和google中搜索了一个解决方案,但似乎没有明显的解决方案。从概念上讲,这是git subtree应该能够做到的事情,但它只适用于单个子目录。

我已经查看了git-subtree脚本,目的是修改它。

https://github.com/git/git/blob/master/contrib/subtree/git-subtree.sh

在我看来,如果我要修改subtree_for_commit(),我应该能够说服git subtree split考虑不止一个目录进行拆分。但是我对git的了解还不足以理解脚本正在做什么并在不破坏事情的情况下修改它。

如果您对上述问题有任何解决方案或修改git-subtree的任何其他指示,请告诉我。

git git-subtree
3个回答
4
投票

拆分与父项目中的文件混合的子树

这似乎是一个常见的请求,但是当文件夹混合在一起时,我不认为有一个简单的答案。

我建议拆分与其他文件夹混合的库的一般方法是:

  1. 使用库目录的新根创建分支: git subtree split -P lib/ -b temp-br git checkout temp-br
  2. 然后使用某些东西重写历史记录以删除不属于库的部分。我不是这方面的专家,但我能够进行实验并发现这样的工作: git filter-branch --tag-name-filter cat --prune-empty --index-filter 'git rm -rf --cached --ignore-unmatch N O P Q R S T U V W X Y Z' HEAD 注意:如果您执行连续命令,则可能需要删除filter-branch所做的备份。 git update-ref -d refs/original/refs/heads/temp-br
  3. 最后,只需为库创建一个新的repo并拉入剩下的所有内容: cd <new-lib-repo> git init git pull <original-repo> temp-br

1
投票

这是一个基于git subtree的shell脚本,它比基于git filter-branch --tree-filter的解决方案快得多;它的副作用是几个额外的git mvgit merge提交将生成并添加到最终的HEAD。如果您对这些额外的空提交感觉不错,可以尝试:

ids=0
lists=(\
    "a/b" \
    "c/d/e" \
)
# subtree each path
for dir in ${lists[@]}
do
    echo git subtree split -P $dir -b split_dir_$ids
    git subtree split -P $dir -b split_dir_$ids
    ((ids++))
done

# restore folder structure
for (( idx=0; idx < ${#lists[@]}; idx++ ))
do
    git checkout split_dir_$idx
    dir=${lists[$idx]}
    mkdir -p $dir
    dirPrefix=${$dir%%/*}
    find . -maxdepth 1 ! -name $dirPrefix -and ! -name '\.*' \
        -exec git mv {} $dir \;
done

# merge
git checkout split_dir_0
for (( idx=1; idx < ${#lists[@]}; idx++ ))
do
    git merge -q split_dir_$idx
done

git push -u `target remote` `target branch`

0
投票

当你在目录src中同时拥有子目录和文件时,你想要拆分成一个单独的存储库,后来成为一个子模块,答案就不多了。假设您希望dir2和file2移动到新的repo srcpublic然后在原始仓库中,

git mv src / file2 src / dir2; git subtree split -P dir2 -b branch_dir2

在新的repo中,子树pull / dir2 branch_dir2; git mv dir2 / file2 ../

新的回购:srcpublic - file2,dir2

原始仓库:src - file1,file2,dir1,dir2

当有许多文件夹和文件时,将命令放在脚本中会很有帮助。

© www.soinside.com 2019 - 2024. All rights reserved.