将子目录分离(移动)到单独的 Git 存储库中

2024-04-08

我有一个Git http://en.wikipedia.org/wiki/Git_%28software%29存储库,其中包含许多子目录。现在我发现其中一个子目录与另一个子目录无关,应该分离到一个单独的存储库。

如何在保留子目录中文件的历史记录的同时执行此操作?

我想我可以制作一个克隆并删除每个克隆中不需要的部分,但我想这会在检查旧版本等时为我提供完整的树。这可能是可以接受的,但我更愿意能够假装两个存储库没有共享历史记录。

为了清楚起见,我有以下结构:

XYZ/
    .git/
    XY1/
    ABC/
    XY2/

但我想要这个:

XYZ/
    .git/
    XY1/
    XY2/
ABC/
    .git/
    ABC/

简单的方法™

事实证明,这是一种常见且有用的做法,Git 的统治者使它变得非常简单(在版本 1.7.11 - 2012 年 5 月中添加)。另外,还有一个现实世界的例子 in the 演练 below.

  1. 准备旧仓库

     cd <big-repo>
     git subtree split -P <name-of-folder> -b <name-of-new-branch>
    

    Note: <name-of-folder>不得包含前导或尾随字符。例如,名为的文件夹subproject必须传递为subproject, NOT ./subproject/

    Note: <name-of-new-branch>是您将在现有/旧存储库中创建的分支,NOT新的[稍后出现]。

    Windows 用户注意事项:当你的文件夹深度 > 1 时,<name-of-folder>必须有 *nix 样式文件夹分隔符 (/)。例如,名为的文件夹path1\path2\subproject必须传递为path1/path2/subproject

  2. 创建新的存储库

     mkdir ~/<new-repo> && cd ~/<new-repo>
     git init
     git pull </path/to/big-repo> <name-of-new-branch>
    
  3. 将新存储库链接到 GitHub 或其他地方

     git remote add origin <[email protected] /cdn-cgi/l/email-protection:user/new-repo.git>
     git push -u origin master
    
  4. 内部清理<big-repo>, 如果需要的话

     git rm -rf <name-of-folder>
    

    Note:这会将所有历史参考文献保留在存储库中。请参阅Appendix如果您确实担心提交密码或者需要减小您的文件大小,请按以下步骤操作:.git folder.


演练

这些是与上面相同的步骤,但是按照我的存储库的确切步骤而不是使用<meta-named-things>.

这是我在 Node 中实现 JavaScript 浏览器模块的项目:

tree ~/node-browser-compat

node-browser-compat
├── ArrayBuffer
├── Audio
├── Blob
├── FormData
├── atob
├── btoa
├── location
└── navigator

我想拆分一个文件夹,btoa,进入一个单独的 Git 存储库

cd ~/node-browser-compat/
git subtree split -P btoa -b btoa-only

我现在有一个新的分行,btoa-only,仅提交了btoa我想创建一个新的存储库。

mkdir ~/btoa/ && cd ~/btoa/
git init
git pull ~/node-browser-compat btoa-only

接下来,我在 GitHub 或 Bitbucket 等上创建一个新的存储库,并将其添加为origin

git remote add origin [email protected] /cdn-cgi/l/email-protection:node-browser-compat/btoa.git
git push -u origin master

快乐的一天!

Note:如果您创建了一个带有README.md, .gitignore and LICENSE,你需要先拉:

git pull origin master
git push origin master

最后,我想从更大的存储库中删除该文件夹

git rm -rf btoa

清除您的历史记录

默认情况下,从 Git 中删除文件并不会真正删除它们;而是将其删除。它只是承诺他们不再存在了。如果您想实际删除历史引用(即您提交了密码),您需要执行以下操作:

git filter-branch --prune-empty --tree-filter 'rm -rf <name-of-folder>' HEAD

之后,您可以检查您的文件或文件夹是否不再显示在 Git 历史记录中:

git log -- <name-of-folder> # should show nothing

然而,你无法将删除“推送”到 GitHub等等。如果你尝试,你会得到一个错误,你必须git pull在你可以之前git push- 然后你又回到了拥有你历史中的一切。

