如何在 Git 中选择性地删除提交

GitGitBeginner
立即练习

💡 本教程由 AI 辅助翻译自英文原版。如需查看原文,您可以 切换至英文原版

简介

Git 是一个强大的版本控制系统,它允许开发者有效地管理项目的历史记录。然而,随着时间的推移,你的 Git 提交历史可能会积累一些你想要删除的不必要或不想要的提交。本教程将指导你完成在 Git 中选择性地删除提交的过程,帮助你维护一个干净且有条理的仓库。


Skills Graph

%%%%{init: {'theme':'neutral'}}%%%% flowchart RL git(("Git")) -.-> git/BranchManagementGroup(["Branch Management"]) git(("Git")) -.-> git/BasicOperationsGroup(["Basic Operations"]) git(("Git")) -.-> git/DataManagementGroup(["Data Management"]) git/BasicOperationsGroup -.-> git/commit("Create Commit") git/DataManagementGroup -.-> git/reset("Undo Changes") git/BranchManagementGroup -.-> git/log("Show Commits") git/BranchManagementGroup -.-> git/reflog("Log Ref Changes") git/BranchManagementGroup -.-> git/rebase("Reapply Commits") subgraph Lab Skills git/commit -.-> lab-392950{{"如何在 Git 中选择性地删除提交"}} git/reset -.-> lab-392950{{"如何在 Git 中选择性地删除提交"}} git/log -.-> lab-392950{{"如何在 Git 中选择性地删除提交"}} git/reflog -.-> lab-392950{{"如何在 Git 中选择性地删除提交"}} git/rebase -.-> lab-392950{{"如何在 Git 中选择性地删除提交"}} end

Git 中选择性删除提交的介绍

Git 是一个强大的版本控制系统,它允许开发者随着时间的推移管理和跟踪代码库的更改。Git 的关键特性之一是能够维护详细的提交历史记录,这对于理解项目的演变和排查问题非常有用。然而,在某些情况下,开发者可能需要从仓库历史记录中选择性地删除或“剥离”某些提交。

这个过程被称为“选择性提交剥离”,在各种场景中都可能有用,例如:

  1. 删除敏感信息:如果某个提交意外包含敏感信息,如 API 密钥或密码,你可能希望从仓库历史记录中删除该提交,以保护这些数据的机密性。

  2. 清理提交历史记录:随着时间的推移,仓库的提交历史记录可能会变得杂乱,充斥着一些小的、不必要的提交,比如拼写错误修正或轻微的代码格式更改。选择性地删除这些提交有助于使历史记录更简洁,更易于浏览。

  3. 为重写做准备:如果你计划重写代码库的很大一部分,你可能希望选择性地删除某些提交,为新的工作创建一个更干净的基础。

在本教程中,我们将探讨在 Git 仓库中选择性删除提交的各种技术和最佳实践,确保你能够在保持项目整体完整性的同时,维护一个干净且有条理的提交历史记录。

理解 Git 提交历史记录和结构

在深入探讨选择性删除提交的过程之前,深入了解 Git 如何管理和存储提交历史记录非常重要。

Git 提交结构

在 Git 中,每个提交都由一个唯一的哈希值表示,这是一个 40 个字符的字符串,它唯一地标识了提交时仓库的状态。这个哈希值通常被称为“提交哈希”或“提交 ID”。

每个提交包含以下关键组件:

  1. 提交消息:对提交中引入的更改的简要描述。
  2. 作者:进行更改并提交的人。
  3. 时间戳:提交的日期和时间。
  4. 父提交:此提交所基于的前一个提交。
  5. 代码库快照:提交时代码库的完整状态。

可视化提交历史记录

Git 仓库中的提交历史记录可以可视化为有向无环图(DAG),其中每个提交都是一个节点,提交之间的父子关系由边表示。这种类似图的结构使 Git 能够有效地跟踪和管理代码库随时间的演变。

graph TD A[Commit A] --> B[Commit B] B --> C[Commit C] C --> D[Commit D] D --> E[Commit E] E --> F[Commit F]

