跳至内容
GitTree

课程 22 · 历史与融合

重新排序、压缩、重写和删除本地提交

将五个粗糙的私有提交变成两个干净的提交:移动依赖修复、重写消息、折叠和压缩步骤、仅删除噪音,并检查结果是否完全包含您想要的文件。

进度已保存在此浏览器中。

播放时会加载来自 YouTube 的视频(隐私增强模式)。

英文旁白 · English and Arabic 字幕

打开视频页面在 YouTube 上观看

你将学到什么

  • 阅读重播计划:最旧的步骤优先,从上到下应用。
  • 选择正确的操作:重写、压缩、修复或删除。
  • 移动一个步骤而不破坏它所依赖的步骤。
  • 之后验证新的提交、文件和救援分支。

开始之前

您的分支 private/signup-polish 有五个提交,仅存在于您的计算机上,位于提交 M 之上。工作树是干净的,并且 rescue/before-polish 指向第五个提交。按顺序,最旧的在前:

步骤提交它的作用
C1壮举:添加注册草稿添加注册表单
C2文档:解释注册审核添加 docs/replay-a.md
C3文档:解释验证添加 docs/replay-b.md
C4修复!壮举:添加注册草稿修复表单的标签
C5琐事:临时笔记添加 docs/temporary-review.md

一切都是本地的并且采用免费套餐(GitTree 要求您登录):没有托管帐户、没有提供商、没有互联网。每个身份都是虚构的(example.com)。切勿在真实项目中运行本课程,也切勿重写其他人已经拥有的提交。

在 GitTree 中或使用本机 Git 命令进行更改,而不是在同一副本上进行更改。读取结果总是安全的。菜单标签来自 GitTree 2.0 自己的字符串,本机命令使用 Git 2.43 在一次性副本中运行。 GitTree 步骤未在 macOS、Windows 或 Linux 上运行。

概念和状态效应

交互式变基是一个计划,而不是排序游戏。 Git 从列表顶部到底部逐个重播列出的提交,因此最早的步骤排在最前面。每个操作都告诉 Git 在一个步骤中要做什么:

  • Pick 保持提交原样。
  • Reword 保留其内容并允许您编写新消息。
  • Squash 将提交折叠到其上方保留的提交中,并允许您编写一条组合消息。
  • Fixup 也将其折叠起来,但丢弃了它自己的消息。
  • Drop 完全保留提交的更改。

顺序很重要。依赖于另一个步骤的步骤(此处标签修复需要 C1 中的表格)必须位于其下方。编辑器会让你将其移到上面,然后重播会因冲突而停止。 GitTree 还拒绝 Git 无法运行的计划:删除每个提交的计划、上面没有任何内容可折叠的挤压以及空消息。

每个重播的提交都会获得一个新的 ID,因为它的父级发生了变化。仅重写该分支;救援部门保留了老五。已经在远程上的提交被标记为“在远程上”,并且重写它们需要明确的确认。这个教训从未证实这一点。

您将制定的计划将五个提交变成两个:

步骤提交行动结果
1C1改写壮举:填写本地注册表单
2C4修正折叠到步骤1中
3C3挑选保留;挤压目标
4C2壁球文档:解释注册审核和验证
5C5掉落消失了

准备准确的项目状态

从第 18 课留下的项目的单独普通副本开始。保持原来的 gittree-features 不变。在一个新分支上构建下面的五个提交,一次一个文件,并仅在其指定的步骤中保存每个完整的正文。

完整的文件输入

仅在下面指定的阶段保存。这些是完整的 UTF-8/LF 正文,最后有换行符;永远不要粘贴 Markdown 栅栏。未更改的可运行文件继承命名输入。单独变体中的版本不得覆盖原始版本。

index.html — 注册

文件摘录 · html
<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>GitTree Features — course demo</title>
  <link rel="stylesheet" href="styles.css">
