HOWTO · Git
如何恢复 Git stash
了解如何选择 `git stash pop` 或 `git stash apply` 来恢复已保存的更改,如何保留或移除 stash 条目,以及如何选择较早的条目并处理冲突。
本页内容
Git stash 会保存尚未提交的更改,让你之后可以恢复到干净的工作树。要恢复已保存的更改,可以选择 git stash pop:它会应用最新的 stash,并在成功应用后移除对应条目;也可以选择 git stash apply:它会应用更改,同时保留该条目。如果你想先检查恢复后的文件再移除 stash,请先应用更改,然后再删除条目。下方示例使用 stash@{n} 指定 stash 列表中的某个条目。
根据操作目的选择合适的命令
使用 git stash list 查看已保存的条目。最新条目通常是 stash@{0},接下来是 stash@{1},再往后则是更早的条目。选择前请先阅读条目说明;编号表示条目在当前列表中的位置,因此添加或移除条目后,编号可能会变化。
- 恢复最新条目,并在成功应用后移除它:
git stash pop。 - 恢复某个条目,同时继续保留它:
git stash apply。 - 不应用更改,直接移除某个条目:
git stash drop。
stash 保存的是工作区更改,并不是分支上的新提交。默认情况下,应用 stash 会将更改恢复到工作树,但不会恢复原先暂存的状态;使用 git stash apply --index 也可以尝试恢复索引状态。之后运行 git status,检查恢复了哪些内容。如果不确定之后是否还需要这份保存状态,可以先使用 apply;检查结果后再决定是否移除它。
运行以下示例:
本节中的代码以及显示的标签或输出仍为英文。
import subprocess
import tempfile
from pathlib import Path
with tempfile.TemporaryDirectory() as temp_dir:
repo = Path(temp_dir)
def git(*args):
subprocess.run(
["git", *args], cwd=repo, check=True,
stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL,
)
git("init", "-q")
git("config", "user.name", "Example User")
git("config", "user.email", "example@example.com")
note = repo / "note.txt"
note.write_text("original\n", encoding="utf-8")
git("add", "note.txt")
git("commit", "-q", "-m", "Add note")
note.write_text("restored change\n", encoding="utf-8")
git("stash", "push", "-m", "demo", "-q")
git("stash", "pop", "-q")
print(note.read_text(encoding="utf-8").strip())
预期输出:
restored change
使用 git stash pop 恢复并移除最新的 stash
如果你要恢复最新保存的更改并移除对应的 stash 条目,请运行 git stash pop。Git 会应用列表顶部的条目,通常是 stash@{0}。如果应用成功,Git 就会移除该条目。恢复的文件仍会保留在工作树中;移除 stash 条目不会丢弃已经应用的更改。
使用 pop 前,请确认当前工作树适合接收这些已保存的更改。操作后运行 git status,并检查受影响的文件。如果更改没有按预期出现,使用 git stash list 检查该条目是否仍在列表中。如果 stash 无法干净地应用,通常会保留下来;这样你可以解决冲突并重试,同时保留已保存的副本。
使用 git stash apply 恢复并保留 stash
如果你想恢复更改,同时保留已保存的条目以备后用,请使用 git stash apply。要应用最新条目,运行 git stash apply。要选择较早的条目,可以在命令后添加选择器,例如 git stash apply stash@{2}。如果你想比较恢复结果,或之后可能需要在另一个工作树中恢复同一份保存内容,这种方式会很有用。
应用后,运行 git status 并检查相关文件,再继续修改。无论应用成功且没有冲突,还是需要解决冲突,应用 stash 都不会移除该条目。确认恢复的内容完整,并且不再需要该条目后,可以按下文所述使用 git stash drop 将其移除。
恢复后使用 git stash drop 移除 stash
git stash drop 会从 stash 列表中移除一个条目,但不会应用其中的更改。只有确定要丢弃已保存的副本时才使用它。不指定选择器时,它会移除最新条目。若要指定某个条目,可以提供选择器,例如 git stash drop stash@{2}。
若要谨慎地先恢复再移除,请先运行 git stash apply 并指定所需的选择器,然后检查文件并运行 git status。确认更改已恢复且不再需要 stash 副本后,再使用同一个选择器运行 git stash drop。执行移除前,请立即运行 git stash list 再次查看列表:移除较早的条目后,剩余条目的编号可能会变化。如果改为运行 git stash pop,Git 会在应用成功时同时完成应用和移除。
选择 stash 条目并处理冲突
使用 git stash list 列出条目,然后选择所需的 stash@{n}。应用前,可以运行 git stash show -p stash@{2} 查看已保存的补丁;将 2 替换为列表中显示的条目编号。条目说明和补丁内容有助于区分相似的 stash,但操作前务必对照当前列表确认选择器。
stash 可能与当前分支上的更改发生冲突。发生冲突时,Git 会报告受影响的文件,并留下冲突标记供你处理。打开每个被报告的文件,选择并合并要保留的更改,删除冲突标记,然后检查 git status 和最终差异。将恢复视为完成之前,还应执行项目通常要求的检查。发生冲突后,不要假设 pop 已移除该条目:如果 Git 无法干净地应用 stash,就会保留它。解决工作树中的冲突并确认结果后,运行 git stash list 检查列表;只有在不再需要该条目时才将其移除。