本文是本人对 Git 基本使用的学习记录,参考了 Git 官方网站的文档。首先我们将说明什么是 Git,然后我们来说明它的使用方法。
Git 是一个分布式的版本控制系统。那么什么是版本控制系统,分布式又是什么?
什么是“版本控制”?我为什么要关心它呢?版本控制是一种记录一个或若干文件内容变化,以便将来查阅特定版本修订情况的系统。
有了版本控制系统你就可以将选定的文件回溯到之前的状态,你还可以比较文件的变化细节。使用版本控制系统通常还意味着,就算你乱来一气把整个项目中的文件改的改删的删,你也照样可以轻松恢复到原先的样子。
许多人习惯用复制整个项目目录的方式来保存不同的版本,或许还会改名加上备份时间以示区别。这么做唯一的好处就是简单,但是特别容易犯错。有时候会混淆所在的工作目录,一不小心会写错文件或者覆盖意想外的文件。
为了解决这个问题,人们很久以前就开发了许多种本地版本控制系统,大多都是采用某种简单的数据库来记录文件的历次更新差异。
接下来人们又遇到一个问题,如何让在不同系统上的开发者协同工作?于是,集中化的版本控制系统(Centralized Version Control Systems,简称 CVCS)应运而生。这类系统都有一个单一的集中管理的服务器,保存所有文件的修订版本,而协同工作的人们都通过客户端连到这台服务器,取出最新的文件或者提交更新。多年以来,这已成为版本控制系统的标准做法。 然而这么做最显而易见的缺点是中央服务器的单点故障。如果宕机一小时,那么在这一小时内,谁都无法提交更新,也就无法协同工作。如果中心数据库所在的磁盘发生损坏,又没有做恰当备份,毫无疑问你将丢失所有数据——包括项目的整个变更历史。
于是分布式版本控制系统(Distributed Version Control System,简称 DVCS)面世了。在这类系统中,客户端并不只提取最新版本的文件快照,而是把代码仓库完整地镜像下来,包括完整的历史记录。这么一来,任何一处协同工作用的服务器发生故障,事后都可以用任何一个镜像出来的本地仓库恢复。因为每一次的克隆操作,实际上都是一次对代码仓库的完整备份。
Git 的诞生与 Linux 关系密切。
Linux 内核开源项目有着为数众多的参与者。绝大多数的 Linux 内核维护工作都花在了提交补丁和保存归档的繁琐事务上(1991-2002年间)。到 2002 年,整个项目组开始启用一个专有的分布式版本控制系统 BitKeeper 来管理和维护代码。到了 2005 年,开发 BitKeeper 的商业公司同 Linux 内核开源社区的合作关系结束,他们收回了 Linux 内核社区免费使用 BitKeeper 的权力。这就迫使 Linux 开源社区(特别是 Linux 的缔造者 Linus Torvalds)基于使用 BitKeeper 时的经验教训,开发出自己的版本系统。他们对新的系统制订了若干目标:
没错,这个新系统就是 Git。自诞生于 2005 年以来,Git 日臻成熟完善,在高度易用的同时,仍然保留着初期设定的目标。它的速度飞快,极其适合管理大项目,有着令人难以置信的非线性分支管理系统。
前往 Git 官方网站进行下载,按照安装包的提示安装即可。
可以使用相应 Linux 发行版的软件包管理工具进行下载安装。Git 官方网站上有在各种 Linux 发行版的系统上的安装步骤。
既然已经在系统上安装了 Git,你会想要做几件事来定制你的 Git 环境。每台计算机上只需要配置一次,程序升级时会保留配置信息。你可以在任何时候再次通过运行命令来修改它们。
Git 自带一个 git config
的工具来帮助设置控制 Git 外观和行为的配置变量。在 Linux 下,这些变量存储在三个不同的位置:
/etc/gitconfig
文件:包含系统上每一个用户及他们仓库的通用配置。如果在执行 git config
时带上 --system
选项,那么它就会读写该文件中的配置变量。(由于它是系统配置文件,因此你需要管理员或超级用户权限来修改它。)
~/.gitconfig
或 ~/.config/git/config
文件:只针对当前用户。你可以传递 --global
选项让 Git 读写此文件,这会对你系统上所有的仓库生效。
当前使用仓库的 Git 目录中的 config
文件(即 .git/config
):针对该仓库。你可以传递 --local
选项让 Git 强制读写此文件,虽然默认情况下用的就是它。(当然,你需要进入某个 Git 仓库中才能让该选项生效。)
每一个级别会覆盖上一级别的配置,比如 .git/config
的配置变量会覆盖 /etc/gitconfig
中的配置变量。
在 Windows 系统中,Git 会查找 $HOME
目录下(一般情况下是 C:\Users\$USER
)的 .gitconfig
文件。这就相当于上述的第 2 级别的配置。
你可以通过以下命令查看所有的配置以及它们所在的文件:
git config --list --show-origin
安装完 Git 之后,要做的第一件事就是设置你的用户名和邮件地址。这一点很重要,因为每一个 Git 提交都会使用这些信息,它们会写入到你的每一次提交中,不可更改:
git config --global user.name "your name"
git config --global user.email "your email"
再次强调,如果使用了 --global
选项,那么该命令只需要运行一次,因为之后无论你在该系统上做任何事情, Git 都会使用那些信息。当你想针对特定项目使用不同的用户名称与邮件地址时,可以在那个项目目录下运行没有 --global
选项的命令来配置。
如果想要检查你的配置,可以使用以下命令来列出所有 Git 当时能找到的配置:
git config --list
你可能会看到重复的变量名,因为 Git 会从不同的文件中读取同一个配置(例如:/etc/gitconfig
与 ~/.gitconfig
)。这种情况下,Git 会使用它找到的每一个变量的最后一个配置。
我们也许会想要使用 Github。在这里给出对它的一些配置,这对于其他与 Github 类似的 Git 托管网站(如国内的 Gitee)来说步骤都是一样的。
首先我们要有一个 Github 账号,这要去 https://github.com/ 自行注册。现在,你就完全可以使用 https
协议,通过你刚刚创建的用户名和密码访问 Git 版本库。
如果你习惯使用 SSH 远程,你需要配置一个公钥。步骤如下:
首先,你需要确认自己是否已经拥有密钥。默认情况下,用户的 SSH 密钥存储在其 ~/.ssh
目录下。对于 Windows 系统来说,一般来说是 C:\Users\$USER
。查看该目录你便可以快速确认自己是否已拥有密钥。我们需要寻找一对以 id_dsa
或 id_rsa
命名的文件,其中一个带有 .pub
扩展名。.pub
文件是你的公钥,另一个则是与之对应的私钥。如果找不到这样的文件(或者根本没有 .ssh
目录),你可以通过运行 ssh-keygen
程序来创建它们。在 Linux/macOS 系统中,ssh-keygen
随 SSH 软件包提供;在 Windows 上,该程序包含于 MSysGit 软件包中。
首先 ssh-keygen
会确认密钥的存储位置(默认是 .ssh/id_rsa
),然后它会要求你输入两次密钥口令。如果你不想在使用密钥时输入口令,将其留空即可。然而,如果你使用了密码,那么请确保添加了 -o
选项,它会以比默认格式更能抗暴力破解的格式保存私钥。你也可以用 ssh-agent
工具来避免每次都要输入密码。
接下来,你就可以去你的 Github 账户设置左侧的“SSH keys”部分,点击“Add an SSH key”按钮,给你的公钥起一个名字,将你的 .ssh/id_rsa.pub
(或者自定义的其它名字)公钥文件的内容粘贴到文本区,然后添加。
注意,请确保给你的 SSH 密钥起一个能够记得住的名字。你可以为每一个密钥起名字(例如,“我的笔记本电脑”或者“工作账户”等),以便以后需要吊销密钥时能够方便地区分。
通常有两种获取 Git 项目仓库的方式:
两种方式都会在你的本地机器上得到一个工作就绪的 Git 仓库。
首先我们需要进入该目录中,然后执行:
git init
这样,这个目录就被转换为 Git 仓库。
如果你想获得一份已经存在了的 Git 仓库的拷贝,比如说,你想为某个开源项目贡献自己的一份力,这时就要用到 git clone
命令:
git clone
这样,就会在你的本地克隆下来服务器上的仓库。
现在我们的机器上有了一个真实项目的 Git 仓库,并从这个仓库中检出了所有文件的工作副本。通常,你会对这些文件做些修改,每当完成了一个阶段的目标,想要将记录下它时,就将它提交到仓库。
请记住,你工作目录下的每一个文件都不外乎这两种状态:已跟踪 或 未跟踪。已跟踪的文件是指那些被纳入了版本控制的文件,在上一次快照中有它们的记录,在工作一段时间后,它们的状态可能是未修改,已修改或已放入暂存区。简而言之,已跟踪的文件就是 Git 已经知道的文件。
工作目录中除已跟踪文件外的其它所有文件都属于未跟踪文件,它们既不存在于上次快照的记录中,也没有被放入暂存区。初次克隆某个仓库的时候,工作目录中的所有文件都属于已跟踪文件,并处于未修改状态,因为 Git 刚刚检出了它们,而你尚未编辑过它们。
编辑过某些文件之后,由于自上次提交后你对它们做了修改,Git 将它们标记为已修改文件。在工作时,你可以选择性地将这些修改过的文件放入暂存区,然后提交所有已暂存的修改,如此反复。
可以用 git status
命令查看哪些文件处于什么状态:
git status
使用命令 git add
开始跟踪一个文件或者把已跟踪的文件放到暂存区:
git add
现在的暂存区已经准备就绪,可以提交了。在此之前,请务必确认还有什么已修改或新建的文件还没有 git add
过,否则提交的时候不会记录这些尚未暂存的变化。这些已修改但未暂存的文件只会保留在本地磁盘。所以,每次准备提交前,先用 git status
看下,你所需要的文件是不是都已暂存起来了,然后再运行提交命令 git commit
:
git commit -m "commit message"
这里,-m
选项后面跟着的就是提交信息。如果没有这个选项,输入指令 git commit
就会进入类似 vim 的提交信息编辑的界面。
为了能在任意 Git 项目上协作,你需要知道如何管理自己的远程仓库。远程仓库是指托管在因特网或其他网络中的你的项目的版本库。我们之前提到的 git clone
命令自行添加了克隆的远程仓库,这里我们将说明如何自己来添加它。使用 git remote add
添加一个新的远程 Git 仓库,同时指定一个方便使用的简写:
git remote add
从远程仓库中获得数据,可以执行:
git fetch
这个命令会访问远程仓库,从中拉取所有你还没有的数据。执行完成后,你将会拥有那个远程仓库中所有分支的引用,可以随时合并或查看。如果你使用 git clone
命令克隆了一个仓库,命令会自动将其添加为远程仓库并默认以 “origin” 为简写。所以,git fetch origin
会抓取克隆(或上一次抓取)后新推送的所有工作。必须注意 git fetch
命令只会将数据下载到你的本地仓库——它并不会自动合并或修改你当前的工作。当准备好时你必须手动将其合并入你的工作。
如果你的当前分支设置了跟踪远程分支,那么可以用 git pull
命令来自动抓取后合并该远程分支到当前分支。
当你想要将 master 分支推送到 origin 服务器时(再次说明,克隆时通常会自动帮你设置好那两个名字),那么运行这个命令就可以将你所做的备份到服务器:
git push origin master
只有当你有所克隆服务器的写入权限,并且之前没有人推送过时,这条命令才能生效。当你和其他人在同一时间克隆,他们先推送到上游然后你再推送到上游,你的推送就会毫无疑问地被拒绝。你必须先抓取他们的工作并将其合并进你的工作后才能推送。