将更改还原到提交中的文件


Answers:


222

这里介绍我所见过的最干净的方法

git show some_commit_sha1 -- some_file.c | git apply -R

与VonC的响应类似,但使用git showgit apply


10
做得很好。脚本解决方案对此过于矫kill过正。为什么不能只有git revert sha-1文件名?
马克·爱丁顿

16
这可以在我的Mac上使用,但在Windows(在Cygwin下)上可以使我:fatal: unrecognized input
Kedar Mhaswade

1
@MerhawiFissehaye:我认为git checkout只会再次还原更改,以恢复到提交状态。我没有'git add filename; git commit --amend'从提交中删除文件。
ViFI

3
提示,我几乎总是必须-3在修补程序失败时向git 添加标志以申请三路合并,因为我通常会及时更正更改。
angularsen

2
对大多数人来说也许很明显,但如果有文件路径,请确保some_file.c包含该文件的路径,否则您将默默地不打补丁:)
扭曲了

35

假定可以更改提交历史记录,以下是一个工作流程,可以在较早的提交中还原单个文件中的更改:

例如,您要badfile.txt在commit中还原1个文件()中的更改aaa222

aaa333 Good commit
aaa222 Problem commit containing badfile.txt
aaa111 Base commit

基于基本提交,修改问题提交,然后继续。

1)开始交互式变基:

git rebase -i aaa111

2)通过更改picke(用于编辑),将问题提交标记为在编辑器中进行编辑:

e aaa222
pick aaa333

3)恢复对错误文件的更改:

git show -- badfile.txt | git apply -R

4)添加更改并修改提交:

git add badfile.txt
git commit --amend

5)完成变基:

git rebase --continue

只是要指出,这假设您可以编辑git历史记录。上面的一些答案创建了一个新的提交,该提交可以撤销特定更改而无需编辑历史记录,而这并非总是可能/允许的。
angularsen '16

太棒了 这正是我想要的。我已经有了这个主意,但是在进行交互式变基时感到困惑,因为执行该操作时文件edit没有显示为已更改。但是git show -- badfile.txt | git apply -R给出了我需要的答案<3
mraxus

如果我理解此git apply -R删除对该文件的提交,将其设置回原始更改状态?
DaImTo

19

git revert 用于提交中的所有文件内容。

对于单个文件,可以编写脚本

#!/bin/bash

function output_help {
    echo "usage: git-revert-single-file <sha1> <file>"
}

sha1=$1
file=$2

if [[ $sha1 ]]; then
git diff $sha1..$sha1^ -- $file | patch -p1
else
output_help
fi

(来自smtlaissezfairegit-shell-scripts实用程序)


注意:

如果尚未提交当前修改,则在此处描述另一种方法。

git checkout -- filename

git checkout 对于文件有一些选项,可以从HEAD修改文件,并覆盖您的更改。


Dropped.on.Caprica 在评论中提到:

您可以为git添加一个别名,以便git revert-file <hash> <file-loc>可以恢复该特定文件。
看到这个要点

[alias]
  revert-file = !sh /home/some-user/git-file-revert.sh

只是为了增加此处的讨论,您可以为git添加一个别名,以便可以进行操作git revert-file <hash> <file-loc>并恢复该特定文件。我从这个答案中解脱出来(尽管我必须进行一些编辑才能正常工作)。您可以.gitconfig在此处找到我的脚本和编辑后的脚本的副本: gist.github.com/droppedoncaprica/5b67ec0021371a0ad438
AlbertEngelB 2015年

@ Dropped.on.Caprica好点。我将其包含在答案中以提高可见性。
VonC

12

我只需要使用--no-commit选项即可git-revert,然后在最终提交索引之前从索引中删除您不想还原的文件。这是一个示例,显示了如何在第二次提交中轻松地将更改仅还原为foo.c:

$ git revert --no-commit HEAD~1
$ git reset HEAD
$ git add foo.c
$ git commit -m "Reverting recent change to foo.c"
$ git reset --hard HEAD

第一个git-reset“取消登台”所有文件,以便我们然后可以只添加要还原的一个文件。最终git-reset --hard摆脱了我们不想保留的剩余文件还原。


9

简单得多:

git reset HEAD^ path/to/file/to/revert

然后

git commit --amend   

然后

git push -f

文件不见了,提交哈希,消息等是相同的。


为了完整起见,您需要采取git checkout -- path/to/file/to/revert步骤吗?而且,后来的哈希值是不相同的,对吗?最后一句话可能会更好,例如:“结果是最后一次提交被新提交替换,新提交的区别仅在于它不包含对还原文件的更改。”
凯文

@凯文你可能是对的。我将不得不仔细检查最后一行,但回顾几年前的内容,如果提交哈希未更改,我会感到惊讶。
Forrest

6
git reset HEAD^ path/to/file/to/revert/in/commit

上面的命令将从提交中删除文件,但会在中反映出来git status

git checkout path/to/file/to/revert/in/commit

上面的命令将还原更改(结果是您获得与HEAD相同的文件)。

git commit

(通过--amend以修改提交。)

git push

这样,将删除并还原提交中已存在的文件。

应该从进行提交的分支中遵循上述步骤。


5

您可以按照以下步骤操作:

  1. git revert -n <*commit*>-n还原所有更改,但不会提交)
  2. git add <*filename*> (您要还原并提交的文件名)
  3. git commit -m 'reverted message' (添加一条要还原的消息)
  4. 提交后,丢弃其他文件更改,以便文件保持与您在还原之前提交的更改一起更新

1

如果您想重置上次提交时对文件所做的更改,这就是我通常使用的方法。我认为这是最简单的解决方案。

请注意,该文件将被添加到暂存区域。

git checkout <prev_commit_hash> -- <path_to_your_file>

希望能帮助到你 :)

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.