了解如何从 Git 历史记录中删除大型二进制文件以管理克隆存储库的大小

Azure DevOps Services |Azure DevOps Server 2022 - Azure DevOps Server 2019 |TFS 2018

近年来,Git 在分布式源代码存储库中非常受欢迎,该存储库允许用户在断开连接状态下使用完整存储库。 git 的优点是有记录的,但如果需要在主存储库上“回滚时钟”,会发生什么情况? 这样做并不直观,需要提升的权限,因为你可能期望影响存储库的每个用户。

那么,如何安全地回滚中央存储库?

问题场景

假设将大型文件(如视频)提交到 git 服务器。 在传统的源代码系统中,将一切存储在一个位置,然后拉取所需的内容是方便的。 但是,使用 git,将整个存储库克隆到每个用户的本地计算机。 使用大型文件时,项目中的每个用户也需要下载大型文件 () 。 随着每个后续大型文件提交到服务器,问题只会增加,直到存储库太大,无法对其用户有效。 为了使事情变得更糟,即使从本地存储库中删除罪犯并重新提交,文件仍将存在于存储库的历史记录中,这意味着该文件仍将下载到每个人的本地计算机作为历史记录的一部分。

“团队资源管理器更改”对话框,其中显示了包含的更改中的大型视频

将大型文件添加到本地存储库

服务器和本地存储库,同时包含大型视频文件的副本

从本地存储库提交后,服务器还将具有大型文件

冻结存储库

重要

以下步骤将从分支历史记录中删除视频,但从 Azure Repos 克隆存储库时,该文件将保留在存储库历史记录中。 从分支历史记录中删除文件可防止更新文件,这将在存储库中创建另一个版本的大型文件。 详细了解如何在 Git 中管理大型文件,并参阅此博客文章,了解有关使用 Azure Repos Git 存储库时此行为的详细说明和解决方法。

若要解决此问题,必须从源开始,在本例中,这是服务器存储库。 要求团队停止推送到存储库,但如果在此过程中发生其他推送,则必须考虑它们,以免丢失任何数据。

重定基并强制推送

如果团队中没有其他人对存储库进行任何更改(通常是通过推送),则可以采用简单的路由,在其中,你基本上使本地存储库看起来就像你希望它 (,也就是说,没有大型文件) ,然后强制更改服务器。

注意:在开始这项工作之前,可能需要克隆或修复本地存储库。 这可能会导致工作或更改丢失,因此请谨慎行事。

默认情况下,你可能只有能够更改其本地项目文件和存储库,并将更改推送到服务器,因此你不能在服务器级别进行其他更改,例如删除或重新分组。 因此,你需要从管理员那里获取 project Force push (首选) 或管理员权限,或者找到具有他们且愿意提供帮助的人员。 有关 git 权限的详细信息, 请转到此处

命令提示符 - git push --force 权限。

接下来,需要重新设置存储库的基。

  1. 但首先,用于 git log 查找最近提交的 SHA 哈希值 - 你将在一刻内需要此信息。 这是因为我们需要知道最新的良好提交。 通过打开 git 命令提示符并键入以下内容来获取该信息:

git log

或者,可以从 Visual Studio 团队资源管理器中查看分支历史记录来获取 SHA 哈希。

主分支视图历史记录

  1. 现在,打开 Git 命令提示符。

同步对话框 - 打开命令提示符操作

  1. 查找感兴趣的 SHA 哈希号。

命令提示符 - 选择视频提交

  1. 你将需要启动“25b4”的 sha

请记住,git 使用指针来确定头或当前分支所在的存储库中的位置。 因此,你感兴趣的存储库状态将在过去某个时候。 若要“及时返回”并使以前的所需状态成为新的当前状态,需要使用 git rebase 命令:

git rebase -i <SHA hash of desired new current branch>

重新base 以删除视频文件

-i 开关提供了一点额外的安全性,因为它会在编辑器中显示历史记录, (Windows 中命令行上 Git 的实现会显示经典 vi 编辑器,你可能记得你是否使用基于 Unix 的系统。)

  1. 对于我们的示例,你将输入:

git rebase -i 25b4

  1. 编辑器出现后,删除除要保留为新头的分支之外的所有“pick”行。 当一切看起来如你希望时,请在 vi 中键入“:w<enter>”保存或“!q<enter>”退出而不保存。

命令提示符 - git rebase -i 25b4 pick 命令

你将更改不再需要的行 ()

