Git简介

  • git是一个分布式的版本控制系统(翻译一下:分布式就是多台电脑,每台电脑都保存全部文件,每两台电脑之间可以互相传输数据文件。版本控制系统就是:管理文件所有快照的一个系统)
  • git :读音[ɡɪt],翻译过来:饭桶、蠢货。为什么起这个名字呢?当年Linus编写Linux操作系统,使用的Bitkeeper工具,但是该软件的公司像linux组织开始收费,迫使linus自己开发了一个分布式版本控制软件Git,所以我们可以猜测,linus本人是在骂该公司“烂人、蠢货”,当然也有另一种猜测,程序员界大家都喜欢自嘲,没准大神当年是自嘲呢。so what,不用管了。。。
  • git本质是一个分布式的内容寻址文件系统。所以git本质是个文件夹,内容寻址的意思就是,根据文件内容生成指纹(一般使用一种哈希函数转变)然后根据指纹查询文件。所以git本质上是一个由指纹管理的文件系统。每一个文件快照通过哈希函数生成一个指纹,通过管理指纹来管理文件。

以下整理自git官方文档:https://git-scm.com/book/zh/v2 该文档非常全面、详细、简单易读

Git 简史

同生活中的许多伟大事物一样,Git 诞生于一个极富纷争大举创新的年代。
Linux 内核开源项目有着为数众多的参与者。 绝大多数的 Linux 内核维护工作都花在了提交补丁和保存归档的繁琐事务上(1991-2002年间)。 到 2002 年,整个项目组开始启用一个专有的分布式版本控制系统 BitKeeper 来管理和维护代码。
到了 2005 年,开发 BitKeeper 的商业公司同 Linux 内核开源社区的合作关系结束,他们收回了 Linux 内核社区免费使用 BitKeeper 的权力。 这就迫使 Linux 开源社区(特别是 Linux 的缔造者 Linus Torvalds)基于使用 BitKeeper 时的经验教训,开发出自己的版本系统。 他们对新的系统制订了若干目标:

  • 速度
  • 简单的设计
  • 对非线性开发模式的强力支持(允许成千上万个并行开发的分支)
  • 完全分布式
  • 有能力高效管理类似 Linux 内核一样的超大规模项目(速度和数据量)

自诞生于 2005 年以来,Git 日臻成熟完善,在高度易用的同时,仍然保留着初期设定的目标。 它的速度飞快,极其适合管理大项目,有着令人难以置信的非线性分支管理系统。

Git是怎么实现分布式版本控制的?

直接记录快照,而非差异比较

Git 和其它版本控制系统(包括 Subversion 和近似工具)的主要差别在于 Git 对待数据的方法。 从概念上来说,其它大部分系统以文件变更列表的方式存储信息,这类系统(CVS、Subversion、Perforce、Bazaar 等等) 将它们存储的信息看作是一组基本文件和每个文件随时间逐步累积的差异 (它们通常称作 基于差异(delta-based) 的版本控制)。
Git - 图1
Figure 4. 存储每个文件与初始版本的差异.
Git 不按照以上方式对待或保存数据。反之,Git 更像是把数据看作是对小型文件系统的一系列快照。 在 Git 中,每当你提交更新或保存项目状态时,它基本上就会对当时的全部文件创建一个快照并保存这个快照的索引。 为了效率,如果文件没有修改,Git 不再重新存储该文件,而是只保留一个链接指向之前存储的文件。 Git 对待数据更像是一个 快照流
Git - 图2
Figure 5. 存储项目随时间改变的快照.
这是 Git 与几乎所有其它版本控制系统的重要区别。 因此 Git 重新考虑了以前每一代版本控制系统延续下来的诸多方面。 Git 更像是一个小型的文件系统,提供了许多以此为基础构建的超强工具,而不只是一个简单的 VCS。

近乎所有操作都是本地执行

