如何取消Git子模块的子模块?

如何取消Git子模块的子模块?,git,git-submodules,Git,Git Submodules,取消Git子模块的子模块化,将所有代码带回核心存储库的最佳实践是什么 git-rm——缓存子模块路径 从.gitmodules文件中删除子模块部分,或者如果它是唯一的子模块,则删除该文件 执行提交“已删除的子模块xyz” git添加子模块路径 另一个提交“添加了xyz的代码库” 我还没有找到更容易的办法。您可以通过git commit将3-5压缩为一个步骤,这取决于您的品味。如果您只想将子模块代码放入主存储库,只需删除子模块并将文件重新添加到主repo: git rm --cached subm

取消Git子模块的子模块化,将所有代码带回核心存储库的最佳实践是什么

  • git-rm——缓存子模块路径
  • .gitmodules
    文件中删除子模块部分,或者如果它是唯一的子模块,则删除该文件
  • 执行提交“已删除的子模块xyz”
  • git添加子模块路径
  • 另一个提交“添加了xyz的代码库”

  • 我还没有找到更容易的办法。您可以通过git commit将3-5压缩为一个步骤,这取决于您的品味。

    如果您只想将子模块代码放入主存储库,只需删除子模块并将文件重新添加到主repo:

    git rm --cached submodule_path # delete reference to submodule HEAD (no trailing slash)
    git rm .gitmodules             # if you have more than one submodules,
                                   # you need to edit this file instead of deleting!
    rm -rf submodule_path/.git     # make sure you have backup!!
    git add submodule_path         # will add files instead of commit reference
    git commit -m "remove submodule"
    
    如果您还想保留子模块的历史记录,可以执行一个小技巧:“合并”子模块到主存储库中,这样结果将与以前相同,只是子模块文件现在位于主存储库中

    在主模块中,您需要执行以下操作:

    # Fetch the submodule commits into the main repository
    git remote add submodule_origin git://url/to/submodule/origin
    git fetch submodule_origin
    
    # Start a fake merge (won't change any files, won't commit anything)
    git merge -s ours --no-commit submodule_origin/master
    
    # Do the same as in the first solution
    git rm --cached submodule_path # delete reference to submodule HEAD
    git rm .gitmodules             # if you have more than one submodules,
                                   # you need to edit this file instead of deleting!
    rm -rf submodule_path/.git     # make sure you have backup!!
    git add submodule_path         # will add files instead of commit reference
    
    # Commit and cleanup
    git commit -m "removed submodule"
    git remote rm submodule_origin
    
    生成的存储库看起来有点奇怪:将有多个初始提交。但它不会给Git带来任何问题


    第二种解决方案的一大优点是,您仍然可以对最初位于子模块中的文件运行
    git-dull
    git-log
    。事实上,这里发生的只是一个存储库中许多文件的重命名,Git应该会自动检测到这一点。如果您在git日志方面仍然存在问题,请尝试一些选项(例如,
    -follow
    -M
    -C
    ),这些选项可以更好地进行重命名和复制检测。

    我们碰巧为两个项目创建了两个存储库,它们耦合得太多,无法将它们分开,因此我们将它们合并

    首先,我将展示如何在每个分支中合并主分支,然后我将解释如何将其扩展到每个分支,希望它对您有所帮助

    如果子模块正常工作,并且希望将其转换为适当的目录,则可以执行以下操作:

    git clone project_uri project_name
    
    在这里,我们做一个干净的克隆工作。对于这个过程,您不需要初始化或更新子模块,所以只需跳过它

    cd project_name
    vim .gitmodules
    
    使用您喜爱的编辑器(或Vim)编辑
    .gitmodules
    ,以删除您计划替换的子模块。需要删除的行应如下所示:

    [submodule "lib/asi-http-request"]
        path = lib/asi-http-request
        url = https://github.com/pokeb/asi-http-request.git
    
    保存文件后

    git rm --cached directory_of_submodule
    git commit -am "Removed submodule_name as submodule"
    rm -rf directory_of_submodule
    
    在这里,我们完全删除了子模块关系,这样我们就可以创建另一个回购协议,并将其带到项目中

    git remote add -f submodule_origin submodule_uri
    git fetch submodel_origin/master
    
    这里我们获取要合并的子模块存储库

    git merge -s ours --no-commit submodule_origin/master
    
    在这里,我们开始两个存储库的合并操作,但在提交之前停止

    git read-tree --prefix=directory_of_submodule/ -u submodule_origin/master
    
    在这里,我们将子模块中master的内容发送到其所在的目录中,然后再作为目录名的前缀

    git commit -am "submodule_name is now part of main project"
    
    在这里,我们完成在合并中提交更改的过程

    完成此操作后,您可以推送并重新开始任何其他要合并的分支,只需签出存储库中将接收更改的分支,并更改您在合并和读取树操作中引入的分支。

    何时

    git rm [-r] --cached submodule_path
    
    返回

    fatal: pathspec 'emr/normalizers/' did not match any files
    

    上下文:我在我的子模块文件夹中做了
    rm-r.git*
    ,然后才意识到它们需要在我刚刚添加它们的主项目中被分解。我在对一些(但不是全部)子模块化时得到了上述错误。无论如何,我通过运行(当然是在
    rm-r.git*
    之后)修复了它们


    请注意,这不会保留历史记录。

    我发现从子模块获取本地提交数据(也?)更方便,因为否则我会丢失它们。(无法推送它们,因为我无法访问该遥控器)。所以我添加了子模块/.git作为remote_origin2,获取它并从该分支合并。 不确定我是否仍然需要子模块remote作为源,因为我对git还不够熟悉。

    因为)(不保留子模块的历史记录):

    这将:

    • 取消注册并卸载子模块(
      deinit
      ,因此首先卸载
      mv
      ),即删除子模块的内容
    • 为您清理
      .gitmodules
      rm
    • 并删除在父回购协议索引中表示该子模块SHA1的标记(
      rm
    一旦子模块的删除完成(
    deinit
    git rm
    ),您可以将文件夹重命名回其原始名称,并将其作为常规文件夹添加到git repo中

    注意:如果子模块是由旧Git(<1.8)创建的,则可能需要删除子模块本身中嵌套的
    .Git
    文件夹,如



    如果您需要保留子模块的历史记录,请参见使用
    git过滤器分支的's

    这里是@gyim答案的一个稍微改进的版本(IMHO)。他在主工作副本中做了一系列危险的更改,我认为在不同的克隆上进行操作,然后在最后将它们合并在一起更容易

    在一个单独的目录中(为了使错误更容易清理并重试),检查顶部回购和子回购

    git clone ../main_repo main.tmp
    git clone ../main_repo/sub_repo sub.tmp
    
    首先编辑子repo,将所有文件移动到所需的子目录中

    cd sub.tmp
    mkdir sub_repo_path
    git mv `ls | grep -v sub_repo_path` sub_repo_path/
    git commit -m "Moved entire subrepo into sub_repo_path"
    
    记下头部

    SUBREPO_HEAD=`git reflog | awk '{ print $1; exit; }'`
    
    现在从主回购中删除子回购

    cd ../main.tmp
    rmdir sub_repo_path
    vi .gitmodules  # remove config for submodule
    git add -A
    git commit -m "Removed submodule sub_repo_path in preparation for merge"
    
    最后,合并它们

    git fetch ../sub.tmp
    # remove --allow-unrelated-histories if using git older than 2.9.0
    git merge --allow-unrelated-histories $SUBREPO_HEAD
    

    完成了!安全且没有任何魔法。

    我找到的最好答案是:


    这篇文章很好地解释了这一过程。

    这里有很多答案,但它们似乎都过于复杂,很可能不符合您的要求。我相信大多数人都想保留他们的历史

    在本例中,主要回购协议为
    git@site.com:main/main.git
    ,子模块回购将
    git@site.com:main/child.git
    。这假设子模块位于p的根目录中
    cd ../main.tmp
    rmdir sub_repo_path
    vi .gitmodules  # remove config for submodule
    git add -A
    git commit -m "Removed submodule sub_repo_path in preparation for merge"
    
    git fetch ../sub.tmp
    # remove --allow-unrelated-histories if using git older than 2.9.0
    git merge --allow-unrelated-histories $SUBREPO_HEAD
    
    git clone git@site.com:main/main.git
    git submodule deinit child
    git rm child
    git add --all
    git commit -m "remove child submodule"
    
    git remote add upstream git@site.com:main/child.git
    git fetch upstream
    git checkout -b merge-prep upstream/master
    
    mkdir child
    
    git add --all
    git commit -m "merge prep"
    
    git checkout master
    git merge merge-prep # --allow-unrelated-histories merge-prep flag may be required 
    
    #!/usr/bin/env bash
    mv "$1" "${1}_"
    git submodule deinit "$1"
    git rm "$1"
    mv "${1}_" "$1"
    git add "$1/**"
    
    $ git-submodule-rewrite <submodule-name>