理解这种提交结构和历史记录对于在 Git 仓库中有效地管理和操作提交历史记录至关重要。

识别不必要或不想要的提交

在你可以从 Git 仓库中选择性地删除提交之前,你需要识别哪些提交是不必要或不想要的。这个过程可能涉及查看提交历史记录、理解每个提交的上下文,并确定哪些提交可以在不影响项目整体完整性的情况下安全地删除。

查看提交历史记录

你可以使用 git log 命令来查看仓库中的提交历史记录。这个命令将显示所有提交的列表,包括它们的提交哈希、作者信息、提交消息和时间戳。

git log

在查看提交历史记录时,寻找以下可能适合选择性删除的提交类型:

  1. 琐碎提交:仅修复小错别字、格式问题或其他无关紧要更改的提交。
  2. 调试提交:仅为调试或测试目的而进行的提交,并不代表对代码库有意义的更改。
  3. 意外提交:意外进行的提交,例如提交了敏感信息或未完成的工作。
  4. 冗余合并:表示可以通过更好的分支策略避免的不必要合并冲突的提交。

分析提交上下文

除了查看提交历史记录外,理解每个提交的上下文也很重要。在评估一个提交的必要性时,考虑以下问题:

  1. 这个提交是否引入了重大更改或功能?
  2. 这个提交是项目开发历史的必要部分吗?
  3. 这个提交可以与其他相关提交合并,以创建更有意义和连贯的更改吗?

通过仔细分析每个提交的上下文和目的,你可以更有效地识别那些不必要或不想要的提交,并将它们列为选择性删除的优先级。

使用 Git Rebase 删除提交

在 Git 中选择性删除提交的主要工具是 git rebase 命令。变基(Rebase)允许你通过重新排列、删除或压缩提交来修改提交历史记录。这使其成为清理提交历史记录并删除不必要或不想要的提交的理想工具。

理解 Git Rebase

git rebase 命令会获取当前分支的提交,并将它们“重放”到指定的基础提交之上。这实际上允许你重写提交历史记录,包括删除特定提交的能力。

以下是使用 git rebase 的一般语法:

git rebase [选项] [ [ < 上游分支 > ] < 分支 > ]

<上游分支> 参数指定你要将提交变基到其上的基础提交,<分支> 参数指定你要进行变基的分支。

使用交互式变基删除提交

要选择性地删除提交,你需要使用交互式变基模式。这可以通过将 -i(或 --interactive)选项传递给 git rebase 命令来完成。

git rebase -i <基础提交>

这将打开一个编辑器窗口,显示将要被重写的提交列表。每个提交由一行表示,你可以通过编辑文件来修改提交的顺序或完全删除它们。

例如,要删除最后 3 个提交,你可以将文件编辑成如下样子:

pick 1a2b3c4 提交 1
pick 5e6f7g8 提交 2
pick 9h0i1j2 提交 3
## 删除了以下提交:
## pick a3b4c5d 提交 4
## pick e6f7g8h 提交 5
## pick i9j0k1l 提交 6

保存并关闭编辑器后,Git 将重写提交历史记录,删除指定的提交。

处理合并冲突

在变基过程中,如果要删除的提交涉及合并,你可能会遇到合并冲突。在这种情况下,Git 将暂停变基过程,并提示你手动解决冲突。

要解决冲突,你可以使用标准的 Git 冲突解决工具,例如使用 git status 来识别冲突文件,使用 git add 来暂存已解决的冲突。解决所有冲突后,你可以使用 git rebase --continue 继续变基过程。

通过掌握 git rebase 及其交互式模式的使用,你可以有效地从 Git 仓库的历史记录中删除不必要或不想要的提交,保持提交历史记录的干净和有条理。

在变基过程中处理合并冲突

当你使用 git rebase 选择性地删除提交时,可能会遇到的一个潜在挑战就是合并冲突的出现。当你试图删除的提交涉及到合并操作,并且 Git 无法自动解决这些更改时,就会产生合并冲突。

