Git - WinDaLex/windalex.github.io GitHub Wiki

Git 是一种版本控制工具,是由著名的 Linux 内核开发者 Linus Torvalds 为了管理 Linux 内核开发而设计的。

相对于其他版本控制工具(如 CVS、SVN 等),Git 有很大的不同,有许多更为强大的特性和功能,但因此也有较复杂的学习曲线。鉴于 Git 强大的能力,大量的开源项目使用 Git 作为主要的版本控制系统,还有非常出名的开源平台 Github,就是以 Git 为技术核心搭建的。

Feature

分布式的版本控制系统

不同于常用的 CVS、SVN 等其他主流版本控制系统,Git 最明显的特点就是分布式,这意味着在每台工作的电脑上,都存有一份所有文件和版本信息的拷贝。因此,Git 不必太担心主服务器的单点故障,也因此,Git 大部分操作完全可以在本地完成,只需要在联网的时候提交到远程服务器即可。

保存文件的快照,而不是变化

除此之外,Git 存储文件的方式和其他的版本控制系统也不一样。大多数版本控制只记录每次文件的修改,而 Git 则储存了所有文件的快照,就算一个文件只修改一行数据,Git 就会生成一个新的快照来存储该新文件。这种做法表面上耗时耗力,但实际上使得 Git 可以将文件快速回退到之前任何一个版本。而对其他版本控制系统来说,越久之前的版本,意味着越多的补丁需要回退,需要花费的时间越长。

轻量级的分支

Git 的杀手锏,是它的轻量级分支。不同于其他版本控制系统,建立一个分支需要大量的时间,Git 要建立一个分支是非常迅速的。因为 Git 实现了一个文件系统,而这个文件系统的本质是一个 DAG(有向无环图)。我们可以将所有的文件看作一个目录树,而每次 commit 是一个指向根目录的指针,每个分支又是一个指向 commit 的指针。因此,新建一个分支对 Git 来说,就是向一个文件写入一个 commit 的哈希值(只有几十个字符长度),这样简单的操作罢了。

暂存

Git 每次提交变化都需要两步:先将变化添加到暂存区,再将暂存区中的内容提交到版本库。这使得用户可以将修改的内容分次提交到版本库中,并且更易于撤销或重做。不过这使得用户需要理解暂存的概念,造成了一定的学习成本。即便如此,花费一点时间去学习,使得自己可以熟练运用这个特性是很值得的。

协作中的公有和私有

在大多数集中式的版本控制系统中,一次 commit 就意味着你将修改的代码附上注释提交到公共的版本库中公开给其它协作者。而在 Git 中,你可以在本地按自己的思路进行多次“短小精悍”的 commit 之后,将其修改至满意为止,再将它“推”(使用 push 命令)到公共的版本库中。这过程中,既有私有的过程,又有公开的过程,让程序员可以更舒适地进行开发,写出更好的代码。

当然,对于那些害怕学习 Git 的人来说,这又是一道鸿沟。

Usage

要想使用 Git,你必须使用命令 git init 初始化一个新的仓库,或者使用命令 git clone 一个现有的仓库。普通目录和 Git 仓库的区别在于,Git 仓库中,除了项目文件之外,还有一个名为 .git 的隐藏目录,该目录存放了所有版本信息及 git 中的对象、指针等文件。

在 Git 中,文件有四种状态,分别是:untracked,unmodified,modified,staged。

要想对项目进行版本控制,首先,需要对项目文件进行跟踪。跟踪文件发生变化之后,可以将文件暂存。这时候,文件会进入暂存区。可以多次执行命令将修改过的文件放入暂存区后,执行一次提交更新的命令,所有变化便会被提交到版本库中。

这过程中,涉及到 Git 最常用的两个命令有 git add、git commit。除此之外,git rm、git mv 等命令也是在这过程中可能用到的。

当涉及 Git 的分支功能时,还有 git branch、git checkout 等常用命令。

而当涉及 Git 的远程仓库时,还需要用到 git push、git pull、git fetch 等命令。

所有 Git 常用的命令如下(输入 git help 命令可以查看):

  • add:将文件内容添加到暂存区中。
  • bisect:用二分法寻找引入了 bug 的提交。
  • branch:列出、创建或删除分支。
  • checkout:切换到一个分支或工作路径。
  • clone:复制一个仓库到一个新的目录中。
  • commit:将变化提交到仓库中。
  • diff:找出提交与提交之间,提交与目录之间等不同版本间的变化。
  • fetch:从远程库中下载更新,更新的变化不会被提交。
  • grep:输出文件中匹配了模式的内容。
  • init:创建一个空的 Git 仓库,或者将一个现存的仓库初始化。
  • log:查看提交日志。
  • merge:合并两个或多个分支。
  • mv:移动或者重命名文件、目录或符号链接。
  • pull:执行 fetch 命令,并且提交变化,使得本地库与远程库保证完全一致。
  • push:将本地的更新提交到远程仓库。
  • rebase:将一个分支的提交逐一更新到另一个分支上(与 merge 功能类似,但有所区别)。
  • reset:还原到某一个特定的版本。
  • rm:从目录树和暂存区中移除文件。
  • show:显示 Git 对象的不同属性。
  • status:显示工作目录的状态(查看当前所有做过的修改)。
  • tag:创建、列出、删除或验证标签。

具体 Git 的使用方法,在每个介绍 Git 的资料中都有详细说明。请见 Reference。

Tips

命令自动补全

Git 默认无法像其他命令行工具一样,用 tab 键自动补全或给出建议,但其实 Git 有提供自动完成脚本,需要自己手动将脚本加载到 Shell 中。步骤如下:

  1. 下载 Git 的源码。
  2. 在 contrib/completion/ 目录中,可以看到几个后缀不同的文件。根据 Shell 的类型,下载对应的文件。例如:使用的是 Bash,则下载 git-completion.bash 文件。
  3. 将该文件放在 HOME 目录下,最好在文件名前面加个点,使之变成隐藏文件,即 cp git-completion.bash ~/.git-completion.bash
  4. 让 Shell 自动加载该脚本。例如,在 .bashrc 或 .bash_profile 中添加一行 source ~/.git-completion.bash

Learn Git

要学习 Git,推荐先看这篇 git - the simple guide,快速上手操作一两个版本库。然后查阅 Git Reference 了解每个命令的用法。之后,就可以看 Pro Git 这部 Git 的经典教材。最后,你还可以玩一下 Githug 这个 Git 小游戏,面对各种情况和需求,实际操练一下。

Reference

  • git - the simple guide:短小精悍的 Git 入门教程,介绍最基本的 Git 命令和原理,快速上手 Git。
  • Git Reference:针对 Git 的命令逐一进行讲解,有详细的说明和示例。
  • Pro Git:相对于 Git Reference 更为详细,Git 进阶书籍。
  • Githug:Git 游戏,在实践中掌握 Git。