因此,如果您想从“源”删除历史记录(即从 GitHub、Bitbucket 等删除历史记录),您需要删除存储库并重新推送存储库的修剪副本。可是等等 -还有更多! - 如果您真的担心删除密码或类似的东西,您需要修剪备份(见下文)。

Making .git smaller

前面提到的删除历史命令仍然会留下一堆备份文件 - 因为 Git 非常友善地帮助您避免意外破坏您的存储库。它最终会在数天和数月内删除孤立的文件,但会将它们保留一段时间,以防您意识到不小心删除了您不想删除的内容。

所以如果你真的想清空垃圾 to 减小克隆大小立即创建一个仓库,你必须做所有这些非常奇怪的事情:

rm -rf .git/refs/original/ && \
git reflog expire --all && \
git gc --aggressive --prune=now

git reflog expire --all --expire-unreachable=0
git repack -A -d
git prune

也就是说,我建议不要执行这些步骤,除非您知道需要这样做 - 以防万一您确实修剪了错误的子目录,您知道吗?当您推送存储库时,备份文件不应被克隆,它们只会位于您的本地副本中。

Credit

  • http://psionides.eu/2010/02/04/sharing-code- Between-projects-with-git-subtree/ http://psionides.eu/2010/02/04/sharing-code-between-projects-with-git-subtree/
  • 从 git 中永久删除目录 https://stackoverflow.com/questions/1216733/remove-a-directory-permanently-from-git
  • http://blogs.atlassian.com/2013/05/alternatives-to-git-submodule-git-subtree/ http://blogs.atlassian.com/2013/05/alternatives-to-git-submodule-git-subtree/
  • 如何从我的 Git 存储库中删除未引用的 blob https://stackoverflow.com/questions/1904860/how-to-remove-unreferenced-blobs-from-my-git-repo
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

