在git中将单个文件还原为以前的版本

有没有办法通过不同的提交文件。 说我修改了一个文件5次,我想回去改变2,我已经提交并推送到一个存储库。

在我的理解中,唯一的办法就是保留很多分支,我有没有这个权利? 如果我是对的,我会在几天内有数百个分支,所以我可能不会真正理解它。

任何人都可以清理那个吗?

让我们从定性描述我们想要做什么(这在Ben Straub的回答中有很多这样的说法)。 我们做了一些提交,其中五个提交了一个给定的文件,我们想把文件恢复到以前的版本。 首先,git不保留单个文件的版本号。 它只是跟踪内容 – 提交实质上是工作树的快照,还有一些元数据(例如提交消息)。 所以,我们必须知道哪个提交有我们想要的文件的版本。 一旦我们知道,我们需要做一个新的提交恢复文件到该状态。 (我们不能只是把历史弄糟,因为我们已经推动了这个内容,并且和其他人一起编辑历史。

那么让我们开始寻找正确的提交。 你可以很容易的看到提交的文件已经修改了。

git log path/to/file 

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

 git log -p path/to/file 

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

 gitk path/to/file 

你也可以通过查看菜单开始gitk; 视图的一个选项是要包含的path的列表。

无论哪种方式,您都可以使用所需文件的版本find提交的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其添加到索引以准备提交。)

如果您的文件可能没有简单的历史logging(例如重命名和复制),请参阅VonC的出色评论。 可以指导git更仔细地search这样的东西,而不是以速度为代价。 如果你确信历史很简单,你就不用费心。

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所build议的那样,使用git checkout <hash> <file path>

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

 git show a4r9593432:path/to/file.txt 

对于所有的命令,除了通过提交散列之外,还有很多方法可以引用提交(参见Git用户手册中的提交命名 )。

说你的5个提交是ABCDEA是第一个, E是最新的。 您想要将file.txt恢复为提交A后的方式。 你不需要学习或记住git-reset和git-checkout命令的不同版本或选项。 跑:

 git show A:file.txt >file.txt # If you want to commit the older version: git add file.txt git commit 

git-show命令显示Git仓库中任何对象的内容或信息。 当像A (或者master ^或者HEAD〜5或者…)那样给定一个提交引用时,后跟一个冒号,后跟一个文件名,它将显示该文件的内容,就像在提交之后一样。 那么这只是将输出redirect到文件的问题。

您可以采取差异化解除您想要的更改并提交。

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

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

从这里提取: 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不考虑文件版本。 git中的版本是整个树的快照。

鉴于此,您真正需要的是具有大多数文件的最新内容的树,但是其中一个文件的内容与之前提交的5个文件的内容相同。 这将采取在旧的承诺之上的一个新的提交的forms,最新版本的树会有你想要的。

我不知道是否有一个单一的文件将恢复到5提交的内容之前,但低保真解决scheme应该工作:结帐master~5 ,复制文件的其他地方,结帐master ,复制文件回来,然后提交。