如何取消子模块 Git 子模块?
取消子模块 Git 子模块、将所有代码带回核心存储库的最佳实践是什么?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
取消子模块 Git 子模块、将所有代码带回核心存储库的最佳实践是什么?
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
接受
或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
发布评论
评论(13)
如果您只想将子模块代码放入主存储库中,则只需删除子模块并将文件重新添加到主存储库中:
如果您还想保留子模块的历史记录,您可以做一个小操作技巧:将子模块“合并”到主存储库中,这样结果将与以前相同,只是子模块文件现在位于主存储库中。
在主模块中,您需要执行以下操作:
生成的存储库看起来有点奇怪:将有多个初始提交。但它不会给 Git 带来任何问题。
第二种解决方案的一大优点是,您仍然可以对最初位于子模块中的文件运行 git Blame 或 git log 。事实上,这里发生的只是一个存储库中许多文件的重命名,Git 应该自动检测到这一点。如果
git log
仍然存在问题,请尝试一些选项(例如--follow
、-M
、-C) 可以更好地进行重命名和复制检测。
If all you want is to put your submodule code into the main repository, you just need to remove the submodule and re-add the files into the main repo:
If you also want to preserve the history of the submodule, you can do a small trick: “merge” the submodule into the main repository, so that the result will be the same as it was before, except that the submodule files are now in the main repository.
In the main module you will need to do the following:
The resulting repository will look a bit weird: there will be more than one initial commit. But it won’t cause any problems for Git.
A big advantage of this second solution is that you can still run
git blame
orgit log
on the files which were originally in submodules. In fact, what happens here is just a renaming of many files inside one repository, and Git should automatically detect this. If you still have problems withgit log
, try some options (e.g.,--follow
,-M
,-C
) which do better rename and copy detection.我创建了一个脚本,它将子模块转换为简单的目录,同时保留所有文件历史记录。它不会遇到其他解决方案所遇到的 git log --follow 问题。这也是一个非常简单的单行调用,可以为您完成所有工作。祝你好运。
它建立在 Lucas Jenß 的出色工作之上,在他的博客文章“将子模块集成到父存储库中”,但会自动化整个过程并清理其他一些极端情况。
最新代码将在 github 上维护并修复错误,网址为 https:// github.com/jeremysears/scripts/blob/master/bin/git-submodule-rewrite,但为了正确的 stackoverflow 应答协议,我在下面包含了完整的解决方案。
用法:
git-submodule-rewrite:
I've created a script that will translate a submodule to a simple directory, while retaining all file history. It doesn't suffer from the
git log --follow <file>
issues that the other solutions suffer from. It's also a very easy one-line invocation that does all of the work for you. G'luck.It builds on the excellent work by Lucas Jenß, described in his blog post "Integrating a submodule into the parent repository", but automates the entire process and cleans up a few other corner cases.
The latest code will be maintained with bugfixes on github at https://github.com/jeremysears/scripts/blob/master/bin/git-submodule-rewrite, but for the sake of proper stackoverflow answer protocol, I've included the solution in its entirety below.
Usage:
git-submodule-rewrite:
自 git 1.8.5(2013 年 11 月)起(不保留历史记录submodule):
这将:
deinit
,因此mv
first),.gitmodules
(rm
),rm
)。子模块删除完成后(
deinit
和git rm
),您可以将该文件夹重命名回其原始名称,并将其作为常规文件夹添加到 git 存储库中。注意:如果子模块是由旧的 Git (< 1.8) 创建的,您可能需要删除子模块本身内嵌套的
.git
文件夹,如 评论由 Simon East如果您需要保留子模块的历史记录,请参阅 jsears 的 answer,它使用
git filter-branch
。Since git 1.8.5 (Nov 2013) (without keeping the history of the submodule):
That will:
deinit
, hence themv
first),.gitmodules
for you (rm
),rm
).Once the removal of the submodule is complete (
deinit
andgit rm
), you can rename the folder back to its original name and add it to the git repo as a regular folder.Note: if the submodule was created by an old Git (< 1.8), you might need to remove the nested
.git
folder within the submodule itself, as commented by Simon EastIf you need to keep the history of the submodule, see jsears's answer, which uses
git filter-branch
.git rm --cached the_submodule_path
.gitmodules
文件中删除子模块部分,或者如果它是唯一的子模块,则删除该文件。git add the_submodule_path
我还没有找到任何更简单的方法。您可以通过 git commit -a 来将 3-5 步压缩为一个步骤 - 这取决于您的喜好。
git rm --cached the_submodule_path
.gitmodules
file, or if it's the only submodule, remove the file.git add the_submodule_path
I didn't find any easier way yet. You can compress 3-5 into one step via
git commit -a
- matter of taste.这里有很多答案,但所有答案似乎都过于复杂,并且可能不符合您的要求。我相信大多数人都想保留自己的历史。
对于此示例,主存储库将为
[email protected]: main/main.git
和子模块存储库将是[email 受保护]:main/child.git
。这假设子模块位于父存储库的根目录中。根据需要调整说明。首先克隆父存储库并删除旧的子模块。
现在我们将把子存储库添加到主存储库的上游。
下一步假设您想要将 merge-prep 分支上的文件移动到与上面子模块相同的位置,尽管您可以通过更改文件路径轻松更改位置。
将除 .git 文件夹之外的所有文件夹和文件移动到子文件夹中。
现在您可以简单地将文件合并回主分支。
在运行 git push 之前环顾四周并确保一切看起来都很好
现在你必须记住的一件事是 git log 默认情况下不会跟随移动的文件,而是通过运行 git log --follow filename 您可以查看文件的完整历史记录。
Lots of answers here but all of them seem to be overly complex and likely do not do what you want. I am sure most people want to keep their history.
For this example the main repo will be
[email protected]:main/main.git
and the submodule repo will be[email protected]:main/child.git
. This assumes that the submodule is located in the root directory of the parent repo. Adjust the instructions as needed.Start by cloning the parent repo and removing the old submodule.
Now we will add the child repos upstream to the main repo.
The next step assumes that you want to move the files on the merge-prep branch into the same location as the submodule was above although you can easily change the location by changing the file path.
move all folders and files except the .git folder into the child folder.
Now you can simply merge your files back into the master branch.
Look around and make sure everything looks good before running
git push
The one thing you have to remember now is that git log does not by default follow moved files however by running
git log --follow filename
you can see the full history of your files.我们碰巧为 2 个项目创建了 2 个存储库,这两个项目耦合得非常紧密,将它们分开没有任何意义,因此我们将它们合并。
我将首先展示如何合并每个分支中的主分支,然后我将解释如何将其扩展到您获得的每个分支,希望它对您有所帮助。
如果您让子模块正常工作,并且想将其转换为适当的目录,您可以这样做:
这里我们进行一个干净的克隆来工作。对于此过程,您不需要初始化或更新子模块,因此只需跳过它。
使用您最喜欢的编辑器(或 Vim)编辑
.gitmodules
以删除您计划替换的子模块。您需要删除的行应如下所示:保存文件后,
这里我们完全删除子模块关系,以便我们可以将其他存储库就地创建到项目中。
这里我们获取要合并的子模块存储库。
这里我们开始对两个存储库进行合并操作,但在提交之前停止。
这里,我们将子模块中 master 的内容发送到它在添加目录名前缀之前所在的目录。
这里,我们完成了在合并中提交更改的过程。
完成此操作后,您可以推送并重新开始与任何其他分支进行合并,只需签出存储库中将接收更改的分支并更改您在合并和读取树操作中引入的分支。
It happened to us that we created 2 repositories for 2 projects that were so coupled that didn't make any sense to have them separated, so we merged them.
I'll show how to merge the master branches in each first and then I will explain how you can extend this to every branches you got, hope it helps you.
If you got the submodule working, and you want to convert it to a directory in place you can do:
Here we do a clean clone to work. For this process you don't need to initialize or update the submodules, so just skip it.
Edit
.gitmodules
with your favorite editor (or Vim) to remove the submodule you plan to replace. The lines you need to remove should look something like this:After saving the file,
Here we remove the submodule relation completely so we can create bring the other repo to the project in-place.
Here we fetch the submodule repository to merge.
Here we start a merge operation of the 2 repositories, but stop before commit.
Here we send the content of master in the submodule to the directory where it was before prefixing a directory name
Here we complete the procedure doing a commit of the changes in the merge.
After finishing this you can push, and start again with any other branch to merge, just checkout the branch in you repository that will receive the changes and change the branch you bringing in the merge and read-tree operations.
我找到的最佳答案在这里:
http://x3ro.de/2013/09/01/Integrating-a-submodule-into-the-parent-repository.html
本文很好地解释了该过程。
The best answer to this I have found is here:
http://x3ro.de/2013/09/01/Integrating-a-submodule-into-the-parent-repository.html
This article explains the procedure very well.
这是 @gyim 答案的稍微改进版本(恕我直言)。他正在主工作副本中进行一系列危险的更改,我认为在单独的克隆上进行操作然后最后将它们合并在一起要容易得多。
在一个单独的目录中(为了使错误更容易清理并重试)检查顶级存储库和子存储库。
首先编辑子存储库以将所有文件移动到所需的子目录中
记下 HEAD
现在从主存储库中删除子存储库
最后,只需合并它们
就完成了!安全且没有任何魔法。
Here's a slightly improved version (IMHO) of @gyim's answer. He is doing a bunch of dangerous changes in the main working copy, where I think it's much easier to operate on separate clones and then merge them together at the end.
In a separate directory (to make mistakes easier to clean up and try again) check out both the top repo and the subrepo.
First edit the subrepo to move all files into the desired subdirectory
Make a note of the HEAD
Now remove the subrepo from the main repo
And finally, just merge them
And done! Safely and without any magic.
对于何时
返回
上下文:我在子模块文件夹中执行了
rm -r .git*
,然后意识到它们需要在我刚刚添加它们的主项目中进行子模块化。我在对某些(但不是全部)进行子模块化时遇到了上述错误。无论如何,我通过运行修复了它们(当然,在rm -r .git*
之后)请注意,这不会保留历史记录。
For when
returns
Context: I did
rm -r .git*
in my submodule folders before realizing that they needed to be de-submoduled in the main project to which I had just added them. I got the above error when de-submoduling some, but not all of them. Anyway, I fixed them by running, (after, of course, therm -r .git*
)Note that this doesn't preserve history.
根据 VonC 的回答,我创建了一个简单的 bash 脚本来执行此操作。最后的
add
必须使用通配符,否则它将撤消子模块本身之前的rm
。添加子模块目录的内容非常重要,而不是在add
命令中命名目录本身。在名为 git-integrate-submodule 的文件中:
Based on VonC's answer, I have created a simple bash script that does this. The
add
at the end has to use wildcards otherwise it will undo the previousrm
for the submodule itself. It's important to add the contents of the submodule directory, and not to name the directory itself in theadd
command.In a file called
git-integrate-submodule
:在主存储库中
在子模块 repo
再次主 repo
In main repo
In submodules repo
Again main repo
我发现(也?)从子模块获取本地提交数据更方便,因为否则我会丢失它们。 (无法推送它们,因为我无法访问该遥控器)。所以我添加了 submodule/.git 作为remote_origin2,获取它的提交并从该分支合并。
不确定我是否仍然需要子模块远程作为源,因为我对 git 还不够熟悉。
I found it more convenient to (also?) fetch local commit data from the submodule, because otherwise I would loose them. (Could not push them as I have not access to that remote). So I added submodule/.git as remote_origin2, fetched it commits and merged from that branch.
Not sure if I still need the submodule remote as origin, since I am not familiar enough with git yet.
这是我发现的最好的&最简单。
在子模块存储库中,您想要从 HEAD 合并到主存储库中:
git checkout -b "mergeMe"
mkdir "foo/bar/myLib/"
(与您所在的路径相同)想要主存储库上的文件)git mv * "foo/bar/myLib/"
(全部移入路径)git commit -m "ready to merge into main"
返回在删除子模块并清除路径“foo/bar/myLib”后的主存储库中:
繁荣完成
历史记录保留
无忧
请注意,这几乎与某些相同其他答案。但这假设您拥有子模块存储库。此外,这还可以轻松获得子模块未来的上游更改。
Here's what I found best & simplest.
In submodule repo, from HEAD you want to merge into main repo:
git checkout -b "mergeMe"
mkdir "foo/bar/myLib/"
(identical path as where you want the files on main repo)git mv * "foo/bar/myLib/"
(move all into path)git commit -m "ready to merge into main"
Back in main repo after removing the submodule and clearing the path "foo/bar/myLib":
git merge --allow-unrelated-histories SubmoduleOriginRemote/mergeMe
boom done
histories preserved
no worries
Note this nearly identical to some other answers. But this assumes you own submodule repo. Also this makes it easy to get future upstream changes for submodule.