本文翻译自:Reverting a single file to a previous version in git [duplicate]
This question already has an answer here: 这个问题在这里已有答案:
- How can I reset or revert a file to a specific revision? 如何将文件重置或还原为特定版本? 32 answers 32个答案
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? 有人可以清楚吗?
#1楼
参考:https://stackoom.com/question/BTCj/将单个文件还原为git中的先前版本-复制
#2楼
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. 它对我来说非常好。
#3楼
Git doesn't think in terms of file versions. Git没有考虑文件版本。 A version in git is a snapshot of the entire tree. 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. 鉴于此,你真正想要的是一个具有大多数文件的最新内容的树,但是一个文件的内容与5个提交前相同。 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. 这将采用旧提交之上的新提交的形式,并且最新版本的树将具有您想要的。
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个提交前的内容,但是低保真解决方案应该有效:checkout master~5
,将文件复制到其他地方,checkout master
,复制归档,然后提交。
#4楼
You can take a diff that undoes the changes you want and commit that. 您可以采取一个差异来撤消您想要的更改并提交它。
Eg 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".
#5楼
Let's start with a qualitative description of what we want to do (much of this is said in Ben Straub's answer). 让我们从对我们想要做的事情的定性描述开始(Ben Straub的回答中说明了这一点)。 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. 首先,git不保留单个文件的版本号。 It just tracks content - a commit is essentially a snapshot of the work tree, along with some metadata (eg 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.) (我们不能只是沉迷于历史,因为我们已经推动了这些内容,并且编辑历史与其他人混淆。)
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; 一旦你通过视图菜单启动了gitk,你也可以这样做; one of the options for a view is a list of paths to include. 视图的一个选项是要包含的路径列表。
Either way, you'll be able to find the SHA1 (hash) of the commit with the version of the file you want. 无论哪种方式,您都可以使用所需文件的版本找到提交的SHA1(哈希)。 Now, all you have to do is this: 现在,你所要做的就是:
# 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 (eg renames and copies), see VonC's excellent comment. 如果您的文件可能没有简单的历史记录(例如重命名和复制),请参阅VonC的优秀评论。 git
can be directed to search more carefully for such things, at the expense of speed. 可以引导git
以更快的速度搜索这些东西。 If you're confident the history's simple, you needn't bother. 如果你对历史的简单有信心,你就不必费心了。
#6楼
Git is very flexible. Git非常灵活。 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
. 如果你想将状态一直恢复到第二次更改(并且它确实是已经提交和推送的更改),请使用git revert
。 Something like: 就像是:
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
(第二或第三种形式):
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. 但这非常复杂,git reset很危险。 Use git checkout <hash> <file path>
instead, as Jefromi suggests. 正如Jefromi建议的那样,使用git checkout <hash> <file path>
。
If you just want to view what the file looked like in commit x, you can use git show
: 如果您只想在commit 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 Commits in the Git User Manual). 对于所有命令,除了通过提交哈希之外,还有很多方法可以引用提交(请参阅Git用户手册中的命名提交 )。