在 Git 中的绝大多数操作都只需要访问本地文件和资源,一般不需要来自网络上其它计算机的信息。 如果你习惯于所有操作都有网络延时开销的集中式版本控制系统,Git 在这方面会让你感到速度之神赐给了 Git 超凡的能量。 因为你在本地磁盘上就有项目的完整历史,所以大部分操作看起来瞬间完成。
举个例子,要浏览项目的历史,Git 不需外连到服务器去获取历史,然后再显示出来——它只需直接从本地数据库中读取。 你能立即看到项目历史。如果你想查看当前版本与一个月前的版本之间引入的修改, Git 会查找到一个月前的文件做一次本地的差异计算,而不是由远程服务器处理或从远程服务器拉回旧版本文件再来本地处理。
这也意味着你在离线或者没有 VPN 时,几乎可以进行任何操作。 如你在飞机或火车上想做些工作,就能愉快地提交(到你的 本地 副本,还记得吗?), 直到有网络连接时再上传。如你回家后 VPN 客户端不正常,那么也仍能工作。 使用其它系统的话,做到这些是不可能或很费力的。 比如,用 Perforce 的话,没有连接服务器时几乎不能做什么事;而用 Subversion 和 CVS 的话, 你能修改文件,但不能向数据库提交修改(因为你的本地数据库离线了)。 这样似乎问题不大,但是你可能会惊喜地发现它带来的巨大的不同。

Git 保证完整性

Git 中所有的数据在存储前都计算校验和,然后以校验和来引用。 这意味着不可能在 Git 不知情时更改任何文件内容或目录内容。 这个功能建构在 Git 底层,是构成 Git 哲学不可或缺的部分。 若你在传送过程中丢失信息或损坏文件,Git 就能发现。
Git 用以计算校验和的机制叫做 SHA-1 散列(hash,哈希)。 这是一个由 40 个十六进制字符(0-9 和 a-f)组成的字符串,基于 Git 中文件的内容或目录结构计算出来。 SHA-1 哈希看起来是这样:

  1. 24b9da6552252987aa493b52f8696cd6d3b00373

Git 中使用这种哈希值的情况很多,你将经常看到这种哈希值。 实际上,Git 数据库中保存的信息都是以文件内容的哈希值来索引,而不是文件名。

Git 一般只添加数据

你执行的 Git 操作,几乎只往 Git 数据库中 添加 数据。 你很难让 Git 执行任何不可逆操作,或者让它以任何方式清除数据。 同别的 VCS 一样,未提交更新时有可能丢失或弄乱修改的内容。但是一旦你提交快照到 Git 中, 就难以再丢失数据,特别是如果你定期的推送数据库到其它仓库的话。
这使得我们使用 Git 成为一个安心愉悦的过程,因为我们深知可以尽情做各种尝试,而没有把事情弄糟的危险。

Git模型

git为了实现分布式版本控制,提出了三个概念来组建VCS模型。

三种状态

现在请注意,如果你希望后面的学习更顺利,请记住下面这些关于 Git 的概念。 Git 有三种状态,你的文件可能处于其中之一: 已提交(committed)已修改(modified)已暂存(staged)

  • 已修改表示修改了文件,但还没保存到数据库中。
  • 已暂存表示对一个已修改文件的当前版本做了标记,使之包含在下次提交的快照中。
  • 已提交表示数据已经安全地保存在本地数据库中。

这会让我们的 Git 项目拥有三个阶段:工作区、暂存区以及 Git 目录。
Git - 图3
Figure 6. 工作目录、暂存区域以及 Git 仓库.

  • 工作区是对项目的某个版本独立提取出来的内容。 这些从 Git 仓库的压缩数据库中提取出来的文件,放在磁盘上供你使用或修改。
  • 暂存区是一个文件,保存了下次将要提交的文件列表信息,一般在 Git 仓库目录中。 按照 Git 的术语叫做“索引”,不过一般说法还是叫“暂存区”。
  • Git 仓库目录是 Git 用来保存项目的元数据和对象数据库的地方。 这是 Git 中最重要的部分,从其它计算机克隆仓库时,复制的就是这里的数据。

基本的 Git 工作流程如下:

  1. 在工作区中修改文件。
  2. 将你想要下次提交的更改选择性地暂存,这样只会将更改的部分添加到暂存区。
  3. 提交更新,找到暂存区的文件,将快照永久性存储到 Git 目录。

如果 Git 目录中保存着特定版本的文件,就属于 已提交 状态。 如果文件已修改并放入暂存区,就属于 已暂存 状态。 如果自上次检出后,作了修改但还没有放到暂存区域,就是 已修改 状态。

命令行

