Git 使用指南

 一、版本控制系统(Version Control Systems)简介

        版本控制系统是跟踪文件随时间变化的工具。版本控制允许您查看或恢复到以前的文件迭代。版本控制的某些方面实际上内置于常用的应用程序中。想想undo命令或者如何查看Google文档的修订历史记录。

        在编码背景下,版本控制系统可以跟踪代码修订的历史记录,从代码的当前状态一直追溯到第一次跟踪。这允许用户引用其工作的旧版本并与其他人(例如其他开发人员)共享代码更改。

        版本控制已成为行业软件开发和协作的支柱。Git 拥有优秀的文档,因此那些有兴趣的人可以阅读更多有关本指南其余部分将总结的内容。

Git简介

        Git 是一个分布式版本控制系统,而不是集中式版本控制系统。这意味着每个开发人员的计算机都存储了整个项目的整个历史记录(包括所有旧版本)!这与 Dropbox 等工具截然不同,在 Dropbox 中,旧版本存储在其他人拥有的远程服务器上。我们将整个项目的整个历史称为“存储库(repository)”。存储库存储在本地的事实使我们能够在自己的计算机上本地使用 Git,即使没有互联网连接。

        如果您还没有安装Git,该链接解释了如何在您自己的计算机上安装 git以及学习初级的命令行操作。除了我们将在本指南中学习使用的基于文本的界面之外,还有一个 Git GUI(图形用户界面),在这里不会涉及Git GUI。

二、本地存储库(Local Repositories )(叙述性介绍)

        让我们通过一个叙述性示例来说明如何使用 git。我们将在这个故事中使用许多不熟悉的术语和想法。

        假设我们想在计算机上存储各种食谱,并且还想在更改这些食谱时跟踪这些食谱的历史记录。我们可以首先为面筋和豆腐食谱创建目录,然后使用 sublime 创建每个食谱(在我的计算机上使用 subl 命令调用)。

        我们假设您只是阅读本文,而不是自己尝试这些命令。如果您想继续输入所有内容,则需要使用计算机上安装的文本编辑器而不是 subl

$ cd /users/sandra
$ mkdir recipes
$ cd recipes
$ mkdir seitan
$ mkdir tofu
$ cd seitan
$ subl smoky_carrot_tahini_seitan_slaw.txt
$ subl boiled_seitan.txt
$ cd ../tofu
$ subl kung_pao_tofu.txt
$ subl basil_ginger_tofu.txt

        现在我们有四种食谱,两种是豆腐,两种是面筋。要设置 git 存储库来存储菜谱演变的历史记录,我们将使用以下命令:

$ cd /users/sandra/recipes
$ git init

        git init 的作用是告诉 git 版本控制系统我们要跟踪当前目录的历史记录,在本例中为“/users/sandra/recipes” 。然而,此时没有任何东西存储在存储库中。这就像我们买了一个保险箱,但我们还没有放任何东西进去。

        为了将所有内容存储在存储库中,我们需要首先添加文件。例如,我们可能会执行以下操作:

git add ./tofu/kung_pao_tofu.txt

        现在,git 开始变得奇怪了。即使在调用 add 命令之后,我们仍然没有将我们的配方存储在存储库中(即保险箱中)。相反,我们所做的是将 kung_pao_tofu.txt 添加到要跟踪的文件列表中(即稍后添加到保险箱中)。这个想法是,您可能不想跟踪 /users/sandra/recipes 文件夹中的每个文件,因此 add 命令告诉 git 应该跟踪哪些文件。我们可以通过git status命令来查看该命令的效果。

$ git status

        在这种情况下,您会看到以下响应:

On branch master

Initial commit

Changes to be committed:
  (use "git rm --cached <file>..." to unstage)

    new file:   tofu/kung_pao_tofu.txt

Untracked files:
  (use "git add <file>..." to include in what will be committed)

    seitan/
    tofu/basil_ginger_tofu.txt

        输出的“changes to be committed”部分列出了当前正在跟踪且其更改已准备好提交的所有文件(即已准备好放入保险箱中)。我们还看到有一些未跟踪的文件,即seitan 文件夹和tofu/basil_ginger_tofu.txt 文件。这些未跟踪,因为我们没有使用 git add 添加它们。

        让我们尝试添加 tofu/basil_ginger_tofu.txt,并再次检查状态:

