分支、差異與評審
代理協助為可選,須遵循書面計畫;學習者擁有權限並驗證每一處差異與命令結果。若所選代理不可用,協助部分記為 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"
)
git worktree 不是獨立複製:它共享基礎儲存庫的參照並寫入 .git/worktrees 元資料(已驗證)。請改為複製私有基礎儲存庫。環境中的 GIT_DIR/GIT_WORK_TREE/GIT_CONFIG*/XDG 變數會把 git 引向別的儲存庫或設定——env -i 丟棄它們,但並不做檔案系統沙箱。絕不對學習儲存庫執行 reset --hard、clean、force-push 或復原類命令。
已驗證的觀測結果(Linux, bash, git 2.56;你的雜湊/時間戳記會不同):
- sha256sum 輸出三個雜湊——基礎儲存庫的身分;core.py 與 __init__.py 全程保持位元組一致。
- git status --short 只顯示 M projects/text_tools/cli.py;git diff 只顯示 --input 說明行;git diff --cached 在 git add 之前為空。
- git log --oneline 在 text_tools snapshot 之上顯示聚焦提交。
- 行為檢查:--help 輸出 Path to the input text corpus file (UTF-8 by default; ...——這是改動生效的公開證據;只有差異只能證明文字變動。
邊界:git worktree 共享基礎儲存庫的參照並改動 .git/worktrees——不是獨立複製。已實證環境 Git 變數的敵意:把 GIT_DIR/GIT_WORK_TREE 指向一個無關私有儲存庫並設置陷阱全域設定(他人 user.name、惡意範本鉤子),本區塊仍只配置了私有 base/clone——無關儲存庫的 HEAD 與 user.name 未變、哨兵鉤子未執行、提交作者為 Learner 而非陷阱身分。env -i 只保留列出的變數;PATH 僅用於定位工具、不授予儲存庫存取——這是衛生而非檔案系統沙箱。執行 cli.py 後可能出現 __pycache__/——未追蹤建構產物(PYTHONDONTWRITEBYTECODE=1 可阻止)。Linux/bash 範圍;sed -i 為 GNU 形式——macOS 需要 sed -i '',Windows 命令不同(僅供參考、未執行)。
Learning Project Submission & Evidence
學習者能附上命令輸出講清分支、提交、差異與評審的邊界——包括證明新說明文字的公開 --help 檢查——並說明可選的代理評審是已執行還是如實記為 blocked/unexecuted。
來源資源與出處
Pro Git, Second Edition
對應章節 / 時間戳: 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)
Interactive but requires a GitHub account and an external service; disposable local repositories keep the exercise self-contained.
Vendor-owned prose with no permissive license; Pro Git covers the same ground under CC BY-NC-SA.