想把改动带到另一个分支,和想撤销已经产生的 commit,不是同一个任务。动手前先检查:
git status
git diff
git diff --cached
git log -5 --oneline
这些信息分别帮助确认未暂存改动、已暂存改动和提交历史。先决定要保留什么,再选择操作。
未提交改动:暂存后带到目标分支
确认改动可以安全暂存、目标分支正确后,可以使用:
git stash push -u -m "move work to another branch"
git switch target-branch
git stash list
git stash apply 'stash@{0}'
git status
git diff
target-branch 应换成实际已确认的分支。较旧 Git 可使用对应 checkout 入口;不要把示例名称直接当作自己的目标。
-u 包含未跟踪文件,但不包含被忽略文件;默认不加它时范围又不同。切换前仍需确认构建产物、未跟踪与忽略文件是否需要另行保护。
apply 保留 stash,方便核对;确认恢复完整后,才按准确存储项决定是否 drop。若使用 pop,正确命令是 git stash pop,不是 git pop;发生冲突时也不要急着清理存储项。Git stash 手册
已有提交:reset 的三种常见模式
以下是针对提交的 reset 语义:
| 模式 | 分支指针 | 暂存区 | 工作区 |
|---|---|---|---|
| —soft | 移到目标提交 | 保留 | 保留 |
| —mixed(默认) | 移到目标提交 | 重置 | 保留 |
| —hard | 移到目标提交 | 重置 | 重写,可能丢失修改 |
路径形式的 reset 还有其他语义,不能与这个表直接混用。Git reset 手册
如果只是撤回最后一个本地 commit,并保留改动且仍处于已暂存状态,在确认 HEAD 有父提交、没有不该保留的暂存内容、历史未被共享等条件后,可以评估:
git reset --soft HEAD~1
这会改变当前分支历史,不是通用的“无风险撤销”。需要保留工作内容时,不应先运行 hard 再想办法恢复。
共享历史另行处理
已经推送、被别人拉取或被其他工作依赖的提交,不适合随意改写。可以根据协作规则评估 revert 产生反向提交等方式。
先做外部备份或保留必要引用,并在可丢弃仓库练习冲突和状态变化。stash、切分支和 reset 都会改变状态;不能把一套命令不加判断地运行在有重要未提交工作的仓库中。