Git 如何回滚上一次提交中的1个文件更改

Git 如何回滚上一次提交中的1个文件更改,git,Git,我在git中进行了2次提交(我没有推送),其中“提交2”是最近的一次: git log -2 commit 791962d776f66253d656586b097b2677eaa983d1 Author: michael <michael@michael-laptop.(none)> Date: Tue Jun 29 23:20:58 2010 -0700 Commit 2 commit b743075e81f6fe25fe48ddbef2b5e7cc0662353

我在git中进行了2次提交(我没有推送),其中“提交2”是最近的一次:

 git log -2
commit 791962d776f66253d656586b097b2677eaa983d1
Author: michael <michael@michael-laptop.(none)>
Date:   Tue Jun 29 23:20:58 2010 -0700

    Commit 2

commit b743075e81f6fe25fe48ddbef2b5e7cc06623533
Author: michael <michael@michael-laptop.(none)>
Date:   Tue Feb 16 23:09:53 2010 -0800

    Commit 1
我的问题是,如何回滚对提交1的dir1/file2.cpp、dir1/file2.h所做的更改?其他一切都保持不变


谢谢。

最简单的解决方案是,从您最近的提交(头)到:

  • 旧版本的那两个文件
  • 加上它们
  • 然后提交
git签出b743075e81——dir1/file2.cpp git签出b743075e81——dir1/file2.h git add dir1/file2.cpp#仅当您进行了其他更改时 git add dir1/file2.h#仅当您进行了其他更改时 git commit-m“还原dir1/file2.cpp和dir1/file2.h” 正如评论中提到的:

git checkout
使用路径规范更新索引(如
git reset
使用路径规范)和工作树,因此不需要
git add
,除非在签出后进行其他更改


使用以下命令,根据需要还原的提交哈希和文件名,使用以前提交的文件回滚该文件

 git reset <commit hash> <filename>

如果您已经将提交推送到了源站,那么这里描述的其他解决方案(使用
git reset
git checkout
,然后是
git commit
)是您唯一明智的选择

但是,如果您尚未推送更改,并且您希望删除文件提交的所有跟踪,则交互式重新基址是一个不错的选择。使用以下命令重新设置最后两次提交的基础:

git rebase --interactive HEAD~2
将打开一个编辑器,显示您的两次提交。要编辑文件以显示以下内容,然后保存;特别是,您希望在第一次提交
编辑
之前更改
选择

edit b743075 Commit 1
pick 791962d Commit 2
git add dir1/file1.cpp
git add dir1/file1.h
git commit -m "Commit 1"
然后Git将把我们置于一种状态,在这种状态下,我们可以编辑第一次提交(而不必触摸第二次提交)。它说您可以使用git commit修改提交--amend
,但实际上我们希望在头部之前重置提交,并完全撤销它:

git reset HEAD^
这将把Commit 1中的更改放回您的工作树中。然后,
git只添加要保留的文件,并使用
git commit
重新提交它们:

edit b743075 Commit 1
pick 791962d Commit 2
git add dir1/file1.cpp
git add dir1/file1.h
git commit -m "Commit 1"
最后,执行硬重置以删除不希望保留在工作树中的文件,并完成重设基础:

git reset --hard
git rebase --continue

当重基完成时,您的存储库将有两个提交,但没有
file2.*
文件的痕迹。

如果您已经使用
git push
将提交推送到源站,这实际上是您唯一明智的选择。git checkout with pathspecs更新索引(如git reset with pathspecs)和工作树,因此,除非在签出后进行其他更改,否则不需要git add。@michael:那么Blair的回答中描述的
git rebase--interactive
应该会引起您的兴趣。这是可行的,但可能会令人困惑,因为它只“回滚”索引项,而不是工作树(与更新索引和工作树的git checkout treesh不同--pathspecs
)。
git reset --hard
git rebase --continue