14 / 90

学习日 14:一次性仓库中的 Git 协作

在不触碰课程工作树的情况下使用分支、差异、冲突、安全恢复和 PR 式评审。

自主学习与 Python 480 分钟(8 小时专注学习)
01 120 分钟

分支、差异与评审

智能体协助为可选,须遵循书面计划;学习者拥有权限并验证每一处差异与命令结果。若所选智能体不可用,协助部分记为 blocked/unexecuted——绝不模拟。

先决条件

第 13 天的项目产物和基本的 Git status/log/diff。

学习目标

创建一个一次性克隆,对文本项目做一处聚焦的分支修改,并在提交前评审差异。

操作说明

必做:按参考答案的步骤构建私有基础仓库与克隆(只把 projects/text_tools/{__init__.py,core.py,cli.py} 复制进新的私有基础仓库——绝不可克隆、发布或改动学习仓库及其 .git、数据库、.venv 或密钥),然后创建分支 parser-help,完成指定的 --input 帮助单行改进,并在一个聚焦提交之前记录 branch、status、log、staged 与 unstaged 差异以及 git diff --check。用公开的 --help 检查证明行为——差异加退出码 0 是证据而非证明。每个块都在带 set -e 的 ( ... ) 内运行:先验证新建的 WORKDIR 再使用,mkdir/cp/cd 失败即在子 shell 内中止——失败的命令绝不会“漏过去”在你当前的仓库里运行 Git,export 也不会泄漏到调用者shell。d14env 用 env -i 包裹外部命令,丢弃环境中的 GIT_DIR/GIT_WORK_TREE/index/object/alternates、GIT_CONFIG*、XDG、模板/钩子/签名变量,使它们无法操纵“这些作例命令”;但仅靠 env -i 并不能阻止命令写到 WORKDIR 之外——让作例命令留在 WORKDIR 内的是已验证的前提条件与 fail-stop。PATH 只决定运行哪些可执行文件(会打印解析后的路径;Python 固定为绝对路径 PYTHON_BIN)——它不是可信工具清单,也不是文件系统边界。这是环境卫生而非 OS 沙箱。打印出的 WORKDIR 值由你自己 export——后续活动块要求它。选做:可按书面计划让真实智能体评审差异;若所选工具不可用,将该部分记为 blocked/unexecuted,绝不伪造会话记录。

练习与预测

