跳至内容
GitTree

课程 25 · 历史与融合

使用cherry-pick应用选定的提交

将一名队友的修复复制到您的发布分支上,而不合并她的整个分支,然后检查新的提交、其作者、文件以及留下的内容。

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

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

英文旁白 · English and Arabic 字幕

打开视频页面在 YouTube 上观看

你将学到什么

  • 选择要复制的一个提交,然后看看为什么它的父项没有出现。
  • 预测新提交的 ID、作者和提交者。
  • 在强制执行任何操作之前,先识别缺失的依赖项或已应用的更改。
  • 根据源分支检查结果。

开始之前

Priya 的分支 priya/label 在共享基线 B(注册页面)之上保存了两个提交。第一个是不相关的注释,“docs:不相关的源注释”,添加了 docs/temporary-review.md。第二个是她的修复,“修复:澄清虚构的电子邮件标签”,它更改了 index.html 中的标签。您的分支 release/label 从相同的基线 B 开始,并拥有自己的一项提交“docs:记录目标审核”,该提交添加了 docs/integration-note.md。 release/label 已签出,工作树是干净的。你希望她修复你的分支,而不是她的笔记。

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

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

概念和状态效应

Cherry-pick 获取一次提交所做的更改,根据其自己的父级进行衡量,并将其作为 new 提交应用到您所在的分支。它不会带来父级,也不会带来其之前的提交。这就是为什么你可以接受 Priya 的修复并留下她的便条。

源提交未被触及。新的提交有一个新的 ID,因为它有一个新的父提交,但它保留了原始作者和消息。提交者,即做出此提交的人,就是您。具有相同消息的相同更改仍然是不同的提交。

依赖性仍然很重要。该修复会编辑注册表单的一行,因此目标分支必须已经具有该表单。如果不存在,Git 将因冲突而停止。如果目标已经包含相同的更改,则选择将为空并且 Git 再次停止。在这两种情况下,请查看操作说明;不要仅仅为了过去而强行进行空提交。

只有目标分支移动。 priya/label 并且服务器上的所有内容都保持原样。新提交将标签更改添加到 release/label,仅此而已。

准备准确的项目状态

从第 18 课留下的项目的单独普通副本开始,并保持原始的 gittree-features 不变。将 SIGNUP 保存为基线,然后构建两个分支。下面的正文是基线页面 (SIGNUP)、不相关的注释 (DOC_NOISE)、固定页面 (SIGNUP_LABEL) 和您自己的注释 (DOC_MERGE)。

完整的文件输入

仅在下面指定的阶段保存。这些是完整的 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>

docs/temporary-review.md — DOC_NOISE

输出
Temporary rehearsal note, deliberately dropped.

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/integration-note.md — DOC_MERGE

输出
# Integration review

This note was written on main while signup work was private.

在GitTree

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

  1. 构建基线和两个分支,如下一节所示。检查 release/label 并确认工作树是干净的。
  2. 在图中找到 Priya 的提交“修复:澄清虚构的电子邮件标签”,而不是其下面的注释。选择它并阅读其详细信息:一个已更改的路径 index.html,其父级是不相关的注释。
  3. 右键单击该提交并选择 Cherry-Pick Commit。它立即适用于您所在的分行;没有分支选择器。该命令在当前提交上被禁用。
  4. 等待真正的结果。如果操作停止,请在横幅上使用 Resolve、Continue 或 Abort…,而不是再次选择。
  5. 选择 release/label 上的新提交。它的 ID 与 Priya 不同,作者是 Priya Nair,提交者是 GitTree Demo。
  6. 打开index.html:它是SIGNUP_LABEL。 docs/temporary-review.md 不存在,而您自己的 docs/integration-note.md 存在。 priya/label 仍以其旧的提示命名。
  7. 保持 release/label 干净。不要推送,也不要合并 priya/label。

如果您在图表中选择两个或多个提交,菜单会提供 Cherry-Pick Commits 并按顺序复制它们。本课抄一。

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

在航站楼

在第 18 课结果的单独副本中,在保存注册之前创建基线分支:

Command · bash
git switch --create label-base

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

Command · bash
git add -- index.html
git commit --quiet -m "feat: prepare the shared signup baseline"
BASE_SHA="$(git rev-parse HEAD)"
git switch --create priya/label

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

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

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

Command · bash
git add -- index.html
git -c user.name="Priya Nair" -c user.email=priya@example.com commit --quiet -m "fix: clarify the fictional email label"
PICK_SHA="$(git rev-parse HEAD)"
git switch --create release/label "$BASE_SHA"

将 DOC_MERGE 保存为 docs/integration-note.md,然后:

Command · bash
git add -- docs/integration-note.md
git commit --quiet -m "docs: record target review"

现在选择修复并读取结果:

Command · bash
git cherry-pick "$PICK_SHA"
git log -1 --format='%s%n%an <%ae>%n%cn <%ce>'
git diff-tree --no-commit-id --name-only -r HEAD
git status --short
输出
fix: clarify the fictional email label
Priya Nair <priya@example.com>
GitTree Demo <demo@example.com>
index.html

新提交的 ID 与 PICK_SHA 不同,index.html 是 SIGNUP_LABEL,docs/temporary-review.md 不存在且状态为空。要知道的两种变体,在单独的副本中运行,而不是在规范的副本中运行: git cherry-pick -x "$PICK_SHA" 将行“(cherry pick from commit ...)”添加到新消息中,这在您跨共享分支进行选择时会有所帮助;在缺少注册表单的目标上,相同的命令会因 index.html 上的冲突而停止,您可以解决该冲突(第 23 课)或使用 git cherry-pick --abort 保留。如果目标已经有更改,Git 会再次停止并出现空选择,而 git cherry-pick --skip 或 --abort 是出路。

结果

Where you end: release/label 有一个包含 Priya 修复的新提交,由 Priya Nair 创作,由 GitTree Demo 提交,并具有新的 ID。该页面具有澄清的标签,不相关的注释没有出现,priya/label 和服务器没有变化,工作树是干净的。

常见错误

  • 考虑选择樱桃会移动提交。它复制更改;原件保留在原来的位置。
  • 选择错误的提交、不相关的注释而不是修复。
  • 当更改已在分支上时强制执行空提交。
  • 使用cherry-pick 复制整个功能,一次提交一个,而不是合并它。

如果出现问题

如果拾取停止,请阅读横幅。 Resolve 和 Continue 按照第 23 课的方法完成; Abort… 将分支返回到原来的位置。如果完成后选择是错误的,则新提交仅在 release/label 上:在那里撤消它,并且源分支从未被触及。

检查你的理解情况

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

  1. 第 1 题,共 6 题

    cherry-pick 复制什么?

    选择一个答案。

  2. 第 2 题,共 6 题

    选择之后,关于新提交,哪些是正确的?

    选择每个适用的答案。

  3. 第 3 题,共 6 题
    必填

    Priya 的修复位于不相关的注释提交之上。您仅挑选对 release/label 的修复。之后 docs/temporary-review.md 是否在 release/label 上?

    选择一个答案。

  4. 第 4 题,共 6 题

    更改输入:release/label 没有 Priya 修复编辑的注册表单。当你选择时会发生什么?

    选择一个答案。

  5. 第 5 题,共 6 题
    必填

    你选择一个提交,Git 会停止并显示“先前的选择现在为空”。更改已在您的分支上。你做什么工作?

    选择一个答案。

  6. 第 6 题,共 6 题
    必填

    哪些回读表明该选择按照课程内容进行了操作?

    选择每个适用的答案。

0 个(共 6 个)正确

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

在此浏览器中检查。

练习

报告新提交的 ID、作者和提交者、其更改的路径以及 docs/temporary-review.md 是否存在。然后预测如果您再次在 release/label 上选择相同的提交会发生什么。

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

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

回顾

  • Cherry-pick 将一个提交的更改复制为新的提交。
  • 父级和它之前的提交会留在后面。
  • 在强制执行任何操作之前检查依赖关系和空选择。

术语表介绍

樱桃挑选——源代码提交 — 详细信息;目标 — α;依赖性—— औंे。

视频文字记录

视频的旁白,逐条提示。

显示成绩单
  1. 从另一个分支获取一个修复,然后 留下其余的。
  2. Cherry-pick 复制一次提交的更改 在这里作为一个新的提交。
  3. 该副本具有新的 ID,但保留 作者和消息。
  4. 建立一个基线,Priya 的分支 注意和修复,以及您的发布分支。
  5. 打开文件夹。该图显示了两者 来自同一基线的分支。
  6. Priya 的修复位于一个不相关的问题之上 注意。我们只想要修复。
  7. 选择修复。一种改变了路径: 索引.html。
  8. 确保发布标签是最新的,并且 工作树是干净的。
  9. 右键单击修复,然后选择 挑选承诺。
  10. 没有分支选择器。它适用于 您所在的分支。
  11. 在当前提交本身上,命令 已禁用。
  12. 运行一下,等待真正的结果。
  13. 新的提交位于发布标签上。
  14. 它的 ID 与 Priya 不同,因为它 父母不同。
  15. 作者依然是Priya。提交者 是你。
  16. 该页面有明确的标签。
  17. 不相关的便条没有出现。 你自己的笔记还在这里。
  18. Priya的分店还是原来的样子。
  19. 在终端中,使用以下格式进行 git log 显示主题、作者和提交者。
  20. git diff-tree 列出了这个路径 提交已更改。
  21. 状态为空。什么都没有留下 后面。
  22. 使用 x 选项,消息记录 选秀权是从哪里来的。
  23. 再次选择相同的提交,Git 将停止: 镐是空的。
  24. 更改输入:目标没有注册 形式。
  25. 选秀因冲突而停止。解决 并继续,或中止。
  26. 更改可能取决于您未进行的提交 采取。测试目标。
  27. 中止将分支放回原处。来源是 从未修改过。
  28. 做法:报告新的ID、作者、 提交者和文件。
  29. 接下来,将未完成的工作安全地放在一边 与藏匿。