# 代码回滚
# 场景一: 仅在工作区做了修改
此时做的修改,仅仅是在工作区进行了修改,还没有执行添加到暂存区操作(git add
),也就更不可能执行了提交操作(git commit
)。
## 注意,文件名前有 双短横线
git checkout -- <文件>
# 比如,撤回对 main.js 文件的修改
git checkout -- main.js
2
3
4
5
需要注意的是,这些改动因为从来没有提交到 Git 仓库中过,Git 无法追踪其历史版本,一旦回滚就相当于直接丢弃这些修改了。
场景:刚 clone 或 pull 了代码到本地,对一个文件做了一些修改,但发现这些修改不想要了,想恢复到 clone 时的状态,此时就可以对这个文件执行 git checkout
。
# 场景二: 已添加(add)到暂存区中
当修改已经添加(git add)到暂存区中,但还没有执行提交 (git commit) 时,可以通过 reset 来进行回滚:
git reset HEAD -- <文件>
执行后,只是将文件修改从暂存区移回到工作区,修改还依然存在,如果要确认放弃修改的内容,可执行场景一的操作。
# 场景三: 已提交(commit), 但还没有 push
已提交修改到本地的 Git 仓库,但是还没有推送到远程仓库时:
# 将当前工作区回滚到某一次 commit 之后,并将回滚的所有文件修改保留在工作区
git reset <commit hash>
# --hard 表示不保留修改内容到工作区,直接回滚到某一次 commit 之后的状态
git reset --hard <commit-hash>
2
3
4
# 场景四:已提交(commit), 但还没有 push, 想修改最后一次 commit
当 commit 之后,还没有 push 到远程的时候,发现刚才的修改还需要优化,如果直接修改后再次 add 并 commit 的话,就会多生成一次 commit 记录。但我们只想要一次提交记录。
方式一:就像场景三中一样,将刚才不完美的 commit 先通过 reset 撤回,等修改完善之后再一次性进行提交。
方式二:commit 时合并到最后一次提交中,修改内容会合并,并且提交说明会覆盖最后一次的提交说明。
# --amend 表示完善提交记录,将本次的修改合并到最后一次 commit 中,并且以本次的 commit message 为准
git commit --amend -m <commit-message>
2
# 已 push 的修改
对于任何一次已经 push 到远程的 commit 提交记录,都不能用 git reset <commit>
来执行,因为 reset 会丢弃指定的 commit 之后的所有 commit,这样修改之后再 push 的话会和远程仓库造成冲突。
比如,假设当前本地和远程均有 a, b, c, d 四次提交记录,在本地执行 reset b
之后,做出一些修改,然后 add 并 commit 生成提交记录 e , c 和 d 就会被丢弃,此时本地的提交记录就只有 a, b, e, 而远程仓库的提交记录是 a, b, c, d, 这样本地和远程仓库的提交记录不一致,就会造成冲突,无法 push 到远程。
所以,针对已经 push 到远程的提交记录,不能使用 git reset
来执行回滚操作,而是应该使用 git revert
来完成。
git revert
会将某一次指定的 commit 作为新的提交,还是以上面的例子为例,本地和远程均有 a, b, c, d 提交记录,revert b
之后,会将 b 的修改内容添加到暂存区,提交后会生成新的提交记录 e,此时本地的提交记录为 a, b, c, d, e, 远程为 a, b, c, d, 没有冲突,可以直接 push 到远程。
# 版本恢复时,不要直接进行提交,可以先进行编辑再进行提交
git revert -n <commit-hash>
# 版本恢复时,直接先将指定的提交记录作为一次新的提交
git revert <commit-hash>
2
3
4