在 git 中将单个文件恢复到以前的版本
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2733873/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Reverting a single file to a previous version in git
提问by georgeliquor
Is there a way to go through different commits on a file. Say I modified a file 5 times and I want to go back to change 2, after I already committed and pushed to a repository.
有没有办法对文件进行不同的提交。假设我修改了一个文件 5 次,我想在我已经提交并推送到存储库后返回更改 2。
In my understanding the only way is to keep many branches, have I got that right? If I'm right I'm gonna have hundreds of branches in a few days, so I'm probably not understanding it really.
根据我的理解,唯一的方法是保留许多分支,我做对了吗?如果我是对的,我将在几天内拥有数百个分支机构,所以我可能并不真正理解它。
Could anyone clear that up please?
有没有人可以澄清一下?
回答by Cascabel
Let's start with a qualitative description of what we want to do (much of this is said in Ben Straub's answer). We've made some number of commits, five of which changed a given file, and we want to revert the file to one of the previous versions. First of all, git doesn't keep version numbers for individual files. It just tracks content - a commit is essentially a snapshot of the work tree, along with some metadata (e.g. commit message). So, we have to know which commit has the version of the file we want. Once we know that, we'll need to make a new commit reverting the file to that state. (We can't just muck around with history, because we've already pushed this content, and editing history messes with everyone else.)
让我们从我们想要做什么的定性描述开始(Ben Straub 的回答中说了很多)。我们已经进行了一些提交,其中 5 次更改了给定的文件,我们希望将文件恢复到以前的版本之一。首先,git 不保留单个文件的版本号。它只是跟踪内容——提交本质上是工作树的快照,以及一些元数据(例如提交消息)。因此,我们必须知道哪个提交具有我们想要的文件版本。一旦我们知道这一点,我们将需要进行新的提交以将文件恢复到该状态。(我们不能只顾及历史,因为我们已经推送了这些内容,并且编辑历史会与其他人混为一谈。)
So let's start with finding the right commit. You can see the commits which have made modifications to given file(s) very easily:
所以让我们从寻找正确的提交开始。您可以非常轻松地查看对给定文件进行修改的提交:
git log path/to/file
If your commit messages aren't good enough, and you need to see what was done to the file in each commit, use the -p/--patch
option:
如果您的提交消息不够好,并且您需要查看在每次提交中对文件做了什么,请使用以下-p/--patch
选项:
git log -p path/to/file
Or, if you prefer the graphical view of gitk
或者,如果您更喜欢 gitk 的图形视图
gitk path/to/file
You can also do this once you've started gitk through the view menu; one of the options for a view is a list of paths to include.
您也可以在通过视图菜单启动 gitk 后执行此操作;视图的选项之一是要包含的路径列表。
Either way, you'll be able to find the SHA1 (hash) of the commit with the version of the file you want. Now, all you have to do is this:
无论哪种方式,您都可以找到具有所需文件版本的提交的 SHA1(哈希)。现在,您所要做的就是:
# get the version of the file from the given commit
git checkout <commit> path/to/file
# and commit this modification
git commit
(The checkout command first reads the file into the index, then copies it into the work tree, so there's no need to use git add
to add it to the index in preparation for committing.)
(checkout 命令首先将文件读入索引,然后将其复制到工作树中,因此无需使用git add
将其添加到索引中以准备提交。)
If your file may not have a simple history (e.g. renames and copies), see VonC's excellent comment. git
can be directed to search more carefully for such things, at the expense of speed. If you're confident the history's simple, you needn't bother.
如果您的文件可能没有简单的历史记录(例如重命名和复制),请参阅 VonC 的精彩评论。git
可以指示以牺牲速度为代价更仔细地搜索此类内容。如果你确信历史很简单,你就不必费心了。
回答by Jim Hurne
Git is very flexible. You shouldn't need hundreds of branches to do what you are asking. If you want to revert the state all the way back to the 2nd change (and it is indeed a change that was already committed and pushed), use git revert
. Something like:
Git非常灵活。您不应该需要数百个分支来执行您的要求。如果您想将状态一直恢复到第二次更改(并且确实是已经提交和推送的更改),请使用git revert
. 就像是:
git revert a4r9593432
where a4r9593432 is the starting characters of the hash of the commit you want to back out.
其中 a4r9593432 是您要撤销的提交哈希的起始字符。
If the commit contains changes to many files, but you just want to revert just one of the files, you can use git reset
(the 2nd or 3rd form):
如果提交包含对许多文件的更改,但您只想还原其中一个文件,则可以使用git reset
(第 2 种或第 3 种形式):
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
But this is pretty complex, and git reset is dangerous. Use git checkout <hash> <file path>
instead, as Jefromi suggests.
但这相当复杂,而且 git reset 很危险。git checkout <hash> <file path>
改为使用,正如 Jefromi 建议的那样。
If you just want to view what the file looked like in commit x, you can use git show
:
如果您只想查看提交 x 中文件的样子,可以使用git show
:
git show a4r9593432:path/to/file.txt
For all of the commands, there are many ways to refer to a commit other than via the commit hash (see Naming Commitsin the Git User Manual).
对于所有命令,除了通过提交哈希之外,还有很多方法可以引用提交(请参阅Git 用户手册中的命名提交)。
回答by Ben Straub
Git doesn't think in terms of file versions. A version in git is a snapshot of the entire tree.
Git 不考虑文件版本。git 中的一个版本是整个树的快照。
Given this, what you really want is a tree that has the latest content of most files, but with the contents of one file the same as it was 5 commits ago. This will take the form of a new commit on top of the old ones, and the latest version of the tree will have what you want.
鉴于此,您真正想要的是一棵树,其中包含大多数文件的最新内容,但其中一个文件的内容与 5 次提交前的内容相同。这将采用在旧提交之上进行新提交的形式,并且树的最新版本将包含您想要的内容。
I don't know if there's a one-liner that will revert a single file to the contents of 5 commits ago, but the lo-fi solution should work: checkout master~5
, copy the file somewhere else, checkout master
, copy the file back, then commit.
我不知道是否有一个单行可以将单个文件恢复为 5 次提交前的内容,但 lo-fi 解决方案应该有效: checkout master~5
,将文件复制到其他地方, checkout master
,将文件复制回来,然后犯罪。
回答by Alex Budovski
You can take a diff that undoes the changes you want and commit that.
您可以使用一个差异来撤消您想要的更改并提交它。
E.g. If you want to undo the changes in the range from..to
, do the following
例如,如果您想撤消范围内的更改from..to
,请执行以下操作
git diff to..from > foo.diff # get a reverse diff
patch < foo.diff
git commit -a -m "Undid changes from..to".
回答by Felipe
Extracted from here: http://git.661346.n2.nabble.com/Revert-a-single-commit-in-a-single-file-td6064050.html
从这里提取: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
It worked very fine to me.
它对我来说非常好。