$ git add ./tofu/basil_ginger_tofu.txt
$ git status
On branch master

Initial commit

Changes to be committed:
  (use "git rm --cached <file>..." to unstage)

    new file:   tofu/basil_ginger_tofu.txt
    new file:   tofu/kung_pao_tofu.txt

Untracked files:
  (use "git add <file>..." to include in what will be committed)

    seitan/

        我们看到两个豆腐食谱都被跟踪,但面筋食谱都没有被跟踪。接下来,我们将使用 commit 命令将豆腐食谱的副本粘贴到存储库中(即放入保险箱中)。为此,我们使用 git commit 命令,如下所示:

$ git commit -m "added tofu recipes"

        当执行时,commit命令将所有添加文件(例如当前豆腐食谱)的快照存储到存储库中。因为我们没有在面筋食谱上使用 git add,所以它们没有包含在放置在存储库中的快照中。我们的工作快照现在永远安全(只要我们的计算机硬盘不出现故障或者我们不损坏秘密存储库文件)。-m 命令允许我们向提交添加一条消息,这样我们就可以记住此提交中最重要的内容。

        再打个比方,你可以把整个过程想象成用相机拍摄全景照片。add 命令捕获图像的一部分,commit 命令将所有“添加(added)”的项目拼接到一个全景图中,并将该全景图放入保险箱中。正如全景图仅包含您所指向的内容(而不是您周围的整个 360 度圆圈)一样,commit 命令仅保护那些使用 add 命令添加的文件(而不是 Recipes 目录中的所有文件)。

        使用提交(commit)后,您会注意到 git status 不再在“要提交的更改(changes to be commited)”下列出文件。这类似于拍摄完全景照片后,所有临时的小图像文件都会被丢弃。此时git status的结果如下所示:

$ git status
On branch master
Untracked files:
  (use "git add <file>..." to include in what will be committed)

    seitan/

nothing added to commit but untracked files present (use "git add" to track)

        如果您查看 tofu 文件夹中的文件,您会发现提交过程不会影响我们计算机上的原始文件。这很像当您为朋友拍摄全景照片时,他们不会陷入手机内的网络地狱景观中。

        我们可以使用特殊的 git log 命令查看快照(snapshot)的证据。

$ git log

commit 9f955d85359fc8e4504d7220f13fad34f8f2c62b
Author: Sandra Upson <sandra@Sandras-MacBook-Air.local>
Date:   Sun Jan 17 19:06:48 2016 -0800

    added tofu recipes

         这个巨大的字符串 9f955d85359fc8e4504d7220f13fad34f8f2c62b 是提交的ID。我们可以使用 git show 命令来查看此提交的内部情况。

$ git show 9f955d85359fc8e4504d7220f13fad34f8f2c62b

commit 9f955d85359fc8e4504d7220f13fad34f8f2c62b
Author: Sandra Upson <sandra@Sandras-MacBook-Air.local>
Date:   Sun Jan 17 19:06:48 2016 -0800

    added tofu recipes

diff --git a/tofu/basil_ginger_tofu.txt b/tofu/basil_ginger_tofu.txt
new file mode 100644
index 0000000..9a56e7a
--- /dev/null
+++ b/tofu/basil_ginger_tofu.txt
@@ -0,0 +1,3 @@
+basil
+ginger
+tofu
diff --git a/tofu/kung_pao_tofu.txt b/tofu/kung_pao_tofu.txt
new file mode 100644 index
0000000..dad9bd9
--- /dev/null
+++ b/tofu/kung_pao_tofu.txt
@@ -0,0 +1,3 @@
+szechuan peppers
+tofu
+peanuts
+kung
+pao

        git show 命令让我们可以直接查看提交的核心内容。并不期望它的所有内部结构对您来说都有意义,但您也许可以了解到提交(commit)是文件名称和内容的快照。注意:您很少会在现实生活中使用 git show 命令,但它在这里对于查看提交内部以更好地了解它们是什么很有用。

        假设我们现在想要修改我们的kung_pao_tofu.txt食谱,因为我们决定其中应该有白菜。我们刚刚对kung_pao_tofu.txt所做的更改没有保存在存储库中。事实上,如果我们再次执行git status,我们会得到:

$ git status

On branch master
Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

    modified:   tofu/kung_pao_tofu.txt

Untracked files:
  (use "git add <file>..." to include in what will be committed)

    seitan/

 您可能会想:“好吧,我会再次提交”。然而,如果我们尝试提交,git 会说没有什么可做的:

On branch master
Changes not staged for commit:
    modified:   tofu/kung_pao_tofu.txt

Untracked files:
    seitan/

no changes added to commit

 这是因为即使 kung_pao_tofu.txt 正在被跟踪,我们也没有暂存我们的更改以进行提交。要将我们的更改存储在存储库中,我们首先需要再次使用 add 命令,这将暂存提交的更改(或者换句话说,我们需要先拍摄新的 kung_pao_tofu.txt 的照片,然后才能创建要放入保险箱的新全景图)。

$ git add ./tofu/kung_pao_tofu.txt
$ git status

On branch master
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

    modified:   tofu/kung_pao_tofu.txt

Untracked files:
  (use "git add <file>..." to include in what will be committed)

    seitan

 我们看到对 kung_pao_tofu.txt 的更改现在是“待提交”,这意味着下一次提交将包括对此文件的更改。我们像以前一样提交,并使用 git log 查看已拍摄的所有快照的列表

$ git commit -m "added bok choy"
$ git log

commit cfcc8cbd88a763712dec2d6bd541b2783fa1f23b
Author: Sandra Upson <sandra@Sandras-MacBook-Air.local>
Date:   Sun Jan 17 19:24:45 2016 -0800

    added bok choy

commit 9f955d85359fc8e4504d7220f13fad34f8f2c62b
Author: Sandra Upson <sandra@Sandras-MacBook-Air.local>
Date:   Sun Jan 17 19:06:48 2016 -0800

    added tofu recipes

我们现在看到有两个提交。

假设我们后来认为白菜很恶心。我们可以使用 checkout 命令回滚我们的文件,如下所示:

$ git checkout 9f955d85359fc8e4504d7220f13fad34f8f2c62b ./recipes/tofu

把checkout命令想象成一个机器人,它进入我们的保险箱,找出豆腐食谱在最新全景图9f955d85359fc8e4504d7220f13fad34f8f2c62b时的样子,并最终重新排列实际食谱/豆腐文件夹中的所有内容,使其与创建快照9f955d85359fc8e4504d7220f13fad34f8f2c62b时完全一样。如果我们现在在运行这个命令后查看recipes/tofu/ kung_pao_tofu.txt的内容,我们会看到白菜不见了!

重要提示:checkout命令不会更改提交历史记录!或者换句话说,包含我们全景照片的保险箱完全不受checkout命令的影响。git 的全部意义在于创建一个日志,记录我们文件中发生的所有事情。换句话说,如果您在 2014 年和 2015 年拍摄了您房间的全景照片并将它们放在保险箱中,然后在 2016 年决定将其完全放回原样,就像 2014 年一样,那么你就不会把2015年的全景照片放火烧了。你的保险箱里也不会神奇地出现一张 2016 年的照片。如果您想记录 2016 年的情况,则需要再拍一张照片(使用适当的 -m 消息来记住您刚刚做了什么)。

同样重要的是:请确保在使用 checkout 时指定文件(或目录)。否则,您使用的checkout功能更强大,可能会让您感到困惑。如果出现这种情况,请参阅61B git-WTFS (git奇怪的技术故障场景)。

如果我们想实际提交最新的宫保豆腐(不再有白菜)的快照,我们必须提交:

$ git commit -m "went back to the original recipe with no bok choy"
$ git log

commit 4be06747886d0a270bf1d618d58f3273f0219a69
Author: Sandra Upson <sandra@Sandras-MacBook-Air.local>
Date:   Sun Jan 17 19:32:37 2016 -0800

    went back to the original recipe with no bok choy

