【问题标题】:How can I revert a single file to a previous version? [duplicate]如何将单个文件恢复到以前的版本? [复制]
【发布时间】:2011-02-13 14:26:00
【问题描述】:

有没有办法在一个文件上进行不同的提交。 假设我修改了一个文件 5 次,在我已经提交并推送到存储库之后,我想返回更改 2。

在我的理解中,唯一的方法是保留许多分支,我说对了吗? 如果我是对的,我将在几天内拥有数百个分支,所以我可能不太了解它。

请问有没有人能解释一下?

【问题讨论】:

  • 您是想将文件还原为永久更改 2,还是暂时拉出更改 2 以查看文件当时的样子?
  • 我仍然每天使用 SVN,并且只使用一点 git,所以我无法回答您的问题 - 但我认为您可能对这个资源感兴趣 - 这本书 'Pro Git' 可在此处在线获得 - @ 987654321@我拥有并读过这本书 - 非常好,太糟糕了我现在不能使用 git 听起来你只需要获取文件的历史版本,然后重新提交旧版本,而不是分支?
  • @Jim Hurne:是的,我想永久恢复文件@house9:谢谢,我会看看那本书。历史位听起来不错,是怎么做到的?

标签: git revert


【解决方案1】:

Git 不考虑文件版本。 git 中的版本是整个树的快照。

鉴于此,您真正想要的是一棵树,其中包含大多数文件的最新内容,但其中一个文件的内容与 5 次提交前相同。这将采取在旧提交之上新提交的形式,最新版本的树将拥有您想要的。

我不知道是否有一个单行器可以将单个文件恢复为 5 次提交之前的内容,但是 lo-fi 解决方案应该可以工作:结帐master~5,将文件复制到其他地方,结帐@ 987654322@,将文件复制回来,然后提交。

【讨论】:

  • 您要求的单行是在单个文件而不是整个工作树上结帐;看我的回答。
  • 哇。我觉得我应该编辑我的答案。干得好!
【解决方案2】:

您可以采用差异来撤消您想要的更改并提交。

例如如果要撤消from..to 范围内的更改,请执行以下操作

git diff to..from > foo.diff  # get a reverse diff
patch < foo.diff
git commit -a -m "Undid changes from..to".

【讨论】:

  • 一些问题。如果你想创建一个补丁,它只需要是有问题的文件的补丁 (git diff to..from path/to/file)。要应用补丁,您应该使用git apply 而不是补丁。在这种情况下根本不需要使用补丁;看我的回答。
  • 仍然很有帮助,因为您可以编辑差异(即仅还原部分更改)。
  • @Jefromi 绝对有理由使用补丁,因为您的答案不等同于还原:它将消除自违规提交以来的所有更改,而不仅仅是撤消该提交的更改为@ 987654325@ 可以。特定于文件和提交的补丁是更精确和语义正确的更改。
  • @JohnWhitley 这个问题明确是关于将文件恢复到以前的版本。它在标题中。我完全同意,如果您只想撤消多个提交的单个提交,我的回答是错误的,但幸运的是,这不是我在这里回答的问题。
  • @Jefromi 这个答案与您的答案不同。这个答案恢复了一次提交。您的回答会还原一个文件。这恰好正是我所需要的。
【解决方案3】:

让我们从对我们想要做的事情的定性描述开始(Ben Straub 的回答中说了很多)。我们进行了一些提交,其中五个更改了给定文件,我们希望将文件恢复到以前的版本之一。首先,git 不保留单个文件的版本号。它只是跟踪内容 - 提交本质上是工作树的快照,以及一些元数据(例如提交消息)。因此,我们必须知道哪个提交具有我们想要的文件版本。一旦我们知道这一点,我们将需要进行新的提交,将文件恢复到该状态。 (我们不能乱搞历史,因为我们已经推送了这个内容,编辑历史会和其他人混在一起。)

让我们从寻找正确的提交开始。您可以很容易地看到对给定文件进行修改的提交:

git log path/to/file

如果您的提交消息不够好,并且您需要查看每次提交中对文件所做的操作,请使用 -p/--patch 选项:

git log -p path/to/file

或者,如果你更喜欢 gitk 的图形视图