Git 有多种使用方式。 你可以使用原生的命令行模式,也可以使用 GUI 模式,这些 GUI 软件也能提供多种功能。 在本书中,我们将使用命令行模式。 这是因为首先,只有在命令行模式下你才能执行 Git 的 所有 命令,而大多数的 GUI 软件只实现了 Git 所有功能的一个子集以降低操作难度。 如果你学会了在命令行下如何操作,那么你在操作 GUI 软件时应该也不会遇到什么困难,但是,反之则不成立。 此外,由于每个人的想法与侧重点不同,不同的人常常会安装不同的 GUI 软件,但 所有 人一定会有命令行工具。
假如你是 macOS 用户,我们希望你懂得如何使用终端(Terminal);假如你是 Windows 用户,我们希望你懂得如何使用命令窗口(Command Prompt)或 PowerShell。 如果你尚未掌握以上技能,我们建议你先停下来快速学习一下,本书中的讲述和举例将用到这些技能。

安装 Git

在你开始使用 Git 前,需要将它安装在你的计算机上。 即便已经安装,最好将它升级到最新的版本。 你可以通过软件包或者其它安装程序来安装,或者下载源码编译安装。

本书写作时使用的 Git 版本为 2.8.0。 我们使用的大部分命令仍然可以在很古老的 Git 版本上使用,但也有少部分命令不好用或者在旧版本中的行为有差异。 因为 Git 在保持向后兼容方面表现很好,本书使用的这些命令在 2.8 之后的版本应该有效。

在 Linux 上安装

如果你想在 Linux 上用二进制安装程序来安装基本的 Git 工具,可以使用发行版包含的基础软件包管理工具来安装。 以 Fedora 为例,如果你在使用它(或与之紧密相关的基于 RPM 的发行版,如 RHEL 或 CentOS),你可以使用 dnf

  1. $ sudo dnf install git-all

如果你在基于 Debian 的发行版上,如 Ubuntu,请使用 apt

  1. $ sudo apt install git-all

要了解更多选择,Git 官方网站上有在各种 Unix 发行版的系统上安装步骤,网址为 https://git-scm.com/download/linux

在 macOS 上安装

在 Mac 上安装 Git 有多种方式。 最简单的方法是安装 Xcode Command Line Tools。 Mavericks (10.9) 或更高版本的系统中,在 Terminal 里尝试首次运行 git 命令即可。

  1. $ git --version

如果没有安装过命令行开发者工具,将会提示你安装。
如果你想安装更新的版本,可以使用二进制安装程序。 官方维护的 macOS Git 安装程序可以在 Git 官方网站下载,网址为 https://git-scm.com/download/mac
Git - 图4
Figure 7. Git macOS Installer.
你也可以将它作为 GitHub for macOS 的一部分来安装。 它们的图形化 Git 工具有一个安装命令行工具的选项。 你可以从 GitHub for macOS 网站下载该工具,网址为 https://mac.github.com

在 Windows 上安装

在 Windows 上安装 Git 也有几种安装方法。 官方版本可以在 Git 官方网站下载。 打开 https://git-scm.com/download/win,下载会自动开始。 要注意这是一个名为 Git for Windows 的项目(也叫做 msysGit),和 Git 是分别独立的项目;更多信息请访问 http://msysgit.github.io/
要进行自动安装,你可以使用 Git Chocolatey 包。 注意 Chocolatey 包是由社区维护的。
另一个简单的方法是安装 GitHub Desktop。 该安装程序包含图形化和命令行版本的 Git。 它也能支持 Powershell,提供了稳定的凭证缓存和健全的换行设置。 稍后我们会对这方面有更多了解,现在只要一句话就够了,这些都是你所需要的。 你可以在 GitHub for Windows 网站下载,网址为 GitHub Desktop 网站

从源代码安装

有人觉得从源码安装 Git 更实用,因为你能得到最新的版本。 二进制安装程序倾向于有一些滞后,当然近几年 Git 已经成熟,这个差异不再显著。
如果你想从源码安装 Git,需要安装 Git 依赖的库:autotools、curl、zlib、openssl、expat 和 libiconv。 如果你的系统上有 dnf (如 Fedora)或者 apt(如基于 Debian 的系统), 可以使用对应的命令来安装最少的依赖以便编译并安装 Git 的二进制版:

  1. $ sudo dnf install dh-autoreconf curl-devel expat-devel gettext-devel \
  2. openssl-devel perl-devel zlib-devel
  3. $ sudo apt-get install dh-autoreconf libcurl4-gnutls-dev libexpat1-dev \
  4. gettext libz-dev libssl-dev

