Git Filter-Branch All 命令

2023-12-28

目前,我正在使用命令“git filter-branch --subdirectory-filter MY_DIRECTORY -- --all”从该 git 存储库的所有 30 个分支中获取某个目录。在执行此过滤分支命令之前,我确保检查每个分支以确保 --all 命令正常工作。

我的问题是,在执行 git-filter all 之前我是否必须检查每个分支,或者 git-filter all 仍然可以工作而不必检查我正在查看的所有 30 个分支吗?现在每个分支几乎有 3GB,所以整个结帐过程需要很长时间。任何澄清都会很棒!


在我们开始之前

在我深入探讨答案之前,请注意,如果您想为每个远程跟踪名称都有一个本地分支名称,您可以简单地创建该本地分支名称,而无需使用git checkout:

git branch -t develop origin/develop
git branch -t feature/X origin/feature/X
git branch -t foo origin/foo

等等。这是以下内容的子集git checkout确实如此,而且速度非常快,因为创建新的分支名称只意味着写入一个文件。

(如果您愿意,您可以使用此技术并在此停止,但此答案的其余部分应该非常有用。)

短答案和长答案

简而言之,您不必签出(或创建新的)分支名称。但要使用 Git,您需要了解的不仅仅是这些(包括这个特定的git filter-branch操作)好。

让我们从这个开始:--all这里的意思是所有参考文献。但什么是“参考”呢?

嗯,任何分店名称是一个参考。但任何也是如此tag name。特别的名字refs/stash,使用者git stash,是一个参考。远程跟踪名称仅供参考。注释参考文献(来自git notes) 为参考。有关此术语和其他 Git 术语的更多信息,请参阅git 术语表 https://www.kernel.org/pub/software/scm/git/docs/gitglossary.html(请注意,该特定条目位于ref而不是reference).

当你第一次使用时git clone要克隆存储库,您需要告诉自己的 Git:在我给您的 URL 上创建一些现有存储库的新的独立副本,以便我可以完成自己的工作,然后根据需要共享或不共享。 But their存储库——URL 上的“他们”是谁——拥有its own分支机构名称。他们有their master,这并不总是与您的相同master。所以你的 Gitrenames他们的名字:他们的master成为你的origin/master, 等等。这些远程跟踪名称是参考。

After git clone完成将所有提交复制到您的存储库,并将所有名称重命名为您的远程跟踪名称,这是最后一步git clone是检查一个分支。但你不have还没有任何分支机构。这就是一个特殊的技巧git checkout确实出现了:如果你要求 Git 按名称签出一个分支,不存在,Git 会查看所有远程跟踪名称。如果其中之一匹配,Git 将create本地分支名称——一个新的引用——指向samecommit 作为此远程跟踪名称。

因此,您的存储库有一系列提交,所有这些提交都以向后的方式相互链接:

first  <--next ... <--almost-last  <--last

(如果它们都是线性的,但它们几乎从来都不是)我们可以将其绘制为:

A--B--...--H--I

其中每个大写字母代表一次提交。一组具有某些“分支性”(分支性?)的提交可能如下所示:

     C--D
    /
A--B
    \
     E--F--G

如果有合并提交,则向后指向two以前的提交而不是只有一次,它会更加复杂。

The names我们最关心的是分支名称和远程跟踪名称,尤其是 Git 的一种方式find最后一次提交:

...--H--I   <-- origin/master

名字origin/master据说point to commit I。当你的 Git 创建你自己的master, your master now also指着I:

...--H--I   <-- master, origin/master

如果您创建自己的新提交master,这就是发生的情况:

...--H--I   <-- origin/master
         \
          J   <-- master

Git 为新的提交创建一个新的 ID——它是一些明显随机的又大又难看的哈希 ID,但在这里我们只是称之为它J-进而changes你的名字master指向这个新的提交。

如果你跑git fetch并引入新的提交origin他们已经更新了their主人,你现在得到:

...--H--I--K   <-- origin/master
         \
          J   <-- master

现在你的master和他们的origin/master已经出现分歧。

这些名字,master and origin/master,对做出承诺具有重要影响可达的。也就是说,通过跟随每个名称中的箭头,Git 可以找到提交J and K。然后,使用向后箭头——实际上是提交的parent提交哈希 ID — 来自J to I或来自K to I,Git可以找到commitI。使用向后箭头I本身,Git 可以找到H,依此类推,一直回到第一次提交,即操作停止的地方。

All 无法到达的提交——那些通过从所有这些起始(结束?)点开始并向后走而没有找到的提交——将在某个时刻被删除,因此它们实际上不存在。对于大多数遍历图表的 Git 命令来说,情况也是如此。 (有一些特殊目的的恢复技巧可以让您将已删除的提交恢复 30 天,但 filter-branch 不支持这些。)

这一切对过滤器分支意味着什么

