3.7 Git 综合实验
前置知识:本章前六页
预计时间:25~35 分钟
练习环境:Bash 与 Git 2.28 或更高版本;不访问网络,不修改全局配置
完成标志:两份本地克隆能完成提交、冲突、push、fetch 和合并
概念已经走完一遍。最后,把远程仓库和两份克隆全部放进同一个临时目录,让 Alice 与 Bob 完成一次可重复的协作。即使前面的连续练习中途停过,这个实验也能独立运行。
任务一:创建远程和第一位开发者
bash
workdir=$(mktemp -d)
git init --bare -b main "$workdir/remote.git"
git init -b main "$workdir/alice"
git -C "$workdir/alice" config user.name Alice
git -C "$workdir/alice" config user.email alice@example.invalid
printf '%s\n' 'line=base' > "$workdir/alice/config.txt"
git -C "$workdir/alice" add config.txt
git -C "$workdir/alice" commit -m 'Add base configuration'
git -C "$workdir/alice" remote add origin "$workdir/remote.git"
git -C "$workdir/alice" push -u origin main运行 git -C "$workdir/alice" status --short,此时应没有输出;远程也已经有了 main。
任务二:第二位开发者提交
bash
git clone "$workdir/remote.git" "$workdir/bob"
git -C "$workdir/bob" config user.name Bob
git -C "$workdir/bob" config user.email bob@example.invalid
printf '%s\n' 'from Bob' > "$workdir/bob/BOB.md"
git -C "$workdir/bob" add BOB.md
git -C "$workdir/bob" commit -m 'Add Bob note'
git -C "$workdir/bob" pushAlice 的 origin/main 不会凭空更新:
bash
git -C "$workdir/alice" fetch origin
git -C "$workdir/alice" log --oneline --left-right main...origin/main
git -C "$workdir/alice" merge --ff-only origin/main
test -f "$workdir/alice/BOB.md"任务三:制造并解决冲突
Alice 和 Bob 从相同基线修改同一行:
bash
printf '%s\n' 'line=alice' > "$workdir/alice/config.txt"
git -C "$workdir/alice" commit -am 'Alice changes configuration'
git -C "$workdir/alice" push
printf '%s\n' 'line=bob' > "$workdir/bob/config.txt"
git -C "$workdir/bob" commit -am 'Bob changes configuration'
git -C "$workdir/bob" fetch origin
merge_status=0
git -C "$workdir/bob" merge origin/main || merge_status=$?
test "$merge_status" -eq 1
git -C "$workdir/bob" status --short在 Bob 的文件中选择符合需求的最终值并提交:
bash
printf '%s\n' 'line=alice+bob' > "$workdir/bob/config.txt"
git -C "$workdir/bob" add config.txt
git -C "$workdir/bob" commit -m 'Resolve configuration conflict'
git -C "$workdir/bob" push任务四:验证历史
bash
git -C "$workdir/alice" fetch origin
git -C "$workdir/alice" merge --ff-only origin/main
test "$(git -C "$workdir/alice" rev-parse HEAD)" = "$(git -C "$workdir/bob" rev-parse HEAD)"
git -C "$workdir/bob" status --short
git -C "$workdir/bob" log --graph --oneline --decorate --all
git -C "$workdir/bob" fsck --no-dangling验收要点:两份克隆的 HEAD 相同,工作区没有未提交改动;提交图包含两位开发者的变化和一次合并;fsck 没有对象错误。
排障
- 提交提示 identity unknown:只在当前练习仓库设置
user.name和user.email。 - push 非快进:fetch 后查看提交图,不要立刻 force。
- pull 要求选择策略:显式使用
--ff-only、--rebase或按团队约定 merge。 - 冲突尚未解决:看
git status列出的 unmerged paths,编辑、测试、add,再 commit。 - 想取消合并:提交前用
git merge --abort;开始合并前最好保持工作区清晰。 - 改错未提交内容:先看
git diff,确认不需要后再git restore -- path。
清理
bash
cd
ls -ld -- "$workdir"
rm -r -- "$workdir"不要把这条清理命令换成真实仓库路径。确认你能解释 $workdir 的来源和内容后再执行。
两份克隆的 HEAD 比较通过、临时目录清理完后,这次协作实验就完成了。下一章准备调试环境,再用断点检查程序的运行状态。