Git 是所有开发人员工具箱中的重要工具。

例如就在前几天,我大约只用了 20 分钟就解决了一个已经投入生产环境的重大问题(完全是我的错)。如果没有 Git,这可能需要几天的时间来修复。

因此,让我们花些时间真正了解 Git 最基本的功能:准备和提交

注意:本文不包含与 GitHub 相关的任何内容,它是第三方在线Web服务,允许你在云端备份用 Git 保存的代码。 Git 是本地的,GitHub 是一个基于云的应用,它们是两个完全不同的东西,尽管目的相同。

什么是版本控制?

如果你年龄够大,可能还记得 Google Drive/Docs/Sheets 之前的世界,你可能会这样做:

Group_Paper_All_4_Members_Sections_Included_Final_Draft_Final_3😔.docx

处理群组项目会导致多人尝试对原始文档的多个副本进行编辑,从而导致许多重复。如果两个人同时进行编辑,则必须有人手动完成所有操作并将这些编辑组合在一起。

没有什么好办法来控制项目的不同版本。这就像是在狂野的西部一样。🤠+😢

Git解决了这个问题💡

也许你已经在自己的项目中增加了一个新功能,破坏了以前工作得很好的东西,但不知道在哪里找到错误或如何解决它。你已经在编辑器中关闭了文件,因此就不能再使用“撤消”了。

Git解决了这个问题💡

好的,但是 Git 是怎样解决这些问题的?

Git 的核心功能是在文件中创建保存点。我觉得这些保存点就像在视频游戏中一样,即使你在那之后搞砸了,总是可以回来再试一次而不必重新开始。

Git 还有很多令人敬畏的方面,但是它的全部内容的核心是:在代码中创建保存点,如果需要,可以在之后返回。

Git 是怎样工作的?

Git 的这个核心功能(在你的项目中创建保存点)分为两个阶段:

  1. 将事物(更改的代码和文件)添加到要在时间线中提交(保存)的临时区域,以及
  2. 实际上提交(保存)的那些东西。

强制性对比

这两个阶段,好像你正在创建一个老式的相册,一个用于打印照片并将其放入真正的相册。如果你因为太年轻没有见过的话,就是这样的:

好吧,我实际上并没有这么老

首先,你用相机拍了一堆照片。拍摄照片并不会影响相册,因为你始终可以选择要包含在相册中的照片。你会得到拍摄得不好的照片,并在必要时重新拍摄。

下一步,你可以选择要在相册中保存哪一张照片。想象一下,你已将它们打印出来,然后将它们放置在在相册中的空白页面旁边。你正在创建一种“临时区域”,你尚未将照片粘贴到相册中的页面上,但是你准备马上就这样做。

最后,一旦你准备好了,就把你的照片粘贴到页面上,并将它们粘合在一起。一个好的相册要包含这些照片中事件的某种描述或标题。

完成操作后,你可以随时回到相册中的这个页面,回忆你当时生活中的情况(无论好坏)。

这与Git有什么关系?

让我们将这个类比与 Git 联系起来。

  • 拍摄照片就像修改项目文件(编写代码、创建文件或删除文件)。
  • 在相册中选择所需的照片就像将更改添加到“临时区域”。
  • 将照片粘贴到相册页面就像把修改提交(保存)到更改时间线中。

让我们逐一解释w。

拍摄照片就像修改项目文件一样

拍摄照片就像对项目进行更改:编写新代码、添加图像、删除旧文件等等。你正在创建最终要在 Git 提交中保存的内容(“保存点”)。它仍然是一项正在进行中的工作,你可以随时编写、重写或删除任何你想要的内容,而无需“永久”保存它们。

Git 目前正在做的唯一事情是观察自上次提交(保存)代码以来是否有什么变化。如果你添加一行代码然后再删它,Git 将会认为整体没有发生任何变化。如果你在几十个文件中编写 500 行代码,Git 能够确切地知道都有哪些代码行被添加到哪些文件中,并在其内存中跟踪这些变化。在你告诉它之前,它不会对变更的时间表做出任何提交,但它会密切关注你的操作。

