要删除remotes/jason/sprint-36 或remotes/ken/retain-cycle-fix 等远程跟踪名称,您可以使用git branch -r -d:
$ git branch -r -d remotes/jason/sprint-36
例如。但是,几乎没有任何理由这样做,因为如果您运行git fetch jason,您将立即重新获取所有您的remotes/jason/ 远程跟踪名称。
要删除整个远程及其所有远程跟踪名称,请使用git remote remove 或git remote rm(同一子命令的两个名称)。
有用的背景知识(这些都不是必读的,你可以停在这里)
这里有几件事值得注意,它们都不是问题的直接答案,但对完整性很有用:
-
首先,Git 将这些东西称为远程跟踪分支名称,但它们实际上并不是分支,因为一个分支——或者至少是一个分支名称 - 是您可以给 git checkout 的名称,这会导致将 HEAD 附加到该名称。
也就是说,在git checkout master 或在您的情况下为git checkout sprint-41 之后,您将“在”该分支上。 git status 命令将显示on branch <em>branch</em>,您所做的新提交将自动更改该分支名称,使其指向刚刚提交的新提交。这些都不适用于这些远程跟踪名称,这就是为什么我开始称它们为“远程跟踪名称”,完全放弃了 branch 这个词。
-
他们有全名表格。 remotes/jason/sprint-36的全名真的是refs/remotes/jason/sprint-36。由于the gitrevisions documentation 中描述的六步名称解析过程,可以缩写全名:jason/sprint-36 通常有效,如果无效,remotes/jason/sprint-36 通常有效,但如果这些都无效,则完整-name 形式始终有效。
无论出于何种原因,git branch -r 列出了缩短的版本没有 remotes/,而git branch -a 列出了缩短的版本有 remotes/。
-
远程跟踪名称的重点是跟踪远程上的名称(特别是分支名称)。所以git fetch 更新了这些远程跟踪名称。至少,从 Git 版本 1.8.4 开始就是这样。
-
与所有引用一样,远程跟踪名称仅记录单个提交的哈希 ID。如果该提交是来自任何其他名称的reachable,则远程跟踪名称仅指向该特定提交。如果提交无法从任何其他名称访问,则远程跟踪名称将保持该提交及其前身(父母、祖父母等)在您的存储库中的活动。 (可达性的定义见http://think-like-a-git.net/的链接。)
这意味着删除远程跟踪名称将不会节省任何空间,除非该名称是唯一到达某些占用存储库中大量空间的提交的方式。如果远程跟踪名称指向由其他提交和/或名称保留的提交,您肯定不会通过删除它来保存任何内容,除了git branch 输出中的一些屏幕空间和类似内容。1
-
当您运行 git fetch <em>remote</em> 时,没有其他参数,Git 将获取并更新 remote.<em>remote</em>.fetch 设置中列出的引用(使用 git config --get-all remote.<em>remote</em>.fetch 来查看这些)。当您运行 git fetch <em>remote</em> <em>refspec1</em> [<em>refspec2</em> [...]] 时,git fetch 将仅根据给定的 refspec 参数进行更新。
1从技术上讲,如果远程跟踪名称当前已解压缩,您可能会保存一个磁盘块左右。但是,大多数远程跟踪名称大多是打包的(与许多其他名称一起存储在 .git/packed-refs 中)。
使用--prune 或fetch.prune 获取
您可能会定期运行git fetch 或git fetch origin 来更新origin 的所有远程跟踪名称。 (例如,我这样做。几乎任何时候都这样做非常安全。)当你这样做时,你会获得很多远程跟踪名称。
最终,其中一些名称可能会从origin 中消失。不过,它们不会自动从您自己的远程跟踪名称中消失。要使它们自动消失,请使用git fetch --prune origin,或将fetch.prune 配置为true,其中git fetch 默认使用--prune。将此处的origin 替换为任何遥控器,例如jason 或ken,以通过修剪更新所有内容。 (但是,如果您不喜欢更新所有内容,请不要这样做——这是“一体式”设置,它会创建或更新该遥控器的所有远程跟踪名称,同时删除任何死的名称。 )
Refspecs,或者,更多关于你正在运行的git fetches
在上面的一个示例中,您运行了:
git fetch jason sprint-36
这使用sprint-36 作为参考规范。 refspec 通常由两个用冒号分隔的名称组成,例如 refs/heads/master:refs/remotes/origin/master。省略冒号和第二个名字会做一些特别的事情——在git fetch 和git push 中有所不同。对于git push,省略冒号意味着两边都使用相同的名字,但对于git fetch,这意味着不要在我这边使用任何名字。
这就是事情变得奇怪的地方,这也是为什么我不得不在其中一个要点中提到 Git 1.8.4 之前和 1.8.4 及更高版本。这里有一个历史上的怪事。
Every git fetch 将有关获取的名称以及相应的 Git 对象哈希 ID 的信息写入 .git 中名为 FETCH_HEAD 的特殊文件。该文件与参考文件几乎相同,但不完全一样,因为它可以而且经常确实包含多行,每行不仅仅是一个哈希 ID。从本质上讲,git fetch 从git ls-remote 的输出开始(在你的遥控器上试试这个——它只是将内容打印到终端窗口),确定要获取的内容,然后在.git/FETCH_HEAD 中保存非常相似的内容。
在过去的糟糕日子里,当 Git 特别难以使用时,那是 唯一git fetch 保存其信息的地方。您必须立即捞出任何有用的东西并自己保存。 git pull 脚本为您完成了这项工作。这仍然有效,因为像英特尔一样,Git 家伙喜欢将“向后”保持在“向后兼容”中。 ?
从 Git 1.8.4 开始,这一切都发生了变化:Git 学会了使用该遥控器的 fetch 设置来更新适当的远程跟踪分支。
同时——当时为真,现在仍然为真——如果你使用两个名字的形式,例如:
git fetch jason sprint-36:rhs
git fetch 将尝试使用左侧名称sprint-36(与从git ls-remote jason 溢出的列表匹配,使其变为refs/heads/sprint-36)写入分支或标签或其他内容在您自己的存储库中命名。在这里,我使用rhs 作为右侧名称。此名称不是完全限定(例如,不以refs/heads/ 开头)并且可能当前不存在于您的存储库中作为名称,因此Git 将使用您的@987654395 中的refs/heads/ 提示@remote 在你自己的仓库中创建一个新的分支refs/heads/rhs。
只要您的 Git 是 1.8.4 或更新版本,它也会在此时机会主义地创建或更新refs/remotes/jason/sprint-36。
因此,使用包含冒号和右侧名称的 refspec 获取可能会在您的存储库中创建或更新 两个 引用。通常,一个分支名称是 refs/heads/rhs 或 refs/heads/sprint-36。另一个是远程跟踪名称,例如refs/remotes/jason/sprint-36,通过.git/config 中的remote.jason.fetch 设置进行管理。
您可以更改remote.jason.fetch 设置。如果你这样做了,那会改变 git fetch jason: 的操作:没有 refspecs,Git 服从 fetch 设置。它还可能改变git fetch jason sprint-36 的操作:如果refs/heads/sprint-36 不再映射到远程跟踪名称,则不会创建或更新远程跟踪名称。
这一切是否以及何时有任何用处都很难说。 (该设计实际上是围绕--single-branch 克隆,而不是花哨的用户管理配置。)不过,这是底层机制:refspecs 通过 refmaps (我不会尝试在这里定义,但它们在the git fetch documentation) 中的描述相当糟糕,默认情况下是从每个远程fetch 设置构建的。
请注意,如果没有前导加号 +,则像 sprint-36:rhs 这样的 refspec 是一个非强制更新。仅当更新导致快进操作时才进行此类更新。事实上,这很有用,因为这意味着您可以从您自己的其他分支或远程跟踪名称中快速转发您自己的非当前分支。您可以通过git fetch 或git push 执行此操作,使用. 作为远程名称,因为. 表示此Git 存储库:
git fetch . refs/remotes/origin/master:refs/heads/master
或:
git push . refs/remotes/origin/master:refs/heads/master
将快进您自己的master 以匹配您的origin/master,而无需离开当前的非master 分支。 (如果你独自一人master,它不会起作用。有一个棘手的方法让它起作用,但不要这样做!)
(您很少需要在此处拼出完整的分支名称,但这通常是一个好主意,以防万一——当 Git 不匹配引用时会很烦人。)