撤消改变(不重写历史)

我做了一个脚本的改变,并承诺。 然后,我做了一些其他的更改,并将它们推送到远程存储库等。

然后我意识到,我提到的第一个变化是愚蠢的,想要撤消它..我可以“不应用”提交,而不需要手动复制/粘贴差异?

举个例子:我有两个文件, a.pyb.py

 Commit 1: I delete a function in a.py Commit 2: I change a few lines in b.py Commit 3: I change the docstring in a.py 

我可以撤销该function删除,并使其显示为“提交4”(而不是删除提交1)

是的,你可以使用git恢复这个。 有关更多信息,请参阅git手册部分 。

要点是你可以说:

 git revert 4f4k2a 

其中4f4k2a是您要撤消的提交的ID,它将尝试撤消它。

只是一个评论:

 git revert aCommit 

会恢复所有的提交(如在“提交的所有文件的一部分”):
它计算反向修补程序,将其应用于HEAD并提交。

所以这里有两个问题(第一个很容易解决):

  • 它总是提交,所以你可能想要添加-no-commit选项:“ git revert --no-commit aCommit ”:当在一行中多次提交'提交'效果到你的索引时,这是很有用的。
  • 它不适用于特定的文件(如果您的a.py是其他1000个您可能不想恢复的更改提交的一部分)?
    为此,如果你想提取特定的文件,就像在另一个提交中那样,你应该看到git-checkout ,特别是git checkout <commit> <filename>语法(这不是你在这种情况下所需要的)

Easy Git (Elijah Newren)试图给Git邮件列表带来更多的“完全还原” 但没有太大的成功:

人们偶尔想要“恢复变化”。

现在,这可能是:

  • 在32到29之间的修改之前,
  • 它可能是自上次提交以来的所有更改,
  • 它可能是自3提交以来的变化,或者
  • 它可能只是一个具体的提交。
  • 用户可能希望将这样的反转子集合到特定的文件中

eg revert logging在这里 ,但我不确定它是目前分配的一部分,例如虽然)

但最终归结为“恢复变化”。

 eg revert --since HEAD~3 # Undo all changes since HEAD~3 eg revert --in HEAD~8 # much like git revert HEAD~8, but nocommit by default eg revert --since HEAD foo.py # Undo changes to foo.py since last commit eg revert foo.py # Same as above eg revert --in trial~7 bar.c baz. # Undo changes made in trial~7 to bar.[ch] 

这些“恢复数据”真的如此不同,以至于需要不同的命令,或者这些操作中的一些不应该被简单的恢复命令所支持?
当然,大多数用户大多数时候可能会使用“ eg revert FILE1 FILE2... ”的forms,但我没有看到支持额外function的危害。

另外…有没有什么基本的东西可以使核心git不采取这种行为?

以利亚

注意:默认提交对于广义revert命令是没有意义的,“ git revert REVISION ”将会出错(告诉用户添加–in标志)。


假设你有50个承诺的20个文件,你意识到旧的提交X引入了不应该发生的变化。
有一点pipe道是为了。
你需要的是一个列出你需要恢复的所有特定文件的方法
(如在“保留所有后续更改时取消提交X中所做的更改” ),
然后,他们每个人:

 git-merge-file -p a.py XX^ 

这里的问题是恢复丢失的function,而不会消除您可能想保留的所有后续更改。
这种技术有时被称为“负合并”。

因为git merge-file <current-file> <base-file> <other-file> 表示 :
将从<base-file><other-file>所有更改合并<current-file> ,可以通过声明要合并所有更改来恢复已删除的函数。

  • 来自:X(function已被删除)
  • 到:X ^(在X之前的那个函数仍然存在的地方)

注意: '- -p '参数允许你在当前文件中不做任何事情的情况下首先查看更改。 如果您确定,请删除该选项。

注意git merge-file 并不那么简单 :你不能像这样引用以前版本的文件。
(你会一遍又一遍的令人沮丧的消息: error: Could not stat X
你必须:

 git cat-file blob a.py > tmp/ori # current file before any modification git cat-file blob HEAD~2:a.py > tmp/X # file with the function deleted git cat-file blob HEAD~3:a.py > tmp/F # file with the function which was still there git merge-file a.py tmp/X tmp/F # basically a RCS-style merge # note the inversed commit order: X as based, then F # that is why is is a "negative merge" diff -u a.py tmp/ori # eyeball the merge result git add a.py git commit -m "function restored" # and any other changes made from X are preserved! 

如果要在之前的提交中为大量文件执行这个操作,则需要执行一些脚本;)

要恢复到一个提交中只有一个文件的变化,正如VonC指出的那样,我会checkout分支(master或trunk或其他),然后checkout我想恢复的文件的版本,并把它作为一个新的提交:

 $ git checkout trunk $ git checkout 4f4k2a^ a.py $ git add a.py $ git diff #verify I'm only changing what I want; edit as needed $ git commit -m 'recover function deleted from a.py in 4f4k2a' 

可能有一个pipe道命令会直接做到这一点,但如果我知道的话,我不会使用它。 这并不是我不信任Git,但我不相信自己 – 我不相信我没有看到那个提交文件中的变化,从那以后。 一旦我看,通过编辑diff来build立一个新的提交就更容易了。 也许这只是个人的工作方式。

看看这个git恢复问题 。 如果不是包括最近的提交在内的连续序列中,似乎还有一个问题还原旧的提交。