如何在 Git 中恢复旧版本文件

6 位读者喜欢这篇文章。
4 manilla folders, yellow, green, purple, blue

Open Clip Art Library (公共领域)。Jen Wike Huger 修改。

阅读

在今天的文章中,您将学习如何了解您在项目历史记录中的位置,如何恢复旧版本文件,以及如何创建 Git 分支,以便您可以安全地进行大胆的实验。

您在 Git 项目历史记录中的位置,就像您在一张摇滚专辑中的位置一样,是由一个名为 HEAD 的标记决定的(类似于磁带录音机或唱片机的播放头)。要在您自己的 Git 时间线中移动 HEAD,请使用 git checkout 命令。

有两种使用 git checkout 命令的方法。一种常见的用途是从之前的提交中恢复文件,您也可以倒带整个磁带,然后完全朝不同的方向前进。

恢复文件

当您意识到您完全破坏了一个原本不错的文件时,就会发生这种情况。我们都会这样做;我们将文件修改到一个很好的状态,我们添加并提交它,然后我们决定它真正需要的是最后一次调整,结果文件变得完全无法识别。

要将其恢复到以前的良好状态,请使用 git checkout 从上次已知的提交(即 HEAD)开始

$ git checkout HEAD filename

如果您不小心提交了一个错误的文件版本,并且需要从更早的时间点恢复版本,请查看您的 Git 日志以查看您之前的提交,然后从相应的提交中检出它

$ git log --oneline
79a4e5f bad take
f449007 The second commit
55df4c2 My great project, first commit.

$ git checkout 55df4c2 filename

现在,旧版本的文件已恢复到您当前的位置。(您可以随时使用 git status 命令查看您的当前状态。)您需要添加该文件,因为它已更改,然后提交它

$ git add filename
$ git commit -m 'restoring filename from first commit.'

查看您的 Git 日志以验证您所做的操作

$ git log --oneline
d512580 restoring filename from first commit
79a4e5f bad take
f449007 The second commit
55df4c2 My great project, first commit.

从本质上讲,您已经倒带了磁带,并且正在覆盖一个糟糕的录音。因此,您需要重新录制好的录音。

倒带时间线

检出文件的另一种方法是倒带整个 Git 项目。这引入了分支的概念,分支在某种程度上是同一首歌的不同版本。

当您回到历史记录中时,您会将 Git HEAD 倒回到项目之前的版本。此示例将倒回到您的原始提交

$ git log --oneline
d512580 restoring filename from first commit
79a4e5f bad take
f449007 The second commit
55df4c2 My great project, first commit.

$ git checkout 55df4c2

当您以这种方式倒带磁带时,如果您按下录制按钮并向前走,您将破坏您未来的工作。默认情况下,Git 假定您不想这样做,因此它会将 HEAD 从项目中分离出来,并让您根据需要工作,而不会意外覆盖您稍后录制的内容。

如果您查看之前的版本,并且突然意识到您想要重新做所有事情,或者至少尝试不同的方法,那么安全的方法是创建一个新分支。您可以将此过程视为尝试同一首歌的不同版本,或创建混音。原始素材存在,但您正在分支出来并制作自己的版本来玩。

要让您的 Git HEAD 回到空白磁带上,请创建一个新分支

$ git checkout -b remix
Switched to a new branch 'remix'

现在您已经回到过去,并且在您面前有一个备用的、干净的工作区,随时可以进行您想要做的任何更改。

您可以在不回到过去的情况下做同样的事情。也许您对当前的进度非常满意,但想切换到一个临时工作区来尝试一些疯狂的想法。这也是完全可以接受的工作流程

$ git status
On branch master
nothing to commit, working directory clean

$ git checkout -b crazy_idea
Switched to a new branch 'crazy_idea'

现在您有了一个干净的工作区,您可以在其中沙箱化一些疯狂的新想法。完成后,您可以保留您的更改,也可以忘记它们的存在,然后切换回您的 master 分支。

要羞愧地忘记您的想法,请切换回您的 master 分支,并假装您的新分支不存在

$ git checkout master

要保留您的疯狂想法并将它们拉回到您的 master 分支,请切换回您的 master 分支并合并您的新分支

$ git checkout master
$ git merge crazy_idea

分支是 git 的强大方面,开发人员通常在克隆仓库后立即创建一个新分支;这样,他们所有的工作都包含在他们自己的分支上,他们可以提交该分支以合并到 master 分支。Git 非常灵活,因此没有“正确”或“错误”的方法(即使 master 分支也可以与它所属的远程仓库区分开来),但分支使分离任务和贡献变得容易。不要太过分,但在你我之间,你可以拥有任意多的 Git 分支。它们是免费的!