为了添加文档的多种格式(doc、html、info),需要以下附加的依赖:

  1. $ sudo dnf install asciidoc xmlto docbook2X
  2. $ sudo apt-get install asciidoc xmlto docbook2x

使用 RHEL 和 RHEL 衍生版,如 CentOS 和 Scientific Linux 的用户需要 > 开启 EPEL 库 以便下载 > docbook2X 包。 如果你使用基于 Debian 的发行版(Debian/Ubuntu/Ubuntu-derivatives),你也需要 install-info 包:

  1. $ sudo apt-get install install-info

如果你使用基于 RPM 的发行版(Fedora/RHEL/RHEL衍生版),你还需要 getopt 包 (它已经在基于 Debian 的发行版中预装了):

  1. $ sudo dnf install getopt

此外,如果你使用 Fedora/RHEL/RHEL衍生版,那么你需要执行以下命令:

  1. $ sudo ln -s /usr/bin/db2x_docbook2texi /usr/bin/docbook2x-texi

以此来解决二进制文件名的不同。
当你安装好所有的必要依赖,你可以继续从几个地方来取得最新发布版本的 tar 包。 你可以从 Kernel.org 网站获取,网址为 https://www.kernel.org/pub/software/scm/git, 或从 GitHub 网站上的镜像来获得,网址为 https://github.com/git/git/releases。 通常在 GitHub 上的是最新版本,但 kernel.org 上包含有文件下载签名,如果你想验证下载正确性的话会用到。
接着,编译并安装:

  1. $ tar -zxf git-2.8.0.tar.gz
  2. $ cd git-2.8.0
  3. $ make configure
  4. $ ./configure --prefix=/usr
  5. $ make all doc info
  6. $ sudo make install install-doc install-html install-info

完成后,你可以使用 Git 来获取 Git 的更新:

  1. $ git clone git://git.kernel.org/pub/scm/git/git.git

初次运行 Git 前的配置

既然已经在系统上安装了 Git,你会想要做几件事来定制你的 Git 环境。 每台计算机上只需要配置一次,程序升级时会保留配置信息。 你可以在任何时候再次通过运行命令来修改它们。
Git 自带一个 git config 的工具来帮助设置控制 Git 外观和行为的配置变量。 这些变量存储在三个不同的位置:

  1. /etc/gitconfig 文件: 包含系统上每一个用户及他们仓库的通用配置。 如果在执行 git config 时带上 --system 选项,那么它就会读写该文件中的配置变量。 (由于它是系统配置文件,因此你需要管理员或超级用户权限来修改它。)
  2. ~/.gitconfig~/.config/git/config 文件:只针对当前用户。 你可以传递 --global 选项让 Git 读写此文件,这会对你系统上 所有 的仓库生效。
  3. 当前使用仓库的 Git 目录中的 config 文件(即 .git/config):针对该仓库。 你可以传递 --local 选项让 Git 强制读写此文件,虽然默认情况下用的就是它。。 (当然,你需要进入某个 Git 仓库中才能让该选项生效。)

每一个级别会覆盖上一级别的配置,所以 .git/config 的配置变量会覆盖 /etc/gitconfig 中的配置变量。
在 Windows 系统中,Git 会查找 $HOME 目录下(一般情况下是 C:\Users\$USER )的 .gitconfig 文件。 Git 同样也会寻找 /etc/gitconfig 文件,但只限于 MSys 的根目录下,即安装 Git 时所选的目标位置。 如果你在 Windows 上使用 Git 2.x 以后的版本,那么还有一个系统级的配置文件,Windows XP 上在 C:\Documents and Settings\All Users\Application Data\Git\config ,Windows Vista 及更新的版本在 C:\ProgramData\Git\config 。此文件只能以管理员权限通过 git config -f <file> 来修改。
你可以通过以下命令查看所有的配置以及它们所在的文件:

  1. $ git config --list --show-origin

用户信息

安装完 Git 之后,要做的第一件事就是设置你的用户名和邮件地址。 这一点很重要,因为每一个 Git 提交都会使用这些信息,它们会写入到你的每一次提交中,不可更改:

  1. $ git config --global user.name "John Doe"
  2. $ git config --global user.email johndoe@example.com

再次强调,如果使用了 --global 选项,那么该命令只需要运行一次,因为之后无论你在该系统上做任何事情, Git 都会使用那些信息。 当你想针对特定项目使用不同的用户名称与邮件地址时,可以在那个项目目录下运行没有 --global 选项的命令来配置。
很多 GUI 工具都会在第一次运行时帮助你配置这些信息。