注意:请记住,现在我们指的是一个与保存更改到硬盘上完全不同的过程。现代文本编辑器可以每隔一秒左右保存你的代码,但这不是我们在这里所提到的。当我提到使用 Git “保存”时,我的意思是创建一个提交,将你的更改保存到时间轴。

在相册中选择所需的照片就像将项目更改添加到“临时区域”

在 Git 中,这是在代码中创建新提交之前发生的阶段。此过程称为“添加到暂存区域”。添加到暂存区域不会创建提交,它只是准备提交。

将一些文件添加到暂存区域后,你可能会发现仍要做一些更改。没问题!由于此时 Git 尚未实际保存(提交)任何内容,你可以简单地进行所需的新更改,然后将这些更改添加到临时区域,即使这些更改发生在与先前添加的文件相同的文件中。这就像拍摄一些你决定要添加到相册页面并打进行印的新照片。

将照片粘贴到相册中就像提交代码一样

这是创建“保存点”(提交)的第二个(也是最后一个)阶段。创建提交时有一个主要要求:你必须包含信息。在相册中,你可以撰写标题或信息,以便向未来的观看者提供关于这些照片对你意味着什么的信息。在 Git 中,你需要编写一条消息来描述你要保存到代码库中的更改。

如果你写了一个糟糕的提交信息,那么回顾你的代码历史对包括你自己在内的任何人都没有帮助。 (如果你不知道这些变化是什么,那么“做出一些改变”的消息有什么用呢?想象一下,在相册中找到一个页面,上面写着“这里有一些人……”)始终使用良好的描述性提交消息来描述你添加到代码库中的功能或修复。

不要这样做 https://xkcd.com/1296/

行动

例子已经足够了,现在让我们开始吧!

安装

首先,你可能已经安装了Git。打开终端或命令提示符并尝试运行 git --version。如果它显示了版本号,请跳过后面这一步。如果它提示不知道你的 git 是什么意思,你需要安装它。 请按照以下说明为你的操作系统安装。

创建一个Git仓库

Git 只知道跟踪你设置为 Git 存储库的项目。在上面的比喻中,如果我们首先没有相册,就无法将照片粘贴到相册中。

当你准备开始一个新项目时,应该执行的第一步(创建项目文件夹之后)是运行:

git init

img

这允许 Git 立即开始跟踪你对项目所做的任何更改。在底层它会创建一个新的隐藏 .git 文件夹,其中的所有内容都需要跟踪你的更改。你几乎不需要进入这个文件夹,除非你正在设置一些高级的东西。

对项目进行更改

对于下面的教程,我将尽可能保持简单 —— 一个项目文件夹,它是一个带有单个名为 README.md markdown 文件的 Git 仓库。你可以想象我对 README 文件所做的每个更改都代表了一些新功能或者几十、几百行新代码。👌🏻😉

基本命令

git status

我想将此视为“理智检查”,用来帮助我了解 Git 目前正在进行的工作。 (例如它注意到了哪些变化,是否一切正常等等)

img

它告诉我正处在主分支上(我会另外再写一篇关于分支的文章),我之前没有提交过,而且现在没有任何东西需要提交。 (意思是,Git 没有看到任何需要要保存的文件夹)。

现在我将添加 README.md 文件并再次运行 git status:

`touch` 是一种以快速、简单的方法来创建新的空白文件的命令

Git 看到我在项目中添加了一个新文件。酷!现在这个令人敬畏的新项目正在进行中,让我们创建一个保存点。

git add

git add 命令是把东西放在临时区域的方式。就像打印我们拍摄的照片一样,然后将它们粘贴在我们的相册页面中。但是我们需要告诉 Git 我们想要添加到暂存区域。 (如果只输入 git add 会提示你没有指定任何东西,所以不会添加内容。)我将用 Git 添加文件的文件名:

git add README.md
git status

img

再次使用 git status ,显示在暂存区域有一个新文件,但它现在变成了绿色!这是提示你它已经被添加到临时区域的简单方法。

基本上 git add README.md 告诉 Git “我希望包括自上次提交后包含在即将提交中的 README.md 所做的所有更改。”