</head>
<body>
  <header class="site-header">
    <a href="#main">GitTree Features</a>
  </header>
  <main id="main" tabindex="-1">
    <section class="hero" aria-labelledby="hero-title">
      <p class="eyebrow">GitTree Learn demo project</p>
      <h1 id="hero-title">See your work clearly.</h1>
      <p id="hero-copy">Choose one change, then check what Git saved.</p>
    </section>
    <section class="features" aria-labelledby="features-title">
      <h2 id="features-title">Follow your work</h2>
      <div class="cards">
        <article class="feature-card">
          <h3>History</h3>
          <p>Read commits and branches together.</p>
        </article>
        <article class="feature-card">
          <h3>Changes</h3>
          <p>Review the exact content selected for a commit.</p>
        </article>
        <article class="feature-card">
          <h3>Recovery</h3>
          <p>Inspect the scope of a recovery point before using it.</p>
        </article>
      </div>
    </section>
    <section aria-labelledby="plans-title">
      <h2 id="plans-title">Choose the workflow you need</h2>
      <div class="cards">
        <article class="feature-card">
          <h3>Local Git</h3>
          <p>Local Git workflows work without signing in.</p>
        </article>
        <article class="feature-card">
          <h3>Connected workflows</h3>
          <p>Provider integrations and Nour require Pro or an applicable trial.</p>
        </article>
      </div>
    </section>
    <section aria-labelledby="signup-title">
      <h2 id="signup-title">Try the demo form</h2>
      <form id="signup-form" novalidate>
        <label for="demo-email">Demo email</label>
        <input id="demo-email" name="email" type="email" autocomplete="off" aria-describedby="signup-hint">
        <p id="signup-hint">Use a fictional example.com address. Nothing is sent.</p>
        <button type="submit">Check the address locally</button>
        <p id="signup-result" role="status"></p>
      </form>
    </section>
  </main>
  <footer><p>Built by a fictional team for GitTree Learn. Review one change at a time.</p></footer>
  <script type="module" src="site.js"></script>
</body>
</html>

文档/replay-a.md — DOC_A

输出
# Local signup review

Review the label and hint together.

文档/replay-b.md — DOC_B

输出
# Local validation review

No address leaves this demonstration.

index.html — SIGNUP_LABEL

文件摘录 · html
<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>GitTree Features — course demo</title>
  <link rel="stylesheet" href="styles.css">
</head>
<body>
  <header class="site-header">
    <a href="#main">GitTree Features</a>
  </header>
  <main id="main" tabindex="-1">
    <section class="hero" aria-labelledby="hero-title">
      <p class="eyebrow">GitTree Learn demo project</p>
      <h1 id="hero-title">See your work clearly.</h1>
      <p id="hero-copy">Choose one change, then check what Git saved.</p>
    </section>
    <section class="features" aria-labelledby="features-title">
      <h2 id="features-title">Follow your work</h2>
      <div class="cards">
        <article class="feature-card">
          <h3>History</h3>
          <p>Read commits and branches together.</p>
        </article>
        <article class="feature-card">
          <h3>Changes</h3>
          <p>Review the exact content selected for a commit.</p>
        </article>
        <article class="feature-card">
          <h3>Recovery</h3>
          <p>Inspect the scope of a recovery point before using it.</p>
        </article>
      </div>
    </section>
    <section aria-labelledby="plans-title">
      <h2 id="plans-title">Choose the workflow you need</h2>
      <div class="cards">
        <article class="feature-card">
          <h3>Local Git</h3>
          <p>Local Git workflows work without signing in.</p>
        </article>
        <article class="feature-card">
          <h3>Connected workflows</h3>
          <p>Provider integrations and Nour require Pro or an applicable trial.</p>
        </article>
      </div>
    </section>
    <section aria-labelledby="signup-title">
      <h2 id="signup-title">Try the demo form</h2>
      <form id="signup-form" novalidate>
        <label for="demo-email">Fictional email address</label>
        <input id="demo-email" name="email" type="email" autocomplete="off" aria-describedby="signup-hint">
        <p id="signup-hint">Use a fictional example.com address. Nothing is sent.</p>
        <button type="submit">Check the address locally</button>
        <p id="signup-result" role="status"></p>
      </form>
    </section>
  </main>
  <footer><p>Built by a fictional team for GitTree Learn. Review one change at a time.</p></footer>
  <script type="module" src="site.js"></script>
</body>
</html>

docs/temporary-review.md — DOC_NOISE

输出
Temporary rehearsal note, deliberately dropped.

在GitTree

使用 Command+Shift+P(在 Ubuntu 上为 Ctrl+Shift+P)打开调色板。提交上的操作使用该提交的右键单击菜单。

  1. 构建五个提交和救援分支,如下一节所示,其中 private/signup-polish 已签出并清理。注意M和五个科目。
  2. 右键单击 M(五个正下方的提交),然后选择 Edit History → Interactive Rebase of the Commits Above…。编辑器以五个私人步骤开始,最旧的在前。
  3. 在 Options for this rebase 下,保留所有三个选项,包括 Arrange fixup!, squash! and amend! commits。您将自行移动修复程序。
  4. 聚焦 C4 行并按 Alt+↑ 两次,然后聚焦 C3 行并按 Alt+↑ 一次。现在的顺序是 C1、C4、C3、C2、C5。在焦点行上按 p、r、e、s、f 或 d 可设置“拾取”、“改写”、“编辑”、“挤压”、“修复”或“删除”。
  5. 将 C1 设置为 Reword 并在其消息字段中输入 feat: complete the local signup form。将 C4 设置为 Fixup。
  6. 将 C3 保留为 Pick,将 C2 设置为 Squash。在 Squashed commits 下,“2 提交到文档:解释验证”组显示一条组合消息。将其替换为 docs: explain signup review and validation。
  7. 将 C5 设置为 Drop。再次阅读每一行和组合消息。没有任何内容被标记为“在远程”,因此不需要确认。
  8. 选择 Start Rebase 一次并等待。如果停止,请使用横幅继续;不要再次开始整个计划。
  9. 验证两个新提交、页面中的标签修复、两个文档且没有临时注释。保留 rescue/before-polish,并保持工作树干净。