文本编辑器

既然用户信息已经设置完毕,你可以配置默认文本编辑器了,当 Git 需要你输入信息时会调用它。 如果未配置,Git 会使用操作系统默认的文本编辑器。
如果你想使用不同的文本编辑器,例如 Emacs,可以这样做:

  1. $ git config --global core.editor emacs

在 Windows 系统上,如果你想要使用别的文本编辑器,那么必须指定可执行文件的完整路径。 它可能随你的编辑器的打包方式而不同。
对于 Notepad++,一个流行的代码编辑器来说,你可能想要使用 32 位的版本, 因为在本书编写时 64 位的版本尚不支持所有的插件。 如果你在使用 32 位的 Windows 系统,或在 64 位系统上使用 64 位的编辑器,那么你需要输入如下命令:

  1. $ git config --global core.editor "'C:/Program Files/Notepad++/notepad++.exe' -multiInst -notabbar -nosession -noPlugin"
Note Vim、Emacs 和 Notepad++ 都是流行的文本编辑器,通常程序员们会在 Linux 和 macOS 这类基于 Unix 的系统或 Windows 系统上使用它们。 如果你在使用其他的或 32 版本的编辑器,请在 core.editor 中查看设置为该编辑器的具体步骤。
Warning 如果你不这样设置编辑器,那么当 Git 试图启动它时你可能会被弄糊涂、不知所措。 例如,在 Windows 上 Git 在开始编辑时可能会过早地结束。

检查配置信息

如果想要检查你的配置,可以使用 git config --list 命令来列出所有 Git 当时能找到的配置。

  1. $ git config --list
  2. user.name=John Doe
  3. user.email=johndoe@example.com
  4. color.status=auto
  5. color.branch=auto
  6. color.interactive=auto
  7. color.diff=auto
  8. ...

你可能会看到重复的变量名,因为 Git 会从不同的文件中读取同一个配置(例如:/etc/gitconfig~/.gitconfig)。 这种情况下,Git 会使用它找到的每一个变量的最后一个配置。
你可以通过输入 git config <key>: 来检查 Git 的某一项配置

  1. $ git config user.name
  2. John Doe

| Note | 由于 Git 会从多个文件中读取同一配置变量的不同值,因此你可能会在其中看到意料之外的值而不知道为什么。 此时,你可以查询 Git 中该变量的 原始 值,它会告诉你哪一个配置文件最后设置了该值:``` $ git config —show-origin rerere.autoUpdate file:/home/johndoe/.gitconfig false

  1. |
  2. | --- | --- |
  3. <a name="FXOrV"></a>
  4. # 获取帮助
  5. 若你使用 Git 时需要获取帮助,有三种等价的方法可以找到 Git 命令的综合手册(manpage):
  6. ```bash
  7. $ git help <verb>
  8. $ git <verb> --help
  9. $ man git-<verb>

例如,要想获得 git config 命令的手册,执行

  1. $ git help config

这些命令很棒,因为你随时随地可以使用而无需联网。 如果你觉得手册或者本书的内容还不够用,你可以尝试在 Freenode IRC 服务器 https://freenode.net 上的 #git#github 频道寻求帮助。 这些频道经常有上百人在线,他们都精通 Git 并且乐于助人。
此外,如果你不需要全面的手册,只需要可用选项的快速参考,那么可以用 -h 选项获得更简明的 “help” 输出:

  1. $ git add -h
  2. usage: git add [<options>] [--] <pathspec>...
  3. -n, --dry-run dry run
  4. -v, --verbose be verbose
  5. -i, --interactive interactive picking
  6. -p, --patch select hunks interactively
  7. -e, --edit edit current diff and apply
  8. -f, --force allow adding otherwise ignored files
  9. -u, --update update tracked files
  10. --renormalize renormalize EOL of tracked files (implies -u)
  11. -N, --intent-to-add record only the fact that the path will be added later
  12. -A, --all add changes from all tracked and untracked files
  13. --ignore-removal ignore paths removed in the working tree (same as --no-all)
  14. --refresh don't add, only refresh the index
  15. --ignore-errors just skip files which cannot be added because of errors
  16. --ignore-missing check if - even missing - files are ignored in dry run
  17. --chmod (+|-)x override the executable bit of the listed files