commit cfcc8cbd88a763712dec2d6bd541b2783fa1f23b
Author: Sandra Upson <sandra@Sandras-MacBook-Air.local>
Date:   Sun Jan 17 19:24:45 2016 -0800

    added bok choy

commit 9f955d85359fc8e4504d7220f13fad34f8f2c62b
Author: Sandra Upson <sandra@Sandras-MacBook-Air.local>
Date:   Sun Jan 17 19:06:48 2016 -0800

    added tofu recipes

 然后我们可以使用 show 来查看最近提交的内容。

$ git show 4be06747886d0a270bf1d618d58f3273f0219a69

commit 4be06747886d0a270bf1d618d58f3273f0219a69
Author: Sandra Upson <sandra@Sandras-MacBook-Air.local>
Date:   Sun Jan 17 19:32:37 2016 -0800

    took boy choy out gross

diff --git a/tofu/kung_pao_tofu.txt b/tofu/kung_pao_tofu.txt
index 35a9e71..dad9bd9 100644
--- a/tofu/kung_pao_tofu.txt
+++ b/tofu/kung_pao_tofu.txt
@@ -1,4 +1,3 @@
szechuan
peppers
tofu
peanuts
kung
pao
-bok choy
\ No newline at end of file

不是很重要的注意事项:非常细心的读者可能已经注意到,在我提交删除白菜之前,我没有使用 git add 。 这是因为一个有趣的事实是,checkout 实际上还会对因回滚而发生更改的任何文件执行自动 git add 操作。

这是git的基础。总而言之,使用我们的照片类比:

git init:创建一个盒子,在其中永久存储全景图片。

git add:拍摄一个事物的临时照片,稍后可以将其组装成全景照片。

git commit:将所有可用的临时照片组装成全景照片。还会销毁所有临时照片。

git log:列出我们拍摄过的所有全景照片

git show:查看特定全景照片中的内容

git checkout:将文件重新排列回它们在给定全景照片中的外观。不会以任何方式影响您盒子里的全景照片。

三、本地存储库(技术概述)

初始化本地存储库

让我们首先从本地存储库开始。如上所述,存储库存储文件以及这些文件的更改历史记录。首先,您必须在要在本地存储库中存储其历史记录的目录中,在终端中键入以下命令来初始化 Git 存储库。如果您使用的是 Windows,则在键入这些命令时应该使用 Git Bash 终端窗口。

$ git init

额外信息:当您初始化 Git 存储库时,Git 会创建一个 .git 子目录。 在这个目录中,它将存储一堆元数据,以及旧的文件的实际快照。但是,您永远不需要实际打开此 .git 目录的内容,并且您绝对不应该直接更改其中的任何内容!

根据您的操作系统,您可能看不到文件夹,因为名称以"."开始,默认情况下,操作系统不会显示。UNIX命令"ls -la"将列出所有目录,包括.git目录,因此您可以使用该命令检查repo是否已正确初始化。

跟踪文件与未跟踪文件

Git 存储库一开始不跟踪任何文件。为了保存文件的修订历史记录,您需要跟踪它。 Git 文档中有一个关于记录更改的精彩部分。为了您的方便,该部分的图像放置在此处:

 如图所示,文件分为两大类:

1.未跟踪的文件:这些文件从未被跟踪或已从跟踪中删除。 Git 不维护这些文件的历史记录。

2.跟踪文件:这些文件已经添加到Git存储库中,并且可以处于不同的修改阶段:未修改(unmodified)、修改(modified)或暂存(staged)。

        2.1 未修改的文件是指自文件的最后一个版本添加到 Git 存储库以来没有发生任何新更改的文件。

        2.2 修改后的文件与 Git 上次保存的文件不同。

        2.3 暂存文件是用户指定为未来提交的一部分的文件(通常通过使用 git add 命令)。我们可以把它们想象成有光照射的文件。

以下 Git 命令允许您查看每个文件的状态,即是否未跟踪、未修改、已修改或已暂存

$ git status

 git status 命令对于确定存储中库每个文件的确切状态非常有用。如果您对已更改的内容和需要提交的内容感到困惑,它可以提醒您下一步该做什么。