的工作git filter-branch is to 复制提交。它会遍历图表,使用您提供的起始(结束?)点来查找所有可到达的提交。它将它们的哈希 ID 保存在临时文件中。然后,朝相反的方向前进——即时间向前,而不是 Git 通常的向后——它提取每个提交。也就是说,它会对其进行检查,以便该快照中的所有文件都可用。然后过滤器分支应用过滤器,然后从结果文件中进行新的提交。因此,如果您的过滤器进行简单的更改,结果就是copy原始图的:

A--B--C------G--H   <-- master, origin/master
    \       /
     D--E--F

becomes:

A'-B'-C'-----G'-H'  <-- master, origin/master
    \       /
     D'-E'-F'

原始提交会发生什么?好吧,它们仍然在那里:过滤器分支对找到它们的名称所做的是rename他们,使用refs/original/在他们的内部全名前面:

A--B--C------G--H   <-- refs/original/refs/heads/master, refs/original/refs/remotes/origin/master
    \       /
     D--E--F

过滤器分支有这么多过滤器选项的原因之一是这个过程非常慢。将每个文件提取到临时目录中需要很长时间。因此,某些过滤器可以在根本不提取文件的情况下工作,这会快得多(快得多!)。

另一个原因是有时我们不想复制every提交,我们只想复制some满足某些标准的提交。情况就是如此--subdirectory-filter:如果它更改涉及相关子目录的文件(相对于其父提交),它只会复制提交。因此,在某些情况下,它可以跳过提取大量提交。当然,子目录过滤器还会在提取并重新提交时重命名文件,以删除子目录路径。结果是将较大的提交图复制到较新、较小的提交图:

A--B--C------G--H   <-- master
    \       /
     D--E--F

可能会变成:

B'--G'--H'   <-- master
 \ /
  E'

所保留的refs/original/refs/heads/master仍然会指向提交H,而重写的refs/heads/master将指向复制的提交H'。请注意,新图中的第一个提交是B', not A', since A'没有相关的子目录。

这里还有一个非常重要的附带问题:过滤器分支在完成所有提交复制后会更新哪些引用?答案在文档中:

该命令只会重写positive中提到的参考文献 命令行(例如,如果您通过a..b, only b将被重写)。