但是,将文件一次一个地添加到暂存区域是很麻烦的,特别如果有许多任务需要你去处理很多文件的话。你大可不必记住并指定正在处理的每个文件,而是可以使用“一网打尽”的方式,它会自动添加你对暂存区域进行更改的每个文件。我的首选方法是:

git add -A

-A标志表示将所有带有更改标记的文件添加到暂存区域)。

注意:你经常会看到人们用 git add . 来实现将所有更改添加到暂存区域。虽然这有效,但它要求你位于项目根目录中以确保获取所有更改。 (. 是“当前目录”的简写)。因此,如果你 cd 进入嵌套目录但对该目录外的文件进行了更改并尝试使用 git add .,那么在尝试将这些文件添加到暂存区域时,将会错过这些更改的文件。但是无论你目前在终端中的哪个位置,git add -A 都适用于整个项目。

git commit

一旦你准备好创建一个提交,就可以用 git commit 命令。但是,还记得你是如何添加备注的吗?如果你只是运行 git commit 并按回车键,将会弹出一个基于终端的编辑器,如 Vi 或 Nano,以填写该提交的信息。

你也可以用 -m 标志,然后在引号中使用字符串消息,使你的 git commit 与消息保持一致。像这样:

git commit -m "Added some really important information to the README"

假设在提交之前其他所有内容都已就绪,现在就已经使用 Git 成功提交了代码!现在你有了一个检查点,如果从这里出现问题,你可以随时返回。

让我们以 gif 的形式再看一下这个过程:

img

注意:gif 使用 git add,但我认为应该用 git add -A 更精确。此外,要使用更好的提交信息!请原谅我的错误

git log

你可以通过运行 git log 来查看提交历史记录。使用箭头键,你可以及时向前和向后滚动来检查提交日期、消息和作者(提交者)。随之一起出现的是“提交哈希”,其实质上是提交的唯一ID,可以在以后需要时用于引用它。

时间旅行

“所以你一直在谈论 Git 如何能让我及时向后跳跃……我该怎么做呢?”

git checkout

术语 “checkout” 是指从一个提交切换到另一个提交的过程。还记得每个提交收到的唯一ID(“哈希”)吗?我可以回顾一下我的提交历史,选择其中一个唯一的提交哈希值,然后用 git checkout 命令查看它。如果我想看的提交有一个 a2 的哈希值(完整它们比这长得多 - 就像 0c9b8f7c23dea4cf0a0285f14211124b6d5891e9),可以运行:

git checkout a2

突然之间,我的整个代码库的时间线缩短了,一切都会像我提交后的那样。 (这可能很吓人,因为看起来你可能已经丢失了自提交以来的所有更新,但不要担心!他们还在!)

以 gif 形式说明:

img

注意,第 3 次提交及其中的更改仍然完全存在。可以用 git checkout a3 或(更常见的)git checkout master 返回到该提交,以恢复所有更改。

现在你回来了,你会看到来自 Git 的消息。就像是:

Note: checking out 'a2'.

You are in 'detached HEAD' state. You can look around, make experimental
changes and commit them, and you can discard any commits you make in this
state without impacting any branches by performing another checkout.

If you want to create a new branch to retain commits you create, you may
do so (now or later) by using -b with the checkout command again. Example:

  git checkout -b <new-branch-name>

HEAD is now at a2 Another Message

“Detached HEAD” 听起来比现在更可怕。🤢

在这种状态下,你不再使用 master 分支,也就是说你可以在这里进行实验性更改甚至创建新的提交,所有这些操作都不会丢失你在 master 分支上的代码(上面的例子提交哈希 a3 )。

同样,我计划在另一个时间覆盖分支,但这只是为了说明 Git 在保存多个版本的代码时是一个非常强大的工具。

结论

关于 Git 你可以学到一百万个东西,但如果不了解核心概念,它总会显得有点神秘。

但是,如果你真的想学习并熟悉 Git,那么你最好的去实操并进行实验。

这意味着你要做的不仅仅是阅读文章。所以请在一个空文件夹中创建一个新的 Git 存储库,开始添加文件,用 git statusgit log 来看看是什么样的,并考虑下载 Sourcetree 以便在你搞乱项目的时候可以通过可视化来观察你存储库的状态。