如何在 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 许可协议本作品根据知识共享署名-相同方式共享 4.0 国际许可协议获得许可。
© . All rights reserved.