命令提示符 - git rebase -i 25b4 drop 命令

  1. 按如下所示将“pick”更改为“drop”,然后在 vi) 中键入“:w” (以保存并“”:q!以启动 rebase

现在再次键入 git log - 冒犯分支应不在日志中。 如果是,则可以完成最后一步,这需要项目管理员权限。

git log

存储库后本地和服务器存储库

请注意,大型视频的提交现在已从本地存储库中消失

  1. 类型:git push --force

命令提示符 - git push --force

命令提示符 - git push --force 结果

此命令将强制存储库覆盖服务器上的存储库。

谨慎使用,因为可以轻松丢失服务器上的数据!!

强制推送显示要保留的内容,而不显示视频文件

请注意,必须向服务器进行身份验证才能正常工作

如果使用Azure Repos,可能需要设置不使用特殊字符的备用凭据 (,例如电子邮件地址) 中的“@”。 为此,请按照 此处的说明操作。

现在,分支将从服务器永久消失,项目团队成员的后续克隆和同步不会下载你尝试删除的大型文件。 用户需要从服务器下拉,以确保它们与新的服务器存储库状态同步。

如果用户有较新的提交

如果其他用户已提交到服务器存储库,则还需要考虑一下。 你想要删除包含大型文件的分支 () ,但你不想丢失团队所做的更改。 若要解决此问题,在重新分组过程中打开编辑器时,请仔细查看提交。 确保要保留的提交列在“pick”行上;删除要删除的文件,例如添加大型文件的位置。

请注意,在重新分组后,团队上的其他用户还需要重新定基,以便每个人都有服务器存储库的一致副本。 这是每个人的痛苦,通常应该避免。 因此,如果需要按此处所述删除推送,请务必与团队协调。 有关重新分组的完整详细信息,请查看 此处的官方重整文档。

关键是确保知道所需的提交和不需要的提交。 研究 IDE ((如 Visual Studio) )中的 git 日志或历史记录,并仔细记下要保留的 SHA 哈希以及要保留的 SHA 哈希。

在大型文件已存在一段时间并且存在后续分支和合并的情况下,可以使用开关删除该文件 git filter-branch 。 若要尝试执行此操作,请按照 此处的说明操作。

最佳做法注意事项

它保存了大量工作,以确保大型文件首先远离主存储库。 考虑到这一点,以下是团队要记住的一些常识最佳做法:

应做事项

  • 经常提交更改。 以后始终可以使用壁球或重设基来修复它们。
  • 请使用分支来隔离更改。 分支便宜,私人,合并很简单。 还可以通过将更改推送到服务器来备份分支上的更改。
  • 发布主题分支时,请使用命名约定。 将分支命名为“users/<alias>/<branchname>”。 这有助于对分支进行分组,并使其他人能够轻松识别“所有者”。
  • 请务必推送更改。 Commit != Checkin. (Commit + Push) == Checkin.
  • 请考虑对大型二进制文件使用 .gitignore ,以便它们不会首先添加到存储库中 - 此处的详细信息。
  • 请考虑使用 NuGet 或 TFS 版本控制来存储大型二进制文件。

禁止事项

  • 推送后不要重新定基。 在 git 中重新提交推送提交可能很糟糕,因为它会强制存储库中的其他人重新设置其本地更改的基数,如果他们需要这样做,他们就不会高兴。 除非其他人正在拉取这些提交,否则将推送提交重新分组到你自己的个人分支上(即使已推送)并不重要。
  • 不要将二进制文件提交到存储库。 Git 不会按照 TFVC 所做的方式压缩二进制文件,因为所有存储库都具有所有历史记录,因此提交二进制文件意味着永久膨胀。

摘要

有时,不需要的元素(如大型文件)会添加到存储库中,并且需要删除才能使存储库保持干净且轻型。 为此,可以使用命令获取本地存储库 git rebase ,然后使用 git push --force 命令将服务器存储库覆盖到本地存储库。

作者:爱德华·弗莱和杰西·侯文|与作者和 ALM |连接此处的 DevOps Rangers

(c) 2015 Microsoft Corporation。 保留所有权限.ÿ 提供了“原样”文档。本文档中表达的信息和视图(包括 URL 和其他 Internet 网站引用)可能会更改,而无需通知。 您自行承担其使用风险。

本文档未向您提供任何 Microsoft 产品中任何知识产权的任何合法权利。 可以复制本文档并将其用于进行内部参考。