对于课程中的每个普通提交:Summary 是规定的主题,Description 为空,并且选项 Amend Previous Commit、Skip Hooks、Add Signed-off-by、Different Author、Push After Commit 和 Allow Empty Commit 保持关闭状态。

在航站楼

在新分支上构建五个提交,并在其步骤中保存每个完整的正文:

Command · bash
git switch --create private/signup-polish

将 SIGNUP 保存为 index.html,然后:

Command · bash
git add -- index.html
git commit --quiet -m "feat: add signup draft"

将 DOC_A 保存为 docs/replay-a.md,然后:

Command · bash
git add -- docs/replay-a.md
git commit --quiet -m "docs: explain signup review"

将 DOC_B 保存为 docs/replay-b.md,然后:

Command · bash
git add -- docs/replay-b.md
git commit --quiet -m "docs: explain validation"

将 SIGNUP_LABEL 保存为 index.html,然后:

Command · bash
git add -- index.html
git commit --quiet -m "fixup! feat: add signup draft"

将 DOC_NOISE 保存为 docs/temporary-review.md,然后:

Command · bash
git add -- docs/temporary-review.md
git commit --quiet -m "chore: temporary note"

保护旧的提示并列出范围,最旧的在前:

Command · bash
git branch rescue/before-polish
BASE_SHA="$(git rev-parse HEAD~5)"
git log --reverse --format=%s "$BASE_SHA"..HEAD

现在开始交互式变基(-i 是 --interactive 的缩写形式)。 Git 打开带有待办事项列表的编辑器(您的 ID 会有所不同):

Command · bash
git rebase --interactive --no-autosquash --no-update-refs --no-autostash "$BASE_SHA"
输出
pick 1a2b3c4 feat: add signup draft
pick 2b3c4d5 docs: explain signup review
pick 3c4d5e6 docs: explain validation
pick 4d5e6f7 fixup! feat: add signup draft
pick 5e6f708 chore: temporary note

将五行重写到计划中,保留每行自己的 ID,然后保存:

输出
reword 1a2b3c4 feat: add signup draft
fixup 4d5e6f7 fixup! feat: add signup draft
pick 3c4d5e6 docs: explain validation
squash 2b3c4d5 docs: explain signup review
drop 5e6f708 chore: temporary note

然后 Git 再打开编辑器两次。对于改写,请将消息替换为 feat: complete the local signup form。对于壁球,它显示这两条消息;将它们替换为一行 docs: explain signup review and validation。检查结果:

Command · bash
git rev-list --count "$BASE_SHA"..HEAD
git log --reverse --format=%s "$BASE_SHA"..HEAD
git status --short
输出
2
feat: complete the local signup form
docs: explain signup review and validation

状态为空。 index.html 是 SIGNUP_LABEL,两个文档都存在,而 docs/temporary-review.md 不存在。

如果您在第一行放置一个挤压,Git 会立即停止并显示 error: cannot 'squash' without a previous commit。使用 git rebase --edit-todo 和 git rebase --continue 修复列表,或使用 git rebase --abort 离开。使用 --autosquash,Git 会为您执行移动和提交 fixup! 的操作;本课将其关闭以显示计划。

结果

Where you end: M 之上的两个重写提交,“feat:完成本地注册表单”和“docs:解释注册审核和验证”。该页面有标签修复,两个文档都在那里,但临时注释不在那里。旧的五个提交由救援分支保存,工作树是干净的。

常见错误

  • 使用 Drop 隐藏您可能需要的提交。这种变化根本不在新历史中。
  • 将修复移至其修复的提交之上。
  • 压扁第一步,上面没有任何东西可以折叠。
  • 计划完成后重新开始,而不是先检查结果。

如果出现问题

在开始之前,Cancel 会保持分支不变。如果 GitTree 表示分支自编辑器打开以来发生了更改,请关闭编辑器并再次打开它。如果变基停止,请修复冲突或消息并从横幅继续,或故意中止它。完成后,请先与 rescue/before-polish 进行比较,然后再尝试恢复任何内容。