既然你正在使用--all,这将重写所有origin/*远程跟踪名称。 (--all算作对这里每一位裁判的积极提及。标签有一些额外的技巧:如果你想重写你的标签,添加--tag-name-filter cat作为过滤器。)

Summary

在你的过滤分支操作之后,你有一系列refs/original/*指向原始(预过滤)提交的名称,从原始全名重命名。您有一系列新更新的参考资料,包括所有分支名称(refs/heads/*)和远程跟踪名称(refs/remotes/*)指向被复制的最后一个提交。

新的存储库将是bigger比原来的,因为它contains原始的,加上复制的提交。请参阅缩小存储库的清单的部分the git filter-branch文档 https://www.kernel.org/pub/software/scm/git/docs/git-filter-branch.html, 接近尾声。但请注意,如果您使用git clone复制过滤后的存储库,仅复制您的branch名字,不是你的远程追踪名称,因此此时,如果您尚未为每个远程跟踪名称创建分支,则应该立即执行此操作。

或者,您可以在删除所有存储库后将复制的存储库保留在适当的位置refs/original/命名空间名称。那么你可以git checkout develop创建你自己的refs/heads/develop根据您的(过滤后的)refs/remotes/origin/develop, 等等。您所做的就是创建新名称(提交本身是 Git 真正关心的内容,并且由重写的远程跟踪名称引用它们),然后检查该特定提交,以便它位于您的索引和工作树中。 (这git branch -t我们在开始时显示的命令创建了名称,而不将提交复制到索引和工作树。)

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Git Filter-Branch All 命令 的相关文章

  • git fetch 的默认远程

    如果我在当地的分支机构not跟踪任何远程分支 我发出命令 git fetch 鉴于我定义了几个遥控器 GIT DIR config 从哪个远程获取 我试图从man page https www kernel org pub software
  • Git 命令查找哪些分支合并到当前分支以及何时合并

    我有几个功能分支正在自动合并到集成分支中 我想知道这种情况是否以及何时发生 我可以打字git log这将向我显示合并已经发生 但由于某种原因 它没有向我显示来自哪个功能分支 它只是说 将integration branch合并到integr
  • Google App Engine 和 Git 最佳实践

    我正在 Google App Engine 上开发一个小型宠物项目 我想使用以下命令将源代码置于源代码控制之下github http www github com 这将允许我的朋友检查和修改源代码 我只有一个PetProject包含所有源的
  • 在 Windows 上为 Bitbucket 设置 SSH 密钥

    首先 我对 git repos 和命令行绝对是菜鸟 我在 Bitbucket 上有仓库 我基本上希望能够通过 gitbash 推送到存储库 而无需每次输入密码 我拥有的 Bitbucket 上的存储库已设置好代码 克隆存储库的本地目录 通过
  • 哪些Git命令无法在本地执行?

    当我和同事谈论 Git 时 我告诉他们 一旦本地存储库初始化 只有三个 Git 命令不能在不访问远程存储库的情况下执行 假设origin当然 不在本地计算机上 git fetch http www kernel org pub softwa
  • GIT Rebase 协作的分支?

    阅读本文后 重新设置基点以收集从主分支到我的功能分支的更改是有意义的 Git 工作流程以及 rebase 与合并问题 https stackoverflow com questions 457927 git workflow and reb
  • git:键不包含节

    我使用的是 Git 版本 1 8 4 2 When I press tab to auto complete any command it prints the error below and it also completes the c
  • 如何在 Git 中重命名带注释的标签

    如何在 Git 中重命名现有的带注释的标签 我在存储库上有近一百个代表版本号的标签 每个标签都注释有有关该版本更改内容的有用描述 我想更改用于这些标签的命名样式 记录标签消息 删除标签 然后使用旧消息和新名称重新创建它 这对于手动为近一百个
  • 如何在 Mac OS X 10.9 上安装和使用最新的 Git?

    我从 sourceforge 下载了 Git 2 4 3http git scm com download mac http git scm com download mac对于我的 Macbook Pro OS X 10 9 5 然后安装
  • 如何将Github中的develop分支设置为默认分支而不是master?

    我知道这可以在存储库的管理页面上完成 可以在那里设置另一个默认分支 这就是这个问题的答案 但我发现 也许是一个错误 以下内容 如果你的master分支和develop分支完全相同 那么git克隆将不会克隆默认的 develop 分支 但仍然
  • 特定远程分支名称的 Git 列表

    如何获取某些远程源分支的所有名称 我从 remote list选项 但变得多余origin HEAD gt origin master来自另一个源的消息和分支 gt git branch remote list origin HEAD gt
  • git pull origin master 返回致命错误:无效的 refspec

    问题是这样的 每当我这样做时 git pull https github com username reponame github io git 接下来是网址 我没有遇到任何问题 但是当我这样做时 git pull origin maste
  • 当 TLSv1 因“忽略未知记录”而失败时,使 git 恢复为 SSLv3

    无法使用git git clone https github com foo bar fails fatal unable to access https github com foo bar Unknown SSL protocol er
  • Github 操作 - 错误:进程已完成,退出代码为 1

    我正在尝试设置 github 操作来部署我的应用程序 My bash 启动部署过程的脚本如下所示 bin sh set e vendor bin phpunit git push true git checkout production g
  • GIT:查找包括子模块的文件列表(例如使用 git ls-files)

    我一直在试图弄清楚如何获取 git 存储库中所有文件的列表 包括子模块中包含的文件 现在 git ls files将提供顶级子模块目录 但不提供子模块中包含的文件 经过进一步调查 我发现使用git submodule 你可以递归地找到所有的
  • GIT 从特定标签拉取/获取

    有没有办法从存储库中的特定标签中提取 获取代码 我知道克隆后 我可以签出标签 但是否可以在拉取期间指定标签 在 ClearCase 中 我可以重新设置或交付特定的代码基线 有没有一种方法可以使用 git 标签 类似于将代码拉 推到指定标签
  • .gitignore 在提交、推送或到达服务器时起作用吗?

    说我有一个 gitignore忽略所有 class files 当 时这些文件是否远离远程源 我在本地提交 添加我的文件 我的吗git寻找一个 gitignore当使用添加 提交时 并根据它所说的内容 从提交中删除内容 我推动我的承诺 做g
  • 如何在不下载文件对象的情况下进行 git 克隆

    是否可以下载所有提交但不能下载文件本身 我想运行 bisect 但从构建服务器下载版本而不是自己编译 当你跑步时git bisect你可以提供 no checkout如果您不想为每次迭代签出新的工作树 请作为参数 同样适用于git clon
  • 对于 Web 应用程序来说,您理想的 git 分支架构是什么?

    我们是一个由开发人员组成的小团队 正在构建 Web 应用程序 我们目前拥有一个实时 测试和多个开发环境 您会建议什么分支架构 以便理想情况下每个开发人员都可以处理他的功能 这些功能可以在不影响其他开发人员 功能的情况下进行测试和部署 目前
  • 如何使用 git-svn 切换 svn 存储库?

    我有许多使用 git svn 创建为 SVN 存储库克隆的 git 项目 我们已将 SVN 存储库迁移到新的提供商 因此 URL 现在已更改 如何更新 git 克隆的远程 SVN URL 一种可能性是我从新的 SVN 存储库重新克隆 但我不

随机推荐