将子目录分离(移动)到单独的 Git 存储库中 的相关文章

  • Git 子模块在 Windows 上更新缓慢

    Git 子模块在 Windows 上似乎非常慢 为了测试性能 我创建了 3 个裸存储库并向它们提交了 3 条独立消息 未存储文件 然后 我将每个裸存储库作为子模块添加到新的 git 存储库中 并执行子模块更新 花费了 5 秒多的时间 当使用
  • Sourcetree 2.1.2.5 - 显示“未提交的更改”,但没有任何待处理的内容

    我有一个以前没有遇到过的问题 即使我没有什么可提交的 并尝试将我的分支重置为 Sourcetree 显示的最新提交Uncommitted changes 根据 Atlassian 论坛的说法 通常有两个原因 您的工作目录中有很多很多未暂存的
  • git push origin 分支名总是推送到 master

    我搜索了一下 但似乎找不到答案 在我可以访问的两个盒子上 当我执行 git push dry run origin mytestbranch 时 我得到以下结果 To email protected cdn cgi l email prot
  • git 提交消息的 vim 语法高亮显示 - 自定义 commentchar

    如上所述在这个答案中 https stackoverflow com a 14931661 835945 从 Git 1 8 2 开始你可以使用core commentchar配置值将提交消息注释更改为默认值以外的其他内容 哈希标记或哈希符
  • 如何在 Android Studio 中比较两个 Git 分支?

    我不确定是否可以将主分支 或任何其他分支 与当前功能分支进行比较 例如GIT does 我想要两个分支 主分支和功能分支 之间的差异 以便我可以在合并之前比较差异 我发现 Git UI 对用户不太友好 就像在 AS 中一样 我可以遍历代码并
  • 如何在 git diff 中按标点符号拆分单词?

    我对以下命令有一些运气 git diff color words lt gt space lt gt 但它似乎没有在第一个字符类中正确地否定方括号 我试过这个 git diff color words lt gt space lt gt 为
  • git分支和标签如何存储在磁盘中?

    我最近检查了我工作中的一个 git 存储库 其中有 10 000 多个分支和 30000 多个标签 新克隆后 存储库的总大小为 12Gigs 我确信没有理由拥有 10000 个分支机构 所以我相信它们会占用磁盘中相当大的空间 所以 我的问题
  • 从分离的头进行 Git 推送

    我以超然的态度做出了一些改变 我想用 Git 将这些更改推送到这个独立的头 我不希望我的更改进入开发分支 当然也不想进入主分支 我正在与另一个人一起处理一个文件 分支示例 develop master HEAD detached at or
  • 如果文件已在服务器上,请避免使用 git-ftp 上传

    假设我有应用程序的本地副本 我将其推送到 github 然后使用 git ftp 将任何更改上传到我的服务器 我首先会使用 git ftp init u
  • git-svn --忽略路径

    我现在在 git svn 的 ignore paths 选项上挣扎了几个小时 试图从大型存储库中仅获取某些标签 我想在 dev 处开始获取 看起来像 gt svn ls http 192 168 0 2 svn repo corporati
  • Git 中的专有+开源设置? (例如铬/铬)

    您将如何设置一个拥有专有版本和开源版本 例如 Chrome 和 Chromium 的代码存储库 对于 Git 您会使用两个分支还是两个存储库 您如何使 私有 版本与开源版本保持同步 如果是我 我会有两个存储库 这样 您就可以对每个版本拥有不
  • 判断 Git 提交是否是合并/恢复提交

    我正在编写一个脚本 需要检查特定提交是否是合并 恢复提交 我想知道是否有 git 技巧 到目前为止我想到的 我绝对不想依赖这里的提交消息 是检查HASH 2看看我是否没有收到错误 是否有更好的方法 判断某个东西是否是合并很容易 这是不止一位
  • Gerrit 安装后无法克隆所有项目存储库

    我有一个新设置的 Gerrit 实例 目前只有两个存储库 所有项目 binutils 测试 尝试克隆所有项目时 我收到以下错误 git clone ssh user hostname 29418 All Projects Initializ
  • 具有单独 work_tree 的 Git 子模块

    我按照本页上的教程使通过 Git 部署我的网站变得简单 http toroid org ams git website howto http toroid org ams git website howto 到目前为止一切都很好 但是我最近
  • 节点项目的 Azure git 部署失败

    我正在尝试将我的项目部署到azure 它正在失败 这些是我采取的步骤 git init git config core longpaths true git add git commit m initial commit 所有这些都有效 我
  • 在 git repo 中查找超过 x MB 且 HEAD 中不存在的文件

    我有一个 Git 存储库 用于存储随机的内容 主要是随机脚本 文本文件 我设计的网站等 随着时间的推移 我删除了一些大型二进制文件 通常为 1 5MB 这些文件会增加存储库的大小 而我在修订历史记录中不需要这些文件 基本上我希望能够做到 m
  • 使用 TFS 个人访问令牌克隆 Git 存储库

    我正在尝试以编程方式克隆 git 存储库 我的 ASP NET MVC 应用程序正在创建并启动一个进程 处理进程的代码工作正常 但是当尝试使用本地 TFS PAT 克隆 git 存储库时 身份验证失败 我无法使用 NTLM 或要求用户输入凭
  • 如何使用交互式变基将提交编辑为未提交?

    我想使用交互式变基来编辑以前的提交 但是当我进入该提交的编辑模式时 所有文件都已提交 我知道我可以进行更改并修改提交 但我希望所有更改最初都未提交 暂存或以其他方式 这样我就可以对其进行编辑 就像在最初提交之前一样 这可能吗 Imagine
  • 如何 git grep 仅一组文件扩展名

    如何执行 git grep 并将检查的文件限制为一组文件 我希望能够 grep cpp 和 h 文件的内容来查找 MyFunc 例如 git grep MyFunc hc 但是 这也匹配 c 文件和 cs 文件 Use git grep M
  • git reset 命令中的 ~1 是什么意思?

    git 重置 HEAD 1 我的印象是 1 的意思是 从 HEAD 开始 遵循 1 链接 并将 HEAD 标签设置为新的提交节点 我正期待着 git 重置 HEAD 2 跟随 2 个链接 然后设置 HEAD 标签 但是 如果我尝试它 我会收

随机推荐