我有一个git树,有很多提交和很多文件.现在,我想恢复仅触及文件的特定提交.解释:
> git init Initialized empty Git repository in /home/psankar/specific/.git/ > echo "File a" > a > git add a ; git commit -m "File a" [master (root-commit) 5267c21] File a 1 file changed, 1 insertion(+) create mode 100644 a > echo "File b" > b > git add b; git commit -m "File b" [master 7b560ae] File b 1 file changed, 1 insertion(+) create mode 100644 b > echo "File c" > c > git add c; git commit -m "File c" [master fd6c132] File c 1 file changed, 1 insertion(+) create mode 100644 c > echo "b and c modified" > b ; cp b c > git commit -a -m "b and c modified" [master 1d8b062] b and c modified 2 files changed, 2 insertions(+), 2 deletions(-) > echo "a modified" > a > git commit -a -m "a modified" [master 5b7e0cd] a modified 1 file changed, 1 insertion(+), 1 deletion(-) > echo "c modified" > c > git commit -a -m "c modified" [master b49eb8e] c modified 1 file changed, 1 insertion(+), 1 deletion(-) > git log --pretty=oneline c > git log --pretty=oneline c | cat b49eb8e03af331bddf90342af7d076f831282bc9 c modified 1d8b062748f23d5b75a77f120930af6610b8ff98 b and c modified fd6c13282ae887598d39bcd894c050878c53ccf1 File c
现在我想恢复两个提交b49eb8和1d8b06而不将更改恢复为a.IOW只恢复文件中的提交(不会在不同的文件中恢复其他中间提交(可能数千个))这怎么可能?
这里有两种情况:
当你已经将你的git树推到某个地方并且你不想改变历史时.在这种情况下,您将需要一个新的提交,表示您在还原先前提交时所做的更改.你应该使用@mamapitufo的答案.
如果您从未推动更改所在的分支,则可以更改历史记录.在这种情况下,您可以完全删除不需要的提交.这将扼杀历史,意味着你不会错误地转向你的同事或公众.
在第二种情况下你应该这样做git rebase -i
.找到您要更改的任何历史记录之前的提交.这可能是提交的哈希值,也可能是分支或标记的名称.例如,你可以这样做
git rebase -i 23def8231
或者如果你从分支开始origin/dev_branch
并完成了包含要在你的分支上删除的位的工作dev_branch
,你可以这样做
git rebase -i origin/dev_branch
现在,您将被发送到编辑器窗口,在该窗口中您可以看到所有要重新设置的提交的列表.这可能是vim
- 如果您通常不在终端中编辑它可以设置为默认值.如果是这种情况,您可能需要一个快速入门指导vim和开放思想.
现在,最简单的方法是删除提交.您可以通过删除该行,或添加一个#
表示该行开头的注释来执行此操作.(文件中已经有一些注释,向你解释.忽略这些或删除它们没有效果.)
完成后,保存文件并退出编辑器.rebase发生如下:git返回到你命名的提交.它会浏览您保存的列表并重播该列表中的每个提交.然后它将该过程的结果作为您最初所在分支的新版本.
要记住的重要事项:
如果丢失或删除了太多行,则可以通过删除文件中的每个提交行并保存来取消rebase.rebase过程将结束,一切都没有改变.
可能会产生冲突.例如,如果删除编辑文件的提交,则保留稍后编辑相同位置的提交.现在,以后的提交将无法正确应用,您必须手动或在合并工具中进行编辑才能获得所需的版本.
你也可以做很多其他操作git rebase -i
.例如,更改提交顺序,将几个压缩成一个,在提交之间添加额外的更改,或更改消息.这非常有用.经典用例是在将其推回到其他人将查看您的更改的位置之前清理您的本地分支.
您可以使用git revert
该--no-commit
选项.在你的例子中:
$ git revert --no-commit b49eb8e 1d8b062 # Files that were modified in those 2 commits will be changed in your working directory # If any of those 2 commits had changed the file 'a' then you could discard the revert for it: $ git checkout a $ git commit -a -m "Revert commits b49eb8e and 1d8b062"
如果您未提供提交消息,则在启动提交消息编辑器时将提供准备好的消息.
如果省略该--no-commit
选项,则将还原您指定的提交中的更改.这是通过应用指定提交中的更改的反向并提交它来实现的.这会导致新的提交,原始提交和还原提交都将在您的存储库的历史记录中.