简体   繁体   English

Git子树和多个目录

[英]Git subtree and multiple directories

I have a rather large git repository that has a directory where I maintain library code. 我有一个相当大的git存储库,它有一个我维护库代码的目录。 The directory contains a number of subdirectories. 该目录包含许多子目录。

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

Now let us assume that I want to open source subdirectories A,...,M and keep subdirectories N,...,Z close sourced. 现在让我们假设我想开源子目录A,...,M并保持子目录N,...,Z关闭源代码。 Let us also assume that I would like to: 我们还假设我想:

  • Keep A,...,M in a single open source repository. A,...,M在一个开源存储库中。 The reason for this is that the directories A,...,M have interdependencies and it would be confusing to split them into individual repositories. 这样做的原因是目录A,...,M具有相互依赖性,将它们分成单独的存储库会很困惑。
  • Keep the structure of my closed source repository intact. 保持我的封闭源存储库的结构不变。 For example, I could create subdirectories lib/pub and lib/pvt , but this would have cascading effects requiring changing references elsewhere or would require a lot of symlinks ( lib/A -> lib/pub/A ). 例如,我可以创建子目录lib/publib/pvt ,但这会产生级联效果,需要在其他地方更改引用,或者需要很多符号链接( lib/A -> lib/pub/A )。
  • Have a solution akin to git subtree where I can modify code either in my closed source repository or in the open source one and I can easily sync the changes between the two repositories. 有一个类似于git subtree的解决方案,我可以在我的封闭源代码库或开源代码库中修改代码,我可以轻松地同步两个存储库之间的更改。

I have searched for a solution in both stackoverflow and google, but there does not seem to be an obvious one. 我已经在stackoverflow和google中搜索了一个解决方案,但似乎没有明显的解决方案。 Conceptually this is something that git subtree should be able to do, but it only works with a single subdirectory. 从概念上讲,这是git subtree应该能够做到的事情,但它只适用于单个子目录。

I have looked into the git-subtree script with the intent of modifying it. 我已经查看了git-subtree脚本,目的是修改它。

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

It appears to me that if I was to modify subtree_for_commit() I should be able to convince git subtree split to consider more than a single directory for splitting. 在我看来,如果我要修改subtree_for_commit()我应该能够说服git subtree split考虑多个单独的目录进行拆分。 But my knowledge of git is not enough to understand what the script is doing and modify it without breaking things. 但是我对git的了解还不足以理解脚本正在做什么并在不破坏事情的情况下修改它。

If you have any solution for the above mentioned problem or any other pointers in modifying git-subtree , please let me know. 如果您对上述问题或任何其他修改git-subtree指针有任何解决方案,请告诉我。

Splitting a subtree mixed with files from the parent project 拆分与父项目中的文件混合的子树

This seems to be a common request, however I don't think there's a simple answer, when the folders are mixed together like that. 这似乎是一个常见的请求,但是当文件夹混合在一起时,我不认为有一个简单的答案。

The general method I suggest to split out the library mixed in with other folders is this: 我建议拆分与其他文件夹混合的库的一般方法是:

  1. Make a branch with the new root for the library directories: 使用库目录的新根创建分支:

     git subtree split -P lib/ -b temp-br git checkout temp-br 
  2. Then use something to re-write history to remove the parts that aren't part of the library. 然后使用某些东西重写历史记录以删除不属于库的部分。 I'm not expert on this but I was able to experiment and found something like this to work: 我不是这方面的专家,但我能够进行实验并发现这样的工作:

     git filter-branch --tag-name-filter cat --prune-empty --index-filter 'git rm -rf --cached --ignore-unmatch NOPQRSTUVWXYZ' HEAD 

    Note: You might need to delete the back-up made by filter-branch if you make successive commands. 注意:如果您执行连续命令,则可能需要删除filter-branch所做的备份。

     git update-ref -d refs/original/refs/heads/temp-br 
  3. Lastly, just create a new repo for the library and pull in everything that's left: 最后,只需为库创建一个新的repo并拉入剩下的所有内容:

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

Here is a shell script based on git subtree , it is much faster than solutions which are based on git filter-branch --tree-filter ; 这是一个基于git subtree的shell脚本,它比基于git filter-branch --tree-filter解决方案要快得多; its side effect is several extra git mv and git merge commits will be generated and added to final HEAD . 它的副作用是几个额外的git mv ,将生成git merge提交并添加到最终的HEAD If you feel ok of these extra empty commits, you can try: 如果您对这些额外的空提交感觉不错,可以尝试:

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`

When you have both subdirectories and files in a directory src you want to split into a separate repository that later becomes a submodule, there were not many answers. 当你在目录src中同时拥有子目录和文件时,你想要拆分成一个单独的存储库,后来成为一个子模块,答案就不多了。 Suppose you want dir2 and file2 moved to a new repo srcpublic then in the original repo, 假设您希望dir2和file2移动到新的repo srcpublic然后在原始仓库中,

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

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

New repo: srcpublic - file2, dir2 新的回购:srcpublic - file2,dir2

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

When there are dozens of folders and files, it helps to put the commands in a script. 当有许多文件夹和文件时,将命令放在脚本中会很有帮助。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM