跳至内容
GitTree

课程 23 · 恢复

解决合并和变基冲突

在合并和变基中解决相同的竞争标题,了解为什么“我们的”和“他们的”在它们之间交换,保存一个经过深思熟虑的组合结果,并在不丢失任何人的想法的情况下完成每一项操作。

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

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

英文旁白 · English and Arabic 字幕

打开视频页面在 YouTube 上观看

你将学到什么

  • 读取真实的冲突:基地、当前方和传入方。
  • 解释为什么“我们的”和“他们的”在合并和变基之间交换。
  • 写下一项深思熟虑的决议,然后将其标记为已解决。
  • 继续操作并检查是否有任何半途而废的情况。

开始之前

两个队友更改了页面的同一行。 conflict/sara,Sara 将主标题更改为“自信地审查更改”。在 conflict/omar,Omar 将同一行更改为“了解每个已保存的更改”。两个分支都从提交 M 开始,其中标题是“清楚地看到你的工作。”,并且每个分支只有一个提交。您为此分歧制作两份相同的副本:一份用于合并 (gittree-conflict-merge),一份用于变基 (gittree-conflict-rebase)。在这两种情况下,conflict/sara 都被签出并且工作树是干净的。没有合并或变基正在运行。

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

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

概念和状态效应

内容冲突意味着 Git 无法自行选择一个结果:双方对同一行进行了不同的更改。 Git 停止并在索引中保留该文件的三个版本:第 1 阶段是公共基础,第 2 阶段是“我们的”,第 3 阶段是“他们的”。它还将冲突标记写入工作树中的文件中。删除编辑器中的标记不会解决 Git 的任何问题:只有当您保存结果并将其暂存时,文件才会被解析,这会返回阶段 0。

“我们的”和“他们的”是立场,而不是人。在合并中,您位于 Sara 的分支,因此我们的版本是 Sara 的版本(当前侧),而他们的版本是 Omar 的版本(传入侧)。在 Sara 到 Omar 的 rebase 中,Git 首先移动到 Omar 的分支,然后重放 Sara 的提交,因此我们的版本是 Omar 的版本(您要 rebase 的分支),而他们的版本是 Sara 的提交。 GitTree 在每个名称旁边打印角色,这样您就不必记住:合并中​​的“(当前)”和“(传入)”,变基中的“(变基到)”和“(您的提交)”。

正确的结果很少是一侧的。这里的预期决议是“充满信心地审查每个更改。”,这既不是萨拉的路线,也不是奥马尔的路线。使页面的所有其他行保持原样。将文件标记为已解决阶段您的结果; continue 是一个单独的步骤,用于完成合并提交或在 Omar 上重新创建 Sara 的提交。

当操作停止时,分支是操作离开的位置并且文件发生冲突。没有任何内容到达服务器。

准备准确的项目状态

做一个分歧,然后复制两次。从第 18 课留下的项目的单独普通副本开始,并保持原始的 gittree-features 不变。页面版本如下:MERGED 是共享库,SARA 和 OMAR 是两个竞争版本,RESOLVED 是您将保存的结果。

完整的文件输入

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

index.html — SARA

文件摘录 · 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">Review changes with confidence.</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>
  </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>

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">Understand each saved change.</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>
  </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>

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">Review each change with confidence.</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>
  </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>

在GitTree

使用 Command+Shift+P(在 Ubuntu 上为 Ctrl+Shift+P)打开调色板。对指定分支的操作​​使用该分支的右键单击菜单。

  1. 如下一节所示构建两个副本。打开 gittree-conflict-merge,签出 conflict/sara。
  2. 右键单击 conflict/omar 并选择 Merge conflict/omar into conflict/sara。在 Record it as 下选择 Always a merge commit。该对话框警告“将因 1 个文件中的冲突而停止”;选择Merge。合并停止,这是预期的结果。
  3. 横幅上写着“将冲突/omar 合并到冲突/sara”和“1 个冲突”,而 Continue 尚不可用:“首先解决 1 个冲突”。选择Resolve。
  4. 从 Conflicted files 打开 index.html。读取两侧 conflict/sara (current) 和 conflict/omar (incoming),并使用 Show Base 读取 Base (common ancestor)。
  5. 选择 Edit Output,将冲突的标题替换为 Review each change with confidence. 并保留每隔一行。然后选择Save and Mark Resolved。删除标记并关闭文件是不够的。
  6. 返回横幅上,选择 Continue。如果提供了一条消息,请保留提议的消息。等待合并完成:新提交有两个父提交。
  7. 打开 gittree-conflict-rebase,签出 conflict/sara。右键单击 conflict/omar 并选择 Rebase conflict/sara onto conflict/omar。将 Options for this rebase 下的选项保留为关闭状态,然后选择 Rebase conflict/sara。它因冲突而停止。
  8. 选择 Resolve 并打开 index.html。双方现在是 conflict/omar (rebasing onto) 和 conflict/sara (your commit):角色交换了。执行相同的 Edit Output → Save and Mark Resolved,然后 Continue。
  9. 检查两个副本:文件等于“已解决”,没有留下任何冲突文件,并且没有显示横幅。将两个结果分开,不要推挤。

对于课程中的每个普通提交: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 conflict/sara
BASE_SHA="$(git rev-parse HEAD)"

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

Command · bash
git add -- index.html
git -c user.name="Sara Lindqvist" -c user.email=sara@example.com commit --quiet -m "feat: Sara clarifies the hero"
git switch --quiet --create conflict/omar "$BASE_SHA"

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

Command · bash
git add -- index.html
git -c user.name="Omar Haddad" -c user.email=omar@example.com commit --quiet -m "feat: Omar explains the hero"
git switch --quiet conflict/sara

BASE_SHA 是 M,在任一竞争提交之前。将此分歧制作两份干净的副本,一份用于合并,一份用于变基 (cd .. && cp -R gittree-features gittree-conflict-merge && cp -R gittree-features gittree-conflict-rebase)。在合并副本中:

Command · bash
git merge --no-ff --no-edit conflict/omar
git ls-files --unmerged
git show :2:index.html
git show :3:index.html

合并以退出代码 1 停止,git ls-files --unmerged 列出三个条目,阶段 1、2 和 3。git show :2:index.html 是 Sara 的版本(我们的),:3: 是 Omar 的(他们的); :1: 是基础。将 RESOLVED 保存为 index.html,然后:

Command · bash
git add -- index.html
git -c core.editor=true merge --continue
git ls-files --unmerged
git status --short

最后两个命令不打印任何内容。在未触及的变基副本中:

Command · bash
git rebase conflict/omar
git show :2:index.html
git show :3:index.html

变基停止。现在,:2: 是 Omar 的版本,而 :3: 是 Sara 的版本:角色交换了。将 RESOLVED 保存为 index.html,然后:

Command · bash
git add -- index.html
git -c core.editor=true rebase --continue
git ls-files --unmerged
git status --short

现在,两个文件都已解析,并且没有任何内容未合并。 core.editor=true 只接受该命令的现有提交消息;它不会更改您的编辑器设置。要保留已停止的操作而不进行解析,请使用 git merge --abort 或 git rebase --abort。

结果

Where you end: 合并副本有一个新提交,其中包含两个父项和组合标题;变基副本在奥马尔的提交上重新创建了萨拉的提交,并具有相同的组合标题。在这两种情况下,index.html 等于 RESOLVED,没有留下任何冲突条目,操作结束并且状态为干净。

常见错误

  • 假设“我们的”始终意味着您自己的特征。这意味着 Git 站在哪一边,并且随着操作的不同而变化。
  • 在阅读两个版本和文件的其余部分之前,先批发一侧(“全部”)。
  • 删除冲突标记,但从不保存并将文件标记为已解决。
  • 重复已经完成的合并或变基。

如果出现问题

如果停止看起来错误,则横幅中的 Abort… 会恢复操作开始时的状态,并放弃迄今为止所做的决议; GitTree 首先保留恢复快照。如果文件在编辑时发生更改,请使用 Compare 和 Use as Output 选项,而不是强制旧的保存。在替换之前保留草稿的副本。

检查你的理解情况

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

  1. 第 1 题,共 6 题

    您位于 conflict/sara 并将 conflict/omar 合并到其中。 Git 称哪一方为“我们的”?

    选择一个答案。

  2. 第 2 题,共 6 题

    关于索引中冲突文件的哪些陈述是正确的?

    选择每个适用的答案。

  3. 第 3 题,共 6 题
    必填

    您将 conflict/sara 重新设置为 conflict/omar,它会因冲突而停止。现在哪个版本是“我们的”?

    选择一个答案。

  4. 第 4 题,共 6 题

    更改输入:您删除编辑器中的冲突标记并保存文件,但从未将其标记为已解决。你处于什么状态?

    选择一个答案。

  5. 第 5 题,共 6 题
    必填

    您保存了结果,但横幅仍然显示“首先解决 1 个冲突”并且“继续”不可用。最可能的原因是什么?

    选择一个答案。

  6. 第 6 题,共 6 题
    必填

    哪些回读显示合并副本正确完成?

    选择每个适用的答案。

0 个(共 6 个)正确

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

在此浏览器中检查。

练习

使用 git show :2:index.html 和 git show :3:index.html 证明两个操作的阶段角色,然后保存相同的 RESOLVED 文件并完成每个操作。预测如果您盲目地在两份副本中都使用“我们的”,那么页面中会留下什么。

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

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

回顾

  • 我们和他们的角色取决于操作。
  • 先保存并标记为已解决,然后继续。
  • 之后检查整个文件和运行状态。

术语表介绍

冲突—— 冲突;基地 — 阿尔萨斯;我们的——恩斯吉塔娜;他们的——解决—— Наّ。

视频文字记录

视频的旁白,逐条提示。

显示成绩单
  1. 冲突不是错误。它是一个 问题只有你能回答。
  2. 两个人改了同一条线 相同的文件。
  3. 萨拉写了一个标题。奥马尔写道 另一个。两者都是从同一页开始的。
  4. Git 无法猜测哪一行获胜,所以它 停下来问你。
  5. 首先,建立Sara和Omar的分支, 和两份相同的副本。
  6. 在第一个副本中我们合并。在第二个中, 我们重新设定基础。
  7. 在 Sara 的分支上打开合并副本。
  8. 右键单击 Omar 的分支并选择其 合并命令。
  9. 对话框已经警告:这将停止 一个文件中存在冲突。
  10. 选择始终合并提交,然后选择合并 一次。正如预期的那样,它停止了。
  11. 横幅显示了一场冲突。继续是 尚不可用。
  12. 选择“解决”,然后打开index.html。
  13. 两侧:Sara 的分支是当前的, 奥马尔的来了。
  14. 展示基地揭示了共同的祖先, 任何更改之前的页面。
  15. 现在编辑输出。将标题替换为 一条刻意的线。
  16. 保存并标记为已解决。直到现在 Git 将文件视为已解决。
  17. 返回横幅上,选择继续。的 合并完成。
  18. 新提交有两个父母,并且 合并标题。
  19. 现在是 rebase 副本,也在 Sara 上 分支。
  20. 右键单击 Omar 的分支,然后重新设置基准 莎拉的树枝放在上面。
  21. 关闭这些选项,然后重新设置一次基准。它 因冲突而停止。
  22. 查看标签。现在奥马尔的分店是 我们重新建立基础的那个。
  23. Sara 的提交是正在重播的提交。 角色互换了。
  24. 相同的分辨率:编辑输出,然后保存 并标记为已解决,然后继续。
  25. Sara 的提交是在之上重新创建的 奥马尔的,标题相同。
  26. 在终端中,列出未合并的条目 停止合并。
  27. 第二阶段是我们的:萨拉的航向。舞台 三是他们的:奥马尔的。
  28. 在停止的变基中,第二阶段和第三阶段 反之亦然。
  29. 修复后,没有任何内容被取消合并,并且 状态为空。
  30. 合并副本的尖端有两个父级;的 rebase copy 的提示有一个。
  31. 更改输入:删除标记并 保存,但不标记已解决。
  32. Git 仍然看到三个阶段,所以继续 保持不可用状态。
  33. 卡住?中止将分支放回原来的位置 手术开始了。
  34. GitTree 首先保存恢复快照, 所以即使中止也是安全的。
  35. 永远不要从你面前的一侧夺取一切 阅读两个版本。
  36. 练习:证明两者的舞台角色 副本,然后完成两份。
  37. 接下来,继续、跳过或中止操作 那已经停止了。