在git中合并子树合并和稀疏检出

ddarikpa  于 2023-09-29  发布在  Git
关注(0)|答案(5)|浏览(103)

bounty还有3天到期。回答此问题可获得+500声望奖励。Dani Mesejo希望引起更多的注意这个问题。

我正在尝试在git中模拟svn:externals。在项目'A'中,我需要将库'B'下拉到'A'的子文件夹中。A和B都是独立的git仓库。我知道我可以用子模块或子树合并来完成。然而,为了使事情更加复杂,我需要将'B'的子文件夹拉到'A'中,而不是整个项目,因为它是一个我需要直接导入的python模块,我不能在那里拥有根目录结构,或者它不能被导入。
这很容易用svn:externals实现.对于git来说,这似乎很复杂,甚至是不可能的。
下面是一个示例:
项目B:

-B
  - src
    __init__.py
 - test
   ...

项目A:

- A
   - src
     A.py (imports B)
     - B (partial check of sub folder 'src' as name 'B')
        __init__.py
   - test
     ...
ssgvzors

ssgvzors1#

Git通常是全有或全无。最好的办法是将模块克隆到其他地方,然后符号链接到所需的目录,或者使用sys.path

- A
   - src
      - B symlink to ../../B/
- B

如果你关心子模块的克隆的大小,并且你不需要提交它,那么你可以在克隆时使用--depth=1来忽略历史。
不幸的是,您不能克隆子文件夹。最多可以使用git-filter-branch从存储库中删除除选定子文件夹之外的所有内容。

yx2lnoni

yx2lnoni2#

与其通过调整git来解决这个问题,为什么不直接在任何地方安装B,并告诉A在哪里找到要包含的子模块呢?如果您只是将包含相关B子模块的文件夹添加到sys.path,则可以回家。

qnyhuwrf

qnyhuwrf3#

我认为用子树合并来合并子模块会更好,所以首先将project B作为子模块添加到project A中,因为这样会将project B作为子模块添加到A/B目录中!

cd A
git submodule add <URL to project B>

现在执行子树合并,只将project B的所需子文件夹包含到project A

git remote add -f B <URL to project B>
git merge -s ours --no-commit B/master
git read-tree --prefix=A/B/ -u B/master:<path to subfolder>
git commit -m "Merge subfolder from project B into project A"

现在,您可以轻松地将子模块更新为project A中所需的提交

git submodule update --remote

你也可以通过一个简单的Python脚本来实现这一点,让我向你展示如何:

import subprocess

def add_submodule_and_merge(url_to_project_b, path_to_subfolder):
    #step 1:adding project B as a submodule to project A
    subprocess.run(['git', 'submodule', 'add', url_to_project_b, 'A/B'])
    
    #step 2:perform a subtree merge to include the desired subfolder of project B into project A
    subprocess.run(['git', 'remote', 'add', '-f', 'B', url_to_project_b])
    subprocess.run(['git', 'merge', '-s', 'ours', '--no-commit', 'B/master'])
    subprocess.run(['git', 'read-tree', '--prefix=A/B/', '-u', 'B/master:' + path_to_subfolder])
    subprocess.run(['git', 'commit', '-m', 'Merge subfolder from project B into project A'])
    
    #step 3:update the submodule to the desired commit in project A
    subprocess.run(['git', 'submodule', 'update', '--remote'])

#for example you can use it like this :
url_to_project_b = '<URL to project B>'
path_to_subfolder = '<path to subfolder in project B>'
add_submodule_and_merge(url_to_project_b, path_to_subfolder)

祝你好运!

6rvt4ljy

6rvt4ljy4#

在git中没有内置的方法来做到这一点,你可以通过两个步骤来做到这一点:
1.在存储库B中,您可以“挤出”src/目录的历史记录:

git checkout master

# switch to a new branch that will contain this "sub history" 
git checkout -b src-master

git filter-repo --subdirectory-filter src/

1.从repo A,你现在可以使用git subtree ...来包含来自repo B的分支src-master
git filter-repo --subdirectory-filter ...将以可重复的方式运行:
如果稍后B得到更新,则在更新的master分支上运行git filter-repo --subdirectory-filter ...将导致更新src-master分支的历史。所以你将能够看到添加了什么提交,git mergegit rebase将从预期的合并基数开始,等等。。

6ojccjat

6ojccjat5#

B(库)必须也是超模块,其中包括子模块“python模块”
您选择了错误的工具,并离开了更高的抽象层,比任务所需的

相关问题