Git 学习笔记

一、准备

学习材料:
官方中文书《Pro Git 第二版》
在线可视化交互式学习Git分支操作
廖雪峰的Git教程

1. 简介

Git 是一种主流的分布式的版本控制系统(version control system, or VCS)。

版本控制系统是指记录文件内容变化以便查阅特定版本修订情况的系统,它能够将文件甚至整个项目回退到特定版本。

分布式是指系统允许同一项目由不同环境下的开发者协同工作;如果某处用于协同工作的服务器发生故障,可以用其他镜像出来的本地仓库恢复。

主流是因为 Git 开源免费,速度快,功能强大,能高效管理超大规模的项目,完全支持大量并行分支下的多人开发模式。

2. 基础概念

特性

  • 记录快照:每次提交更新或保存项目状态时,它主要对当时的全部文件制作一个快照并保存这个快照的索引;Git 不再重新存储没有改动的文件,而是保留指向已存储的文件的链接。

  • 几乎本地执行:绝大多数操作都只需要访问本地文件和资源,一般不需要来自网络上其它计算机的信息。

  • 保证完整性:Git 在存储前计算所有数据的校验和,然后以校验和来引用。这意味着不可能在 Git 不知情时更改任何文件内容或目录内容。

  • 一般只添加数据:Git 操作几乎只往 Git 数据库中增加数据。一旦你提交快照到 Git 中,就难以再丢失数据。

工作区域

仓库(repository, or .git)存放项目的元数据以及对象数据库。仓库是 Git 的核心。克隆仓库就是克隆.git目录。

工作目录(working directory)存放从仓库的压缩数据库中拷贝出来的某个版本的项目文件,放在外存以供使用或修改。

暂存区域(staging area, or index)是一个文件,保存了下次将提交的文件列表信息,一般在仓库中。

文件状态

Git 中的文件分三种基本的状态:

  • 已提交(committed):该文件已保存在本地数据库中。
  • 已修改(modified):该文件已被修改,但未保存到数据库中。
  • 已暂存(staged):该文件已被修改且被标记,使之包含在下次提交的快照中。

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

:在项目目录下但不在 Git 中的文件属于未跟踪状态(untracked);在分支合并时起冲突的文件会被标记成未合并状态(unmerged)。

3. 分支模型

分支简介

暂存操作(git add)会先为每一个文件用哈希算法计算校验和,再把当前版本的文件快照保存为 blob 对象放到仓库,最后把校验和加入到暂存区域等待提交。

提交操作(git commit)会先计算每一个子目录的校验和,再把校验和保存为 tree 对象放到仓库。
然后,Git 创建一个提交对象(commit object),它包含:

  • 指向 blob 对象的指针;
  • 指向 tree 对象的指针;
  • 指向父对象的指针;
  • 作者姓名和邮箱地址;
  • 提交时的注释信息。

Git 的分支,其实本质上就是指向提交对象的可变指针。从存储的角度来说就是一个包含所指对象校验和的文件。

创建仓库的操作(git init)会默认设置一个分支,代表主分支,一般名为mastermain
创建分支的操作也仅仅是增加了一个可以移动的指针。

Git 中有一个特殊指针HEAD,用于指向当前所在的分支。
每次提交时HEAD会自动移动以指向最新的提交对象。
切换分支的操作就是切换HEAD的指向,同时会改变工作目录中的文件以还原切换后的分支最后一次提交后的状态。

分支合并

在项目中为了修复某个 bug 或者增加某个功能,开发者往往要新建一个对应的分支,然后在该分支上工作,编码完成和测试无误后再回到主分支以合并该分支。至此主分支包含了该分支的工作,所以可以删除该分支。

一次合并一般要用到三个快照:

  • 当前分支末端所指的快照;
  • 待合并分支末端所指的快照;
  • 两个分支的公共祖先所指的快照。

一般地。三方合并后会创建一个新的快照并且自动创建一个新的提交指向它。因此三方合并会使得当前分支指针指向两个父提交对象。
特殊地,如果两个分支互相“平行”,即顺着当前分支走下去能到达待合并的分支,那么合并时会把指针直接向前快速推进(fast-forward)。

遇到冲突的分支合并

如果在两个不同的分支中对同一文件的同一部分进行了不同修改,Git 做了合并但不会自动创建一个新的合并提交。Git 会报告冲突并等待手动解决。
Git 会在有冲突的文件中加入标准的冲突解决标记,这样你可以打开这些包含冲突的文件然后手动解决冲突。

4. 远程仓库

远程仓库是指托管在网络中的项目的版本库。
特殊地,远程仓库也可以设置在本地主机上,“远程”只是代表在别的地方。

当你克隆(git clone)了一个远程仓库,Git 会默认给该远程仓库所在服务器命名为origin

抓取操作(git fetch)会尝试从目标远程仓库中下载本地仓库还没有的数据;
拉取操作(git pull)会抓取数据后并自动尝试合并到当前的分支;
推送操作(git push)会尝试向目标远程仓库上传本地更新的数据;

抓取不会自动合并或修改当前的工作
推送在对远程仓库有写权限且抓取并合并远程仓库后才生效
拉取和推送都需要本地的分支设置了跟踪远程分支

远程分支

远程跟踪分支是对远程分支状态的引用。在每一次抓取远程数据后,远程跟踪分支会自动移动以同步远程仓库的状态。

变基

5. 安装

注:对于 CentOS 7,yum 安装的 Git 版本较低,如果需要升级需要下载新版的源码编译安装;对于学生用的云服务器,编译过程可能会出现内存不足,需要自行设置系统的交换分区。

因为每次提交都需要用户名和邮箱地址,所以安装后必须设置用户名和邮箱。

二、基础

Git 速查表

注:新版 Git 支持一些新的命令,比如git restore来分担一名多用的git checkout
$$a_1 \cdot \frac{1-q^n}{1-q}$$