gitk path/to/file

您也可以在通过视图菜单启动 gitk 后执行此操作;视图的选项之一是要包含的路径列表。

无论哪种方式,您都可以使用所需文件的版本找到提交的 SHA1(哈希)。现在,您所要做的就是:

# get the version of the file from the given commit
git checkout <commit> path/to/file
# and commit this modification
git commit

(checkout命令先将文件读入索引,然后将其复制到工作树中,因此无需使用git add将其添加到索引中以准备提交。)

如果您的文件可能没有简单的历史记录(例如重命名和副本),请参阅 VonC 的出色评论。可以指示git 更仔细地搜索此类内容,但会牺牲速度。如果您确信历史很简单,则无需费心。

【讨论】:

  • 您不应该使用-C--find-copies-harder 来检测重命名和副本,再加上--follow 以继续列出重命名之外的文件历史记录吗?鉴于您的回答强调文件内容,最好通过提及其自然结果来完成它:inference 方面(参见stackoverflow.com/questions/612580/…
  • 切中要害!谢谢!!
  • 很棒的解释。您不仅完美地回答了这个问题,还加深了我的理解。我之前也从未见过gitk - 太棒了!
  • git checkout head~3 filename 不起作用吗?
  • @EdRandall 当然,HEAD~3 可以工作,如果你想要的提交是 HEAD 之前的三。一般来说,你可能并不完全自信,所以我介绍了如何确定你真正想要的提交。
【解决方案4】:

Git 非常灵活。您不应该需要数百个分支机构来完成您的要求。如果您想将状态一直恢复到第二次更改(确实是已经提交和推送的更改),请使用git revert。比如:

git revert a4r9593432 

其中 a4r9593432 是您要退出的提交的哈希的起始字符。

如果提交包含对许多文件的更改,但您只想还原其中一个文件,则可以使用git reset(第二种或第三种形式):

git reset a4r9593432 -- path/to/file.txt
# the reverted state is added to the staging area, ready for commit
git diff --cached path/to/file.txt        # view the changes
git commit
git checkout HEAD path/to/file.txt        # make the working tree match HEAD           

但这很复杂,而且 git reset 很危险。正如 Jefromi 建议的那样,改用 git checkout &lt;hash&gt; &lt;file path&gt;

如果你只是想查看提交 x 中文件的样子,可以使用git show:

git show a4r9593432:path/to/file.txt

对于所有命令,除了通过提交哈希之外,还有很多方法可以引用提交(请参阅 Git 用户手册中的 Naming Commits)。

【讨论】:

  • git revert 不会只是退出 one 更改 - 不是“将状态一直恢复到第二个更改”?
  • @Alex - 是的,你是对的。接得好!只有在给定提交中引入的更改才会被撤销。这很痛苦,但您可以多次调用get revert 来将所有提交撤消到某个时间点。或者您可以使用git diffgit apply 执行您在回答中建议的操作。
  • 另外,git revert 不是针对一个特定文件,而是针对整个存储库。
  • @PaŭloEbermann 是的,但它只会恢复指定提交中受影响的文件。
  • 我们可以吃蛋糕吗?是否可以从单个文件还原单个提交并保留其他未来更改?
【解决方案5】:

摘自此处:http://git.661346.n2.nabble.com/Revert-a-single-commit-in-a-single-file-td6064050.html

 git revert <commit> 
 git reset 
 git add <path> 
 git commit ... 
 git reset --hard # making sure you didn't have uncommited changes earlier 

对我来说效果很好。

【讨论】:

  • 直觉上,在阅读您的答案之前,我做了git revertgit resetgit add,然后我在承诺之前进行了搜索,看看我是否做得对。为您的回答 +1!
  • 你知道如果以这种方式恢复单个文件,git 会识别出我实际上是在恢复文件吗?
  • gitk 显示为new file
  • @AntonioViniciusMenezesMedei:正如你所发现的那样,它不起作用。它显示您还原所有更改并添加所有其他文件,就好像您刚刚完成它们一样。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-10-01
  • 1970-01-01
  • 1970-01-01
  • 2019-07-13
  • 2017-03-05
相关资源
最近更新 更多