理解合并冲突

当 Git 无法自动协调在两个或多个要合并的提交中所做的更改时,就会发生合并冲突。当在要合并的提交中以不同方式修改了同一个文件时,就可能出现这种情况。

在变基过程中发生合并冲突时,Git 将暂停变基过程,并提示你手动解决冲突。

解决合并冲突

要在变基过程中解决合并冲突,你可以遵循以下步骤:

  1. 识别冲突文件:使用 git status 命令来识别有合并冲突的文件。
git status
  1. 打开冲突文件:在文本编辑器中打开冲突文件,查看更改并解决冲突。

  2. 解决冲突:在冲突文件中,你会看到指示冲突部分的标记。通过选择你想要保留的更改来手动编辑文件以解决冲突。

  3. 暂存已解决的冲突:解决冲突后,使用 git add 命令暂存已解决的文件。

git add <冲突文件>
  1. 继续变基:一旦所有冲突都已解决并暂存,你可以使用 git rebase --continue 命令继续变基过程。
git rebase --continue

如果你遇到任何其他合并冲突,请重复此过程,直到变基完成且没有任何冲突。

中止变基

如果你无法解决合并冲突,或者决定完全放弃变基过程,你可以使用 git rebase --abort 命令中止变基。

git rebase --abort

这将把你的仓库恢复到开始变基之前的状态。

通过了解如何在变基过程中处理合并冲突,你可以有效地应对在从 Git 仓库中选择性删除提交时可能出现的挑战。

保留提交元数据和历史记录

当你从 Git 仓库中选择性地删除提交时,确保保留提交历史记录的整体完整性非常重要,这包括与每个提交相关联的元数据。这些元数据,如作者、时间戳和提交消息,对于维护项目开发的上下文和可追溯性至关重要。

保留提交元数据

在变基过程中,Git 会自动保留正在被重写的提交的元数据。这意味着即使提交顺序或内容发生了变化,作者、时间戳和提交消息也会被保留。

然而,需要注意的是,如果你完全删除一个提交,与该提交相关联的元数据将会丢失。为了减轻这种情况,你可以考虑以下策略:

  1. 压缩提交:与其完全删除一个提交,你可以选择将它与前一个提交“压缩”在一起。这将保留前一个提交的元数据,并将更改合并到一个更有意义的提交中。

  2. 编辑提交消息:如果你需要修改你保留的提交的消息,可以在交互式变基过程中进行。

保留提交历史记录

除了保留单个提交的元数据外,维护提交历史记录的整体结构和脉络也很重要。如果你正在处理一个有多个协作者的项目,或者计划将你的更改推送到远程仓库,这一点尤其重要。

当使用 git rebase 选择性地删除提交时,Git 会自动更新剩余提交之间的父子关系,确保提交历史记录保持完整和连贯。

然而,如果你正在处理一个共享分支,或者已经将你的更改推送到远程仓库,在重写提交历史记录时你需要更加谨慎。在这些情况下,通常建议使用带有 --force-with-lease 选项的 git rebase 命令,以避免意外覆盖其他人的工作。

git rebase --force-with-lease

通过在选择性删除过程中仔细保留提交元数据和历史记录,你可以确保你的 Git 仓库保持其完整性,并且对你和你的团队来说仍然易于理解和导航。

使用交互式变基选择性删除提交

在 Git 中选择性删除提交的关键在于交互式变基功能。这个强大的工具允许你在将更改应用到仓库之前查看并修改提交历史记录。

使用交互式变基

要开始交互式变基过程,使用 git rebase -i 命令,后跟你想要将更改变基到其上的基础提交。

git rebase -i <基础提交>

这将打开一个编辑器窗口,显示将要被重写的提交列表。每个提交由一行表示,你可以通过编辑文件来修改提交的顺序或完全删除它们。

以下是交互式变基编辑器可能的样子示例:

pick 1a2b3c4 提交 1
pick 5e6f7g8 提交 2
pick 9h0i1j2 提交 3
pick a3b4c5d 提交 4
pick e6f7g8h 提交 5
pick i9j0k1l 提交 6

