Git子树和多个目录

时间:2014-02-07 06:51:02

标签: git git-subtree

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

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

现在让我们假设我想要打开源子目录A,...,M并保持子目录N,...,Z的源代码。我们还假设我想:

  • 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的任何其他指示有任何解决方案,请告知我们。

4 个答案:

答案 0 :(得分: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. 最后,只需为库创建一个新的仓库并拉入剩下的所有内容:

    cd <new-lib-repo>
    git init
    git pull <original-repo> temp-br
    

答案 1 :(得分:1)

这是一个基于git subtree的shell脚本,它比基于git filter-branch --tree-filter的解决方案要快得多;它的副作用是会产生多个额外的git mv,并且将生成git 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`

答案 2 :(得分:0)

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

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

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

新回购: srcpublic - file2,dir2

原始回购: src - file1,file2,   dir1,dir2

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

答案 3 :(得分:0)

使用lldb

请参见Git subtree split two directories,我认为您可以将该技术用于两个以上的目录,即使对于多个存储库也是如此。

(gdb) call malloc_stats()