github-从gi还原特定的提交

我有很多提交和很多文件的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仅还原文件中的提交(不还原其他文件中的其他中间提交(可能是数千个)),这怎么可能?

Sankar asked 2020-02-22T18:46:06Z
2个解决方案
80 votes

您可以将--no-commit--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选项,则您指定的提交中的更改将被还原。 这可以通过在指定的提交中应用相反的更改并将其提交来实现。 这将导致一个新的提交,原始提交和还原的提交都将在存储库的历史记录中。

mamapitufo answered 2020-02-22T18:46:29Z
11 votes

这里有两种情况:

  1. 当您已经将git树推到某个位置并且不想更改历史记录时。 在这种情况下,您将需要一个新的提交,以表示您在还原先前提交时所做的更改。 您应该使用@mamapitufo的答案。

  2. 如果您从未按过更改所在的分支,则可以更改历史记录。 在这种情况下,您可以完全删除不需要的提交。 这将孕育历史,意味着您不会对同事或公众施加错误的求助。

在第二种情况下,您应该执行git rebase -i。找到要更改的任何历史记录之前的提交。 这可能是提交的哈希值,或者是分支或标记的名称。 例如,您可以

git rebase -i 23def8231

或者,如果您从分支git rebase -i开始,并完成了包含要在分支上删除的名为dev_branch的工作,则可以

git rebase -i origin/dev_branch

现在,您将被带到一个编辑器窗口,在该窗口中您可以看到要重新定基的所有提交的列表。 这可能是git rebase -i-如果您通常不在终端中进行编辑,则可以将其设置为默认值。 如果是这样的话,您可能需要快速入门的vim和开放的心态。

现在,最简单的方法是删除提交。 为此,您可以删除该行,或添加git rebase -i来指示该行开头的注释。 (文件中已经有一些注释可以向您解释。忽略这些注释或将其删除无效。)

完成后,保存文件并退出编辑器。 重新设置是这样的:git返回到您命名的提交。 它遍历您保存的列表,并重播该列表中的每个提交。 然后,它使该过程的结果成为您最初所在的分支的新版本。

要记住的重要事项:

  • 如果丢失或删除了太多行,则可以通过删除文件中的每个提交行并保存来取消重新设置基准。 重新设置过程将以任何更改结束。
  • 有可能造成冲突。 例如,如果您删除了一个编辑文件的提交,而保留了一个以后的编辑同一位置的提交。 现在,以后的提交将无法正确应用,您必须手动或在合并工具中进行编辑才能获得所需的版本。

您还可以在git rebase -i中进行许多其他操作。例如,更改提交顺序,将多个压缩在一起,在提交之间添加额外的更改,或更改消息。 这是非常有用的。 典型的用例是清理本地分支,然后再将其推回到其他人可以查看您的更改的地方。

jwg answered 2020-02-22T18:47:42Z
translate from https://stackoverflow.com:/questions/20324638/reverting-specific-commits-from-git