情景一 文件被修改,还没有git add。
这时候文件还没有被添加到object database中,可以使用index中的版本来覆盖工作区。
1
|
git checkout -- [filename]
|
情景二 文件被修改,且已经git add。
此时修改过的文件已经作为一个新的object添加到object databse中,可以使用当前HEAD中的版本来覆盖index。
这时候文件还没有被添加到object database中,可以使用index中的版本来覆盖工作区。
1
|
git reset HEAD -- [filename]
|
这时候文件还没有被添加到object database中,可以使用index中的版本来覆盖工作区。
1
|
git checkout -- [filename]
|
情景三 已经提交commit,需要撤销commit。
这种情况又分为多种子情景,详细讨论,首先给出一个模拟的提交历史,从左到右一次提交,master执行提交H。
A---B---C---D---E---F---G---H | master子情形1. 要撤销最近1个commit,要撤销H。
可以使用2个命令:
1
|
git reset --hard G
|
1
|
git revert H
|
A---B---C---D---E---F---G---H | master而git revert会产生一个新的提交,生成的提交历史为:
A---B---C---D---E---F---G---H---I | master
子情形2. 要撤销的提交不是最新的提交,即在错误提交之后又有若干个提交。
比如我们想撤销E,F两个提交,此时git reset已经无法胜任,因为我们在E,F后又有多个正常提交。这时可以使用git revert,但是要操作两次。这种情况下,推荐使用git rebase:
1
|
git rebase --onto D G^ H
|
情形四 执行merge操作,但是遇到conflict,想要撤销merge操作。
此时并为生成新的提交,当前分支头并未移动,因此可以简单的:
1
|
git reset --hard HEAD
|
情形五 执行merge操作,且已生成新的提交,要撤销merge操作。
这是简单的git revert 已经不能胜任。因为merge生成的提交有2个父提交,git不知道该使用哪个作为主线。这时需要添加一个额外的参数:
1
|
git revert -m [parent-number] [refs]
|
如果还有其他情形本文未考虑到,请留言写出,大家一起讨论。