暂存和提交

提交是工作目录在特定时间的特定快照。用户必须通过暂存文件指定快照的具体组成。add 命令允许您暂存一个文件(在下面的示例中称为 FILE)。

$ git add FILE

一旦您准备好要包含在快照中的所有文件,您就可以将它们作为一个带有消息的块提交。

$ git commit -m MESSAGE

 您的消息应该是描述性的,并解释您的提交对代码所做的更改。您可能希望快速描述错误修复、实现的类等,以便您的消息在稍后查看提交日志时有所帮助。为了查看以前的提交,您可以使用 log 命令:

$ git log

作为开发工作流程的旁注,尽可能频繁地提交代码是个好主意。每当您对代码进行重大(甚至微小)更改时,请进行提交。如果你正在尝试一些你可能无法坚持的东西,请将其提交(也许提交到不同的分支,这将在下面解释)。

 经验法则:如果您提交,您随时可以恢复或更改代码。但是,如果您不提交,您将无法恢复旧版本。所以经常提交!

撤消更改

Git 参考中有一个关于撤销操作的重要部分。请注意,虽然Git是围绕历史记录的概念展开的,但如果使用其中一些undo命令进行恢复,可能会丢失您的工作。因此,在撤消工作之前,请务必小心并了解更改的影响。

取消暂存尚未提交的文件:

  $ git reset HEAD [file]

这将使文件的状态恢复为已修改,保持更改不变。不用担心此命令会撤消任何工作。此命令相当于删除要组合成全景图的临时图像之一。为什么我们需要使用这个命令?假设您不小心开始跟踪您不想跟踪的文件(例如,您自己的尴尬视频)。或者您对一个文件进行了一些更改,您认为您会提交但现在不想再提交。

修改最新提交(更改提交消息或添加忘记的文件):

  $ git add [forgotten-file]
  $ git commit --amend

请注意,这个新的修改提交将取代之前的提交。

将文件恢复到最近提交时的状态 :

 $ git checkout -- [file]

 如果您想实际撤消您的工作,则下一个命令非常有用。假设您自之前提交以来修改了某个文件,但您希望文件恢复到修改之前的状态。

注意:此命令可能非常危险,因为自上次提交以来对文件所做的任何更改都将被删除。请谨慎使用!

四、远程仓库

Git 的一项特别方便的功能是能够将存储库的副本存储在您自己的计算机之外的计算机上。回想一下,我们的快照都存储在我们计算机上的一个秘密文件夹中。这意味着如果我们的计算机被损坏或毁坏,我们所有的快照也会被损坏或毁坏。

假设我们想将豆腐和面筋食谱推送到另一台计算机,我们通常会使用以下命令:、

$ git push origin master

 但是,如果我们尝试一下,我们只会收到以下消息:

fatal: 'origin' does not appear to be a git repository
fatal: Could not read from remote repository.

Please make sure you have the correct access rights and the repository exists.

这是因为我们还没有告诉 git 将文件发送到哪里。碰巧的是,有一家名为 GitHub 的营利性私营公司,它以存储人们的存储库副本为业务。他们的商业模式很简单:你付钱给他们来存储你的存储库(尽管如果你向全世界开放,或者如果你像我们为 61B 所做的那样安排特殊的免费折扣,他们就会让你拥有免费的存储库)。

我们将使用 GitHub 来存储我们的存储库。要在 GitHub 上创建存储库,您可能会使用他们的 Web 界面。

下面列出了最重要的远程存储库命令,以及可能还没有意义的技术描述。

git clone [remote-repo-URL]:在本地计算机上创建指定存储库的副本。还创建一个工作目录,其中的文件排列方式与下载存储库中的最新快照完全相同。还记录用于后续网络数据传输的远程存储库的 URL,并为其赋予特殊的远程存储库名称“origin”。

git remote add [remote-repo-name] [remote-repo-URL]:记录网络数据传输的新位置。

git remote -v:列出网络数据传输的所有位置。

git pull [remote-repo-name] master:获取remote-repo-name中看到的文件的最新副本

git push [remote-repo-name] master:将文件的最新副本推送到remote-repo-name。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值