从git恢复特定的提交

我有一个很多提交和大量文件的git树。 现在,我想恢复只接触文件的特定提交。 解释:

psankar@linux-9dni:~/specific> git init Initialized empty Git repository in /home/psankar/specific/.git/ psankar@linux-9dni:~/specific> echo "File a" > a psankar@linux-9dni:~/specific> git add a ; git commit -m "File a" [master (root-commit) 5267c21] File a 1 file changed, 1 insertion(+) create mode 100644 a psankar@linux-9dni:~/specific> echo "File b" > b psankar@linux-9dni:~/specific> git add b; git commit -m "File b" [master 7b560ae] File b 1 file changed, 1 insertion(+) create mode 100644 b psankar@linux-9dni:~/specific> echo "File c" > c psankar@linux-9dni:~/specific> git add c; git commit -m "File c" [master fd6c132] File c 1 file changed, 1 insertion(+) create mode 100644 c psankar@linux-9dni:~/specific> echo "b and c modified" > b ; cp bc psankar@linux-9dni:~/specific> git commit -a -m "b and c modified" [master 1d8b062] b and c modified 2 files changed, 2 insertions(+), 2 deletions(-) psankar@linux-9dni:~/specific> echo "a modified" > a psankar@linux-9dni:~/specific> git commit -a -m "a modified" [master 5b7e0cd] a modified 1 file changed, 1 insertion(+), 1 deletion(-) psankar@linux-9dni:~/specific> echo "c modified" > c psankar@linux-9dni:~/specific> git commit -a -m "c modified" [master b49eb8e] c modified 1 file changed, 1 insertion(+), 1 deletion(-) psankar@linux-9dni:~/specific> git log --pretty=oneline c psankar@linux-9dni:~/specific> git log --pretty=oneline c | cat b49eb8e03af331bddf90342af7d076f831282bc9 c modified 1d8b062748f23d5b75a77f120930af6610b8ff98 b and c modified fd6c13282ae887598d39bcd894c050878c53ccf1 File c psankar@linux-9dni:~/specific> 

现在我只想恢复两个提交b49eb8e03af331bddf90342af7d076f831282bc91d8b062748f23d5b75a77f120930af6610b8ff98,而不会将更改还原为。 IOW只恢复文件中的提交(不用在其他文件中恢复其他中间提交(数量可能是数千))这是如何实现的?

你可以用--no-commit选项来使用git revert 。 在你的例子中:

 $ 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 'a' then you could discard the revert for it: $ git checkout a $ git commit -a -m "Revert commits b49eb8e and 1d8b062" 

如果不提供提交消息,则在提交消息编辑器启动时,准备好的消息将可用。

如果你省略了--no-commit选项,那么你指定的提交中的改变将被恢复。 这是通过应用指定提交中的更改的反向并提交的。 这导致了一个新的提交,原来的和恢复的提交将在你的仓库的历史。

这里有两种情况:

  1. 当你已经把你的git树推到某个地方而你不想改变历史。 在这种情况下,您将需要一个新的提交来expression您在恢复先前提交时所做的更改。 你应该使用@ mamapitufo的答案。

  2. 如果您从未推送过更改的分支,并且可以更改历史logging。 在这种情况下,您可以完全删除不需要的提交。 这将刷新历史,意味着你不要把错误的转向你的同事或公众。

在第二种情况下,你应该做git rebase -i 。 在您想要更改的任何历史logging之前find一个提交。 这可能是提交的散列,或分支或标记的名称。 例如,你可以做

 git rebase -i 23def8231 

或者如果你是从分支origin/dev_branch开始的,并且在你的分支dev_branch上完成了包含要删除的部分的dev_branch ,你可以

 git rebase -i origin/dev_branch 

现在,您将被发送到编辑器窗口,您可以在其中看到所有提交的提交列表。 这可能是vim – 如果你通常不在terminal编辑它可以被设置为默认。 如果是这样的话,你可能需要一个vim的快速入门指南和一个开放的心态。

现在,最简单的做法是删除提交。 您可以通过删除该行或添加一个表示注释的#来开始该行。 (在文件中已经有一些注释,向你解释,忽略这些或删除它们没有任何作用。)

完成后,保存文件并退出编辑器。 rebase发生如下:git回到您提交的提交。 它通过您保存的列表并重播列表中的每个提交。 然后,它会使该过程的结果成为您原来所在分支的新版本。

重要的事情要记住:

  • 如果你丢了或删除了太多的行,你可以通过删除文件中的每一个提交行来取消rebase,并保存。 这个rebase将被取消。
  • 有可能造成冲突。 例如,如果您删除了一个编辑文件的提交,并在之后的提交中留下了相同的地方。 后面的提交现在不能正确应用,您将不得不手动编辑或在合并工具中获取所需的版本。

你也可以在git rebase -i做很多其他的操作。 例如,改变提交的顺序,将几个合并成一个,在提交之间增加额外的改变或者改变消息。 这是非常有用的。 经典的使用案例是清理本地分支,然后再将其推回到其他人将查看您的更改的地方。