删除提交

要删除一个提交,只需从编辑器窗口中删除相应的行。例如,要删除第 4 和第 5 个提交,文件将如下所示:

pick 1a2b3c4 提交 1
pick 5e6f7g8 提交 2
pick 9h0i1j2 提交 3
## pick a3b4c5d 提交 4
## pick e6f7g8h 提交 5
pick i9j0k1l 提交 6

压缩提交

你也可以选择不直接删除提交,而是将它与前一个提交“压缩”在一起。这会将两个提交的更改合并到一个更有意义的提交中。要做到这一点,在你想要压缩的行上,将 pick 命令替换为 squash(或简写为 s)。

pick 1a2b3c4 提交 1
pick 5e6f7g8 提交 2
pick 9h0i1j2 提交 3
squash a3b4c5d 提交 4
squash e6f7g8h 提交 5
pick i9j0k1l 提交 6

保存并关闭编辑器后,Git 将重写提交历史记录,删除或压缩指定的提交。

处理合并冲突

如前所述,如果要删除的提交涉及合并,在变基过程中你可能会遇到合并冲突。在这种情况下,Git 将暂停变基并提示你按照上一节所述手动解决冲突。

通过掌握交互式变基的使用,你可以有效地从 Git 仓库中选择性地删除提交,保持一个干净且有条理的提交历史记录,该记录反映了你项目的真实演变过程。

选择性提交删除的最佳实践和策略

如你所知,从你的 Git 仓库中选择性地删除提交是维护干净且有条理的提交历史记录的一项强大技术。然而,遵循最佳实践和策略以确保你不会无意中引入问题或给团队带来麻烦是很重要的。

最佳实践

  1. 全面审查提交历史记录:在尝试删除任何提交之前,仔细审查提交历史记录,以识别不必要或不想要的提交。了解每个提交的上下文和目的,以便做出明智的决策。
  2. 确定要删除的提交的优先级:根据你确定要删除的提交的重要性及其删除可能产生的影响对它们进行排序。首先专注于删除影响最小的提交。
  3. 备份你的仓库:在对提交历史记录进行任何重大更改之前,始终创建仓库的备份。这将在变基过程中出现问题时提供一个安全保障。
  4. 与你的团队沟通:如果你在处理一个共享仓库,请确保将你选择性删除提交的计划告知你的团队。这将有助于避免冲突,并确保每个人都了解情况。
  5. 使用描述性提交消息:在重写提交历史记录时,确保使用清晰且描述性的提交消息,准确反映所做的更改。这将有助于维护项目开发的整体上下文和可追溯性。

选择性提交删除的策略

  1. 压缩提交:与其完全删除提交,不如考虑将它们压缩在一起,以保留元数据并保持更简洁的提交历史记录。
  2. 在稳定分支上进行变基:尽可能在稳定分支(如 maindevelop)上对你的更改进行变基,以最小化冲突风险,并确保你的更改与项目的其他部分干净地集成。
  3. 使用增量变基:不要试图一次性重写大部分提交历史记录,而是考虑将过程分解为更小、更易于管理的步骤。这将使识别和解决出现的任何问题变得更容易。
  4. 利用 Git 钩子:实现 Git 钩子,如 pre-commit 或 pre-push 钩子,以自动检查并防止在你的仓库中包含不想要的提交。
  5. 记录过程:记录你删除的提交以及这样做的原因。这将帮助你和你的团队了解项目的历史,并在未来做出明智的决策。

通过遵循这些最佳实践和策略,你可以有效且安全地使用选择性提交删除来维护一个干净且有条理的 Git 仓库,以支持你的项目的长期开发和维护。

总结

在本教程结束时,你将全面了解如何在 Git 中选择性地删除提交。你将学会识别不必要或不想要的提交,使用 Git 变基删除它们,处理合并冲突,以及保留重要的提交元数据和历史记录。此外,你还将发现通过选择性提交删除来有效管理 Git 提交历史记录的最佳实践和策略。