预测 --input 帮助改进会改变 projects/text_tools/cli.py 的哪一行,以及复制的三个文件中哪些必须保持字节一致(用 sha256sum 验证)。解释为什么 git diff 加零退出码是证据而不是行为的证明,以及当 GIT_DIR 可能指向别的仓库时为何必须经 d14env(env -i + 私有 HOME/XDG/config/template + 关闭签名)执行,以及为何 ( set -e 的 fail-stop 与 WORKDIR 验证能防止失败的 cd 在调用者仓库中运行 Git。执行以下完整的私有环境与检查:

(
set -e
WORKDIR=$(mktemp -d)
[ -n "$WORKDIR" ] && [ -d "$WORKDIR" ] && [ -w "$WORKDIR" ] && [ -x "$WORKDIR" ] || {
  echo "abort: WORKDIR '$WORKDIR' is missing or unusable - refusing to run anything outside it" >&2
  exit 1
}
LEARN=/absolute/path/to/your/clone
[ -f "$LEARN/projects/text_tools/cli.py" ] || {
  echo "abort: LEARN must point at a checkout containing projects/text_tools/cli.py" >&2
  exit 1
}
export WORKDIR LEARN
mkdir -p "$WORKDIR/home" "$WORKDIR/xdg" "$WORKDIR/tpl" "$WORKDIR/tmp"
d14env() {
  env -i PATH="$PATH" HOME="$WORKDIR/home" XDG_CONFIG_HOME="$WORKDIR/xdg" \
      TMPDIR="$WORKDIR/tmp" WORKDIR="$WORKDIR" LEARN="$LEARN" \
      GIT_CONFIG_NOSYSTEM=1 GIT_CONFIG_GLOBAL=/dev/null \
      GIT_TEMPLATE_DIR="$WORKDIR/tpl" \
      GIT_CONFIG_COUNT=1 GIT_CONFIG_KEY_0=commit.gpgsign GIT_CONFIG_VALUE_0=false \
      LC_ALL=C PYTHONDONTWRITEBYTECODE=1 "$@"
}
command -v git sed python3
PYTHON_BIN="$(command -v python3)"
mkdir -p "$WORKDIR/base/projects/text_tools"
cp "$LEARN"/projects/text_tools/__init__.py "$LEARN"/projects/text_tools/core.py "$LEARN"/projects/text_tools/cli.py "$WORKDIR/base/projects/text_tools/"
cd "$WORKDIR/base"
d14env git init
d14env git config user.name "Learner"
d14env git config user.email "[email protected]"
d14env sha256sum projects/text_tools/*.py
d14env git add projects/
d14env git commit -m "text_tools snapshot"
d14env git clone "$WORKDIR/base" "$WORKDIR/clone"
cd "$WORKDIR/clone"
d14env git config user.name "Learner"
d14env git config user.email "[email protected]"
d14env git switch -c parser-help
d14env sed -i 's|corpus file\.|corpus file (UTF-8 by default; override with --encoding/--errors).|' projects/text_tools/cli.py
d14env git status --short
d14env git diff
d14env git diff --cached
d14env git diff --check
d14env git add projects/text_tools/cli.py
d14env git commit -m "cli: document --input decoding defaults"
d14env git log --oneline -3
d14env "$PYTHON_BIN" projects/text_tools/cli.py --help | grep -F "UTF-8 by default"
printf 'export WORKDIR=%s  # run this before the later activity blocks\n' "$WORKDIR"
)

Learning Project Submission & Evidence

0 / 4096 字节
Declared Assistance Condition

Current Submitted Evidence Details

No submission recorded yet.
独立掌握标准

学习者能附上命令输出讲清分支、提交、差异与评审的边界——包括证明新帮助文本的公开 --help 检查——并说明可选的智能体评审是已执行还是如实记为 blocked/unexecuted。

来源资源与出处

linking CC BY-NC-SA 3.0 noncommercial share-alike

Pro Git, Second Edition

作者 / 机构: Scott Chacon and Ben Straub | 原始出处链接 ↗

对应章节 / 时间戳: Chapter 3 (Git Branching: branches, basic merging and conflicts), Chapter 7.7 (Reset Demystified), Chapter 5.2 (Contributing to a Project)

验证版本与日期: Second edition (Apress, 2014); verified 2026-10-30

入选理由:

Freely licensed reference for branching, merging, conflict resolution, and safe recovery vocabulary.

来源前置条件:

Basic git status/log/diff vocabulary from earlier study days

安全回退方案(离线弹性):

git help <command> and the Git manual pages ship with Git and cover the same commands offline; every required workflow is stated locally in the lesson.

对比候选资源与选型分析 (2)
GitHub Skills interactive courses ↗ compared_rejected_for_day14 [MIT (varies by course)]

Interactive but requires a GitHub account and an external service; disposable local repositories keep the exercise self-contained.

Atlassian Git Tutorials ↗ compared_rejected_for_day14 [All Rights Reserved]

Vendor-owned prose with no permissive license; Pro Git covers the same ground under CC BY-NC-SA.

02 120 分钟

独立解决冲突

独立掌握检查:不允许 AI 或抄来的冲突解决;可查阅官方 Git 文档。

先决条件

一个有两条分叉分支的一次性仓库。

学习目标

独立解决真实的 text_tools 夹具冲突,同时保留双方预期的修改。

操作说明

必做:先独立尝试一个全新的变体——选 cli.py 中另一行真实文本(例如 --seed 帮助文本)和你自己想出的两个兼容需求词,创建两条分叉分支,合并,做保留两个用语的解决,并用两次独立的 --help 检查加 git rev-list --parents -n 1 HEAD(三个 id = 双亲合并)验证。然后与下方使用 description 行和 Unicode-aware、original-byte 两词的参考案例对照。本块复用环境块导出的 WORKDIR 夹具(或先把它打印出的路径设为 WORKDIR),并重新声明 d14env。可查阅官方 Git 文档;AI 输出或抄来的解决不计入独立掌握。选做:事后对照参考讲解。

练习与预测

在合并前预测你的变体会出现的冲突标记和最终行内容。解释为什么盲目选择 ours 或 theirs 会丢失需求,以及解决如何同时满足两条验收条件。参考序列(同一私有克隆):

(
set -e
: "${WORKDIR:?set WORKDIR to the private Day 14 fixture path first}"
[ -d "$WORKDIR/clone/.git" ] || { echo "private clone not found - run the setup block first"; exit 1; }
d14env() {
  env -i PATH="$PATH" HOME="$WORKDIR/home" XDG_CONFIG_HOME="$WORKDIR/xdg" \
      TMPDIR="$WORKDIR/tmp" WORKDIR="$WORKDIR" LEARN="$LEARN" \
      GIT_CONFIG_NOSYSTEM=1 GIT_CONFIG_GLOBAL=/dev/null \
      GIT_TEMPLATE_DIR="$WORKDIR/tpl" \
      GIT_CONFIG_COUNT=1 GIT_CONFIG_KEY_0=commit.gpgsign GIT_CONFIG_VALUE_0=false \
      LC_ALL=C PYTHONDONTWRITEBYTECODE=1 "$@"
}
command -v git sed python3
PYTHON_BIN="$(command -v python3)"
cd "$WORKDIR/clone"
d14env git switch -c desc-unicode
d14env sed -i 's|compute statistics, deterministic splits, and provenance artifacts\.|compute Unicode-aware statistics, deterministic splits, and provenance artifacts.|' projects/text_tools/cli.py
d14env git commit -am "describe Unicode-aware statistics"
d14env git switch -
d14env git switch -c desc-provenance
d14env sed -i 's|and provenance artifacts\.|and original-byte provenance artifacts.|' projects/text_tools/cli.py
d14env git commit -am "describe original-byte provenance"
if d14env git merge desc-unicode; then
  echo "unexpected: merge resolved cleanly" >&2
  exit 1
else
  echo "expected non-zero exit (content conflict): $?"
fi
d14env sed -n '/<<<<<<</,/>>>>>>>/p' projects/text_tools/cli.py
d14env "$PYTHON_BIN" - <<'PY'
from pathlib import Path
p = Path('projects/text_tools/cli.py')
s = p.read_text()
i = s.index('<<<<<<<')
j = s.index('\n', s.index('>>>>>>>', i))
resolved = '        description="Text and Data Tools: compute Unicode-aware statistics, deterministic splits, and original-byte provenance artifacts."\n'
p.write_text(s[:i] + resolved + s[j+1:])
PY
d14env git add projects/text_tools/cli.py
d14env git commit -m "merge: keep both requirements"
d14env git rev-list --parents -n 1 HEAD
d14env "$PYTHON_BIN" projects/text_tools/cli.py --help | grep -F "Unicode-aware"
d14env "$PYTHON_BIN" projects/text_tools/cli.py --help | grep -F "original-byte"
d14env git status --short
)
独立掌握标准

学习者自己的变体上无协助的解决正确:两个需求词经 --help 验证、双亲合并提交被记录,证据指明冲突、所选行为、检查与安全边界。

来源资源与出处

linking CC BY-NC-SA 3.0 noncommercial share-alike

Pro Git, Second Edition

作者 / 机构: Scott Chacon and Ben Straub | 原始出处链接 ↗

对应章节 / 时间戳: Section 3.2 (Basic Merging and Conflicts)

验证版本与日期: Second edition (Apress, 2014); verified 2026-10-30

入选理由:

Standard reference for conflict markers and merge semantics underlying the independent resolution exercise.

来源前置条件:

Completion of day-14-act-01 in a disposable repository

安全回退方案(离线弹性):

git help merge documents conflict handling offline; the disposable fixture and instructions are fully local.

对比候选资源与选型分析 (2)
Oh Shit, Git!?! ↗ compared_alternative [Copyright Katie Sylor-Miller (all rights reserved; linking only)]

Strong recovery cheatsheet, but conflict resolution is exercised hands-on; Pro Git remains the primary reference.

Learn Git Branching ↗ compared_alternative [MIT]

Visual branch/merge sandbox; useful companion but the exercise must run in a real disposable repo.

03 120 分钟

安全恢复

智能体协助的工程检查:智能体可以解释选项,但由学习者执行并验证每一步;工具不可用时记为 blocked/unexecuted。

先决条件

一个已提交的一次性夹具和一个故意的、可逆的错误。

学习目标

使用安全的、非破坏性操作,从误编辑或不想要的提交中恢复。

操作说明

必做(同一私有克隆):(0) 建立正典参考基线——从 parser-help 切出 d14-ref 分支并提交已解决的 description 行;你已封存的独立尝试留在自己的分支上、绝不丢弃。(A) 先备份 cli.py,重现两块 hunk 的未暂存情形(description 行 MISTAKE 拼写错误 + --seed 帮助行 KEEP 编辑),查看 git diff,只撤销拼写错误并验证 KEEP hunk 仍在,然后把该有效编辑提交——已提交的修改不会被后面的清理演示丢弃。(B) 用一个新的单 hunk 错误演示暂存区与工作树的区别:暂存它,展示 git restore <path> 会把它留在索引中,再 --staged 取消暂存并做整路径丢弃——此时仅剩的改动确实不要,所以是正当的;验证工作树干净且已提交的 KEEP 在 --help 中仍生效。(C) 先提交已知的单父 BAD 提交,再提交独立的 GOOD 提交,用新提交 revert BAD,证明 GOOD 与 KEEP 都保留且历史未被改写;最后(预期失败)观察对合并提交 revert 需要 -m 指定主线。选做:运行后与智能体复盘恢复方式的选择。

练习与预测

对与有效编辑同处一文件的未暂存拼写错误,以及跟在单父坏提交之后的独立良好提交:分别选择 git restore、git revert 或保存的副本,并在运行前预测最终的差异与历史。为什么 KEEP 编辑必须在演示暂存错误之前提交,而不仅仅在工作树中幸存?

(
set -e
: "${WORKDIR:?set WORKDIR to the private Day 14 fixture path first}"
[ -d "$WORKDIR/clone/.git" ] || { echo "private clone not found - run the setup block first"; exit 1; }
d14env() {
  env -i PATH="$PATH" HOME="$WORKDIR/home" XDG_CONFIG_HOME="$WORKDIR/xdg" \
      TMPDIR="$WORKDIR/tmp" WORKDIR="$WORKDIR" LEARN="$LEARN" \
      GIT_CONFIG_NOSYSTEM=1 GIT_CONFIG_GLOBAL=/dev/null \
      GIT_TEMPLATE_DIR="$WORKDIR/tpl" \
      GIT_CONFIG_COUNT=1 GIT_CONFIG_KEY_0=commit.gpgsign GIT_CONFIG_VALUE_0=false \
      LC_ALL=C PYTHONDONTWRITEBYTECODE=1 "$@"
}
command -v git sed python3
PYTHON_BIN="$(command -v python3)"
cd "$WORKDIR/clone"
d14env git switch -c d14-ref parser-help
d14env sed -i 's|compute statistics, deterministic splits, and provenance artifacts\.|compute Unicode-aware statistics, deterministic splits, and original-byte provenance artifacts.|' projects/text_tools/cli.py
d14env git commit -am "reference baseline: description keeps both requirement terms"
d14env sed -i 's|Unicode-aware statistics|statistisc|' projects/text_tools/cli.py
d14env sed -i 's|(default: 42)\.|(default: 42; any integer).|' projects/text_tools/cli.py
d14env cp projects/text_tools/cli.py "$WORKDIR/cli-backup.py"
d14env git diff
d14env sed -i 's|statistisc|Unicode-aware statistics|' projects/text_tools/cli.py
d14env git diff
d14env git diff --check
d14env "$PYTHON_BIN" projects/text_tools/cli.py --help | grep -F "any integer"
d14env git commit -am "document that --seed accepts any integer"
d14env sed -i 's|default=42,|default=7,|' projects/text_tools/cli.py
d14env git add projects/text_tools/cli.py
d14env git status --short
d14env git restore projects/text_tools/cli.py
d14env bash -c 'git diff --cached | grep -F "default=7"'
d14env git restore --staged projects/text_tools/cli.py
d14env git restore projects/text_tools/cli.py
d14env git status --short
d14env bash -c 'test -z "$(git status --porcelain)"'
d14env "$PYTHON_BIN" projects/text_tools/cli.py --help | grep -F "any integer"
d14env sed -i 's|default=42,|default=7,|' projects/text_tools/cli.py
d14env git commit -am "BAD: change default seed to 7"
BAD=$(d14env git rev-parse HEAD)
d14env sed -i 's|(default: 0.1)\.|(default: 0.1; must be in [0, 1]).|' projects/text_tools/cli.py
d14env git commit -am "GOOD: clarify split-ratio range"
d14env git revert --no-edit "$BAD"
d14env grep -F "default=42," projects/text_tools/cli.py
d14env grep -F "must be in [0, 1]" projects/text_tools/cli.py
d14env grep -F "any integer" projects/text_tools/cli.py
d14env git log --oneline -3
d14env git rev-list --count HEAD
MERGE_SHA=$(d14env git rev-list --all --merges -n 1)
[ -n "$MERGE_SHA" ] || { echo "no merge commit found - run the act-02 reference merge first" >&2; exit 1; }
if d14env git revert "$MERGE_SHA" 2>"$WORKDIR/merge_revert.err"; then
  echo "unexpected: merge revert succeeded without -m" >&2
  exit 1
else
  rc=$?
  grep -F "no -m option" "$WORKDIR/merge_revert.err" && echo "expected non-zero exit (merge needs -m): $rc"
fi
)
独立掌握标准

学习者能在不丢弃已封存工作的情况下建立正典基线,根据仓库状态论证每个操作,通过 KEEP 自身的提交加干净的 status 与 --help 检查证明其在清理后仍然保留,展示 revert 以新提交而非改写历史的方式生效,并在不猜测主线的情况下观察到合并 revert 的失败。

来源资源与出处

linking CC BY-NC-SA 3.0 noncommercial share-alike

Pro Git, Second Edition

作者 / 机构: Scott Chacon and Ben Straub | 原始出处链接 ↗

对应章节 / 时间戳: Section 7.7 (Reset Demystified) and Section 2.4 (Undoing Things): restore, revert, and history boundaries

验证版本与日期: Second edition (Apress, 2014); verified 2026-10-30

入选理由:

Freely licensed explanation of why restore and revert are the safe recovery tools while destructive commands are deferred.

来源前置条件:

Completion of day-14-act-02

安全回退方案(离线弹性):

git help restore and git help revert document the same safe operations offline.

对比候选资源与选型分析 (2)
Git documentation: git-restore/git-revert ↗ compared_alternative [GPL-2.0 (Git) / CC BY-NC-SA 3.0 (book-derived pages)]

Exact command references, useful as a companion; Pro Git provides the conceptual model the activity teaches.

Oh Shit, Git!?! ↗ compared_alternative [Copyright Katie Sylor-Miller (all rights reserved; linking only)]

Recovery cheatsheet matching the safe-recovery theme; Pro Git provides the underlying model.

04 120 分钟

PR 式评审与检索

独立掌握检查:预测、自己的检查和封存评审均无协助;之后的协助对比是独立部分,绝不替代封存稿。

先决条件

已完成的分支、冲突和恢复证据。

学习目标

像评审拉取请求一样评审一次性改动,区分正确性、范围、测试、风险和证据。

操作说明

必做:先无协助地记录你的预测/初始假设;然后亲自运行弱检查和强检查——自己的执行属于无协助尝试的一部分,不算协助;再撰写并封存(提交、注明日期)完成的无协助评审——验收标准、阻塞性意见、非阻塞性意见、实际观察到的证据和边界。若行为其实正确,封存评审仍要记录所跑检查及充分理由——只写“看起来没问题”为不合格。选做:之后可对照真实的智能体评审并标注 assisted(不替代封存稿);任何借助协助的修正都要做一次新的无协助复查。不授权对外发布。

练习与预测

在运行强检查前,预测 --help 列出 --quiet 是否证明该标志生效。指出弱冒烟检查看不到的缺陷,以及能暴露它的更强 CLI 检查。补丁(评审者编写,非观察到的智能体输出):

(
set -e
: "${WORKDIR:?set WORKDIR to your private Day 14 fixture path first}"
[ -d "$WORKDIR/clone/.git" ] || { echo "private clone not found - run the setup block first"; exit 1; }
d14env() {
  env -i PATH="$PATH" HOME="$WORKDIR/home" XDG_CONFIG_HOME="$WORKDIR/xdg" \
      TMPDIR="$WORKDIR/tmp" WORKDIR="$WORKDIR" LEARN="$LEARN" \
      GIT_CONFIG_NOSYSTEM=1 GIT_CONFIG_GLOBAL=/dev/null \
      GIT_TEMPLATE_DIR="$WORKDIR/tpl" \
      GIT_CONFIG_COUNT=1 GIT_CONFIG_KEY_0=commit.gpgsign GIT_CONFIG_VALUE_0=false \
      LC_ALL=C PYTHONDONTWRITEBYTECODE=1 "$@"
}
command -v git sed python3
PYTHON_BIN="$(command -v python3)"
cd "$WORKDIR/clone"
d14env git switch -c add-quiet
d14env "$PYTHON_BIN" - <<'PY'
from pathlib import Path
p = Path('projects/text_tools/cli.py')
s = p.read_text()
old = '    parser.add_argument(\n        "--errors",'
assert s.count(old) == 1
s = s.replace(old, '''    parser.add_argument(
        "--quiet",
        action="store_true",
        help="Suppress the artifact-generation success summary.",
    )
    parser.add_argument(
        "--errors",''')
p.write_text(s)
PY
d14env git commit -am "add --quiet flag"
d14env "$PYTHON_BIN" projects/text_tools/cli.py --help | grep -F -- "--quiet"
mkdir -p "$WORKDIR/acts"
d14env printf 'a\nb\nc\n' > "$WORKDIR/acts/in.txt"
d14env "$PYTHON_BIN" projects/text_tools/cli.py --input "$WORKDIR/acts/in.txt" --split --output-dir "$WORKDIR/acts/out" --quiet
)
独立掌握标准

封存的无协助评审写明验收标准(--quiet 下抑制摘要),引用自己运行中实际观察到的 stdout 为证据,区分阻塞与非阻塞意见,区分假想补丁与真实智能体输出、自己的检查与隐藏评估器,且在预测与自己的检查之后、协助对比之前已封存并提交。

来源资源与出处

linking CC BY-NC-SA 3.0 noncommercial share-alike

Pro Git, Second Edition

作者 / 机构: Scott Chacon and Ben Straub | 原始出处链接 ↗

对应章节 / 时间戳: Section 5.2 (Contributing to a Project: commit and review etiquette) and Section 6.2 (Contributing via pull requests)

验证版本与日期: Second edition (Apress, 2014); verified 2026-10-30

入选理由:

Provides the shared vocabulary for PR-style review findings while the exercise stays entirely local and disposable.

来源前置条件:

Completion of day-14-act-03

安全回退方案(离线弹性):

The review rubric is fully specified in the lesson; no network access is required to complete it.

对比候选资源与选型分析 (2)

Industry-grade review guidance; offered as optional further reading since the exercise reviews a local disposable change.

Conventional Comments ↗ compared_alternative [CC BY 3.0]

Comment-labeling convention for review findings; optional vocabulary, not a substitute for the local rubric.