协慌网

登录 贡献 社区

如何将单个文件还原到以前的版本?

有没有一种方法可以对文件进行不同的提交。假设我已经提交并推送到存储库后,我修改了文件 5 次,并且想返回到更改 2。

以我的理解,唯一的办法是保留许多分支机构,我说对了吗?如果我是对的,那么几天之内我将拥有数百个分支机构,因此我可能不太了解。

任何人都可以清理一下吗?

答案

让我们从对我们要做什么的定性描述开始(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 ,以牺牲速度为代价,更仔细地搜索此类内容。如果您确信历史很简单,那么您就不必费心了。

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 <hash> <file path>

如果只想查看 commit x 中的文件,可以使用git show

git show a4r9593432:path/to/file.txt

对于所有命令,除了通过提交哈希以外,还有许多方法可以引用提交(参见《 Git 用户手册》中的命名提交)。

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

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

我不知道是否有一个一行将恢复单个文件的 5 次提交前的内容,但是 LO-Fi 解决方案应该工作:结帐master~5 ,将文件复制在其他地方,结账master ,复制归档回去,然后提交。