如何在 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 的人收到您的更改,您可以创建一个pull request,它使用 Web 服务的后端将补丁发送给真正的所有者,并允许他们查看和拉取您的更改。

Fork 项目通常在 Web 服务上完成,但管理您的项目副本的 Git 命令是相同的,即使是 push 过程也是如此。然后回到 Web 服务打开 pull request,工作就完成了。

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

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

5 条评论

很棒的系列!! :)
对于这样一个伟大的工具非常有用!
谢谢

谢谢!它才刚刚变得令人兴奋。接下来还有:git hooks、git GUI 以及很多其他东西!

回复 作者 victorhck (未验证)

你好 Seth!

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

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

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

Creative Commons License本作品根据 Creative Commons Attribution-Share Alike 4.0 International License 许可。
© . All rights reserved.