检查你的理解情况

回答每个问题,然后阅读原因。标记为“必填”的问题将有助于完成本课程。

  1. 第 1 题,共 6 题

    在交互式变基的待办事项列表中,首先重播哪个提交?

    选择一个答案。

  2. 第 2 题,共 6 题

    这些计划中哪一个不能实施?

    选择每个适用的答案。

  3. 第 3 题,共 6 题
    必填

    计划是:重写C1,修复C4,选择C3,压缩C2,删除C5。运行后,M以上的commit有多少,临时note的文件去了哪里?

    选择一个答案。

  4. 第 4 题,共 6 题

    更改输入:将 C5 保留为 Pick 而不是 Drop。有什么不同?

    选择一个答案。

  5. 第 5 题,共 6 题
    必填

    您将步骤 1 设置为 Squash,并且 GitTree 拒绝启动:“步骤 1 压缩为空:将其移至保留的提交下方。”这是什么意思,你会做什么?

    选择一个答案。

  6. 第 6 题,共 6 题
    必填

    哪些回读证明结果是计划想要产生的结果?

    选择每个适用的答案。

0 个(共 6 个)正确

正确回答所需的问题以完成课程。

在此浏览器中检查。

练习

解释计划 C1、C4、C3、C2、C5 以及保留下来的两条消息。检查旧范围 5、新范围 2、预期文件,但没有注释。然后在不运行的情况下预测为什么将 C4 移动到 C1 上方或压缩步骤 1 不起作用。

您自己的确认:该网站无法看到您的计算机。

要完成本课程,请正确回答所需的问题并确认实践练习。

回顾

  • 重播计划具有顺序和依赖性。
  • Squash 会保留这两条消息供您组合; fixup 会丢弃自己的。
  • 丢弃会删除更改本身,因此只丢弃真正的噪音。

术语表介绍

改写 — ¡¡¡¡¡¡¡壁球 — жмّ;修复 — 修复并修复;掉落 — ¡重播计划 — 重播计划。

视频文字记录

视频的旁白,逐条提示。

显示成绩单
  1. 五个粗糙的提交变成两个干净的提交, 安全。
  2. 交互式变基是一个计划:一个列表 步骤,最旧的在前。
  3. Git 从上到下重播列表 一个基地。
  4. 每个步骤都有一个动作:选择、改写、 挤压、修复或丢弃。
  5. 首先,构建五个私有提交和一个 救援分会。
  6. 三是实实在在的工作。一个是修复,一个是 是暂时的噪音。
  7. 右键单击它们下面的提交,然后 打开编辑历史记录。
  8. 选择提交的交互式变基 以上。
  9. 小编列出了五个步骤,最古老的 首先。
  10. 关闭所有三个选项。我们会搬家 我们自己修复。
  11. 修复程序在提交之后立即生效 它修复了。将其向上移动两次。
  12. 现在将验证注释移至 复习笔记。
  13. 现在的顺序是一、四、三、二、 五.
  14. 将第一步设置为Reword,然后写入 新消息。
  15. 将修复步骤设置为 Fixup。它的信息 被扔掉了。
  16. 保留验证记录,并压扁 查看注释。
  17. Squash 显示这两条消息。写一个 给这对的消息。
  18. 放下临时笔记。它的改变将 无法生存。
  19. 再次阅读每一行。上面什么都没有 远程。
  20. 选择一次Start Rebase,然后等待 完成。
  21. 该图现在在上面有两个提交 基地。
  22. 两人都有新的身份证。老五都在 救援分会。
  23. 打开页面:标签修复就在那里。的 噪音消失了。
  24. 现在航站楼也有同样的计划, git rebase -i。
  25. Git 打开待办事项列表。最旧的第一个,全部 设置为选择。
  26. 将这些内容重写到我们的计划中:重写, 修复、拾取、挤压、掉落。
  27. Git 要求提供这两条消息。写一个 每条线。
  28. 计算基础之上的提交:两次。
  29. 列出科目。这是我们两个 写道。
  30. 状态为空,临时备注为 走了。
  31. 更改输入:将南瓜放在 第一步。
  32. 它上面没有任何东西可以折叠,所以 吉特拒绝了。
  33. 或者将修复程序移至其提交之上: 重播因冲突而停止。
  34. 如果停止,请修复它并继续。或者 中止,并且没有任何变化。
  35. 救援部门仍然保留着你 原来的五次提交。
  36. 永远不要重写别人的提交 已经有了。
  37. 练习:解释计划以及为什么要采取步骤 一个不可能是南瓜。
  38. 接下来,解决合并或合并时的冲突 变基停止。