使用远程仓库

到目前为止,您已经在自己舒适且私密的家中维护了一个 Git 仓库,但是当您与其他人一起工作时呢?

有几种不同的方法可以设置 Git,以便多人可以同时在一个项目上工作,因此现在我们将重点关注克隆的工作,无论您是从某人的个人 Git 服务器还是他们的 GitHub 页面,还是从同一网络上的共享驱动器获得该克隆。

在您自己的私有 Git 仓库上工作与在您想要与他人共享的内容上工作之间的唯一区别是,在某个时候,您需要将您的更改 push 到其他人的仓库。我们将您正在工作的仓库称为本地仓库,将任何其他仓库称为远程仓库。

当您从另一个源克隆一个具有读取和写入权限的仓库时,您的克隆会继承它来自的远程仓库作为其origin。您可以看到克隆的远程仓库

$ git remote --verbose
origin  seth@example.com:~/myproject.Git (fetch)
origin  seth@example.com:~/myproject.Git (push)

拥有远程 origin 很方便,因为它在功能上是异地备份,并且还允许其他人参与该项目。

如果您的克隆没有继承远程 origin,或者如果您选择稍后添加一个,请使用 git remote 命令

$ git remote add seth@example.com:~/myproject.Git

如果您更改了文件并想将它们发送到您的远程 origin,并且具有对该仓库的读取和写入权限,请使用 git push。首次推送更改时,您还必须发送您的分支信息。除非您被告知这样做,否则最好不要在 master 上工作

$ git checkout -b seth-dev
$ git add exciting-new-file.txt
$ git commit -m 'first push to remote'
$ git push -u origin HEAD

这会将您当前的位置(HEAD,自然地)及其存在的分支推送到远程仓库。在您推送分支一次后,您可以删除 -u 选项

$ git add another-file.txt
$ git commit -m 'another push to remote'
$ git push origin HEAD

合并分支

当您在 Git 仓库中单独工作时,您可以随时将测试分支合并到您的 master 分支中。当与贡献者协同工作时,您可能需要在将他们的更改合并到您的 master 分支之前对其进行审查

$ git checkout contributor
$ git pull
$ less blah.txt  # review the changed files
$ git checkout master
$ git merge contributor

如果您正在使用 GitHub 或 GitLab 或类似的东西,则过程有所不同。在那里,传统做法是 fork 项目并将其视为您自己的仓库。您可以在仓库中工作,并将更改发送到您的 GitHub 或 GitLab 帐户,而无需获得任何人的许可,因为它是您的仓库。

如果您希望您 fork 的人收到您的更改,您可以创建一个拉取请求,它使用 Web 服务的后端将补丁发送给真正的所有者,并允许他们审查和拉取您的更改。

Fork 项目通常在 Web 服务上完成,但管理您的项目副本的 Git 命令是相同的,甚至 push 过程也是如此。然后回到 Web 服务打开一个拉取请求,工作就完成了。

在我们的下一期中,我们将研究一些便利的附加组件,以帮助您将 Git 舒适地集成到您的日常工作流程中。

标签
Seth Kenlon
Seth Kenlon 是一位 UNIX 极客、自由文化倡导者、独立多媒体艺术家和 D&D 爱好者。他曾在电影和计算机行业工作,而且经常同时从事这两个行业。

5 条评论

很棒的系列!! :)
对于像这样的出色工具非常有用!
谢谢

谢谢!这才刚刚开始令人兴奋。即将推出:git hooks、git GUI 以及许多其他内容!

回复 作者 victorhck (未验证)

你好 Seth!

又是我 (https://rocketgit.com)!

并非所有 git 托管解决方案都需要在推送之前进行克隆。
RocketGit 允许匿名用户直接推送到主仓库,但是推送不会成功,而是会自动转换为拉取请求!
您甚至不需要在 rocketgit.com 上注册帐户!
我认为这是为项目做出贡献的最短途径。

非常感谢您的文章。我是一个初学者,一直在努力定义 git 到底是什么以及如何使用它。您的解释非常清楚,并且帮助很大。
再次感谢您。

很高兴听到这个,感谢您的反馈,Michelle!慢慢来,git 最终会变得有意义!

回复 作者 Michelle

Creative Commons License本作品根据知识共享署名-相同方式共享 4.0 国际许可协议获得许可。
© . All rights reserved.