手上改动还没提交,怎么在另一分支复现故障?用 Git worktree
当前分支有未提交的工作时,可以用 git worktree add 在另一个目录检出用于排障的分支。两个工作树共用同一个仓库的提交和分支引用,各自保留工作文件、HEAD 和暂存区。可以一边复现故障,一边保留原来的暂存内容。
1. 比较两个工作树的暂存区
将代码保存为 worktree_lab.py,用 Python 运行,需 Git。脚本只在临时目录创建仓库和链接工作树。
from pathlib import Path
import subprocess
from tempfile import TemporaryDirectory
with TemporaryDirectory() as tmp:
root = Path(tmp)
main = root / "main"
repair = root / "repair"
main.mkdir()
def git(cwd, *args, check=True):
return subprocess.run(
["git", *args], cwd=cwd, capture_output=True, text=True, check=check
)
git(main, "init", "-q", "-b", "main")
git(main, "-c", "user.name=Demo", "-c", "user.email=demo@example.com",
"-c", "commit.gpgsign=false", "commit", "--allow-empty", "-qm", "base")
(main / "notes.txt").write_text("draft\n", encoding="utf-8")
git(main, "add", "notes.txt")
git(main, "worktree", "add", "-q", "-b", "repair", str(repair), "HEAD")
assert not (repair / "notes.txt").exists()
assert git(main, "diff", "--cached", "--name-only").stdout.strip() == "notes.txt"
assert not git(repair, "diff", "--cached", "--name-only").stdout.strip()
print("main: notes.txt staged; repair: index clean")
branch = git(repair, "branch", "--show-current").stdout.strip()
assert branch == "repair"
assert git(main, "show-ref", "--verify", "refs/heads/repair").returncode == 0
blocked = git(main, "switch", "repair", check=False)
assert blocked.returncode != 0
assert git(main, "branch", "--show-current").stdout.strip() == "main"
print("repair branch shared; second checkout blocked")
git(main, "worktree", "remove", str(repair))
assert git(main, "show-ref", "--verify", "refs/heads/repair").returncode == 0
print("repair worktree removed; branch still exists")
main: notes.txt staged; repair: index clean
repair branch shared; second checkout blocked
repair worktree removed; branch still exists
2. 选择分支工作树或分离 HEAD
要在排障过程中提交修复,可以用 git worktree add -b fix-login ../fix-login <基线>。只想查看发布标签或运行测试时,可用 git worktree add --detach ../check-release <标签>。已在其他工作树检出的分支默认不能再次检出,遇到拒绝时用 git worktree list 找到它所在的目录。
在排障目录完成后,先检查 git status --short,确认需要的改动已提交或保留,再用 git worktree remove <目录> 清理登记和工作文件。随后分支仍存在,可按正常流程合并。各工作树中被忽略的依赖和构建文件通常需要各自准备,实验中的仓库没有这类依赖。
小结
同一个仓库可以有多份工作树。用各自的目录和暂存区并行处理改动,用共享分支引用合并成果。
数据来源与检索时间
| 来源 | URL | 检索日期 | 对应内容 |
|---|---|---|---|
| Git git-worktree | https://git-scm.com/docs/git-worktree | 2026-11-13 | add、list、remove,以及共享引用和工作树私有状态 |
核验说明
- Windows、Python 3.11.9、Git 2.54.0.windows.1 实测暂存隔离、重复检出拒绝及清理后分支仍存在。