1.1 – Git 入门
一、关于版本控制
版本控制是一套系统,该系统按时间顺序记录某一个或一系列文件的变更,让你可以查看其以前的特定版本。
版本控制系统:Version Control System (VCS)
(一)本地版本控制系统
- 将文件复制到另一个文件目录下,加上时间戳,是最简单但也最容易出错的版本控制方式;
- RCS:常用 VCS 工具,通过叠加保存在磁盘上的补丁集(patch set)使文件恢复到某个历史状态;

(二)集中式版本控制系统 CVCS
- 有一个包含所有修订版本的单一服务器,多个客户端可以从这个中心位置检出文件;
- 缺点:服务器如果宕机,任何人都无法协作或提交更改;如果磁盘受损,可能丢失历史记录。

(三)分布式版本控制系统 DVCS
- 客户端对代码仓库(repository)进行完整镜像,而不仅是检出文件的快照;

二、关于 Git
(一)快照而非差异
- Git 与其他 VCS 的最大区别是对待数据的方式。
- Git 将数据视为一个微型文件系统的一组快照:
- 每次提交或在 Git 中保存项目状态时,Git 会抓取一张所有文件当前状态的快照,然后存储一个指向该快照的引用;
- 如果文件未发生变动,Git 则不会重新保存文件,而是留下一个指向先前已经保存过的相同文件的链接;

传统版本控制系统,存储对每个文件的基础版本做出的改动

Git 将数据存储为随时间变化的项目快照
(二)几乎所有操作都在本地执行
- Git 的大部分操作只需要应用到本地文件和资源,使 Git 的速度惊人;
- 可以在离线状态下继续大部分工作。
(三)Git 的完整性
- Git 中所有的数据在存储前都会执行校验和计算,随后以校验和来引用对应的数据,意味着 Git 对所有文件/目录的更改都知情;
- Git 采用 SHA-1 散列(一个由 40 个十六进制字符组成的字符串)进行校验。
(四)Git 通常只增加数据
- Git 中基本所有的操作都只是向 Git 数据库中添加数据,很难让系统执行无法撤销的操作;
- Git 中你有可能弄丢/弄乱未提交的变更,但一旦提交就基本不可能丢失。
(五)三种状态
- 在 Git 中,文件可以处于以下三种状态之一:
- 已提交(committed):数据被安全地存入本地数据库中;
- 已修改(modified):已经改动了文件,但尚未提交;
- 已暂存(staged):对已修改文件的当前版本做出了标识,并将其加入下一次要提交的快照中;

- Git 项目的三个主要区域:
- Git 目录:最重要的部分,是 Git 保存项目元数据和对象数据库的地方,也是克隆仓库时要复制的内容;
- 工作目录:项目某个版本的单次检出,从 Git 目录下的压缩数据库内被提取出,放置在磁盘上以供使用和修改;
- 暂存区:单个文件,一般位于 Git 目录下,保存了下次所要提交内容的信息;
- Git 的基本工作流:
- 修改工作目录中的文件;
- 暂存文件,将这些文件的快照加入暂存区;
- 提交暂存区的文件,将快照永久保存在 Git 目录中;
- 状态的判断:
- 处在 Git 目录中的文件版本就被认为是 已提交 状态;
- 如果该文件被修改,且处于暂存区,就处于 已暂存 状态;
- 如果检出后发生了变更,但未被暂存,则处于 已修改 状态。
三、安装 Git
Getting Started – Installing Git
https://git-scm.com/book/en/v2/Getting-Started-Installing-Git
四、Git 的首次配置
Git 包含了名为 git config 的配置工具,可获取和设置配置变量。
配置变量存储的三个位置
[path]/etc/gitconfig文件:- 包含系统中所有用户及其仓库的值;
--system选项;
~/.gitconfigor~/.config/git/config文件:- 针对你自己;
-- global选项;
- 当前仓库的 Git 目录(即
.git/config)中的 config 文件:- 针对单个仓库;
-- local选项。
常用操作
- 设置用户身份:
- 设置用户名和电子邮件地址:
$ git config --global user.name "Du Guiyu"$ git config --global user.email duhelan07@outlook.com - 只需要进行一次配置,Git 此后的每一次提交都使用这些信息,非常重要;
- 设置用户名和电子邮件地址:
- 设置个人编辑器:
- 例如 Emacs:
$ git config --global core.editor emacs - 例如在 Windows 系统中使用 Nodepad++:
$ git config --global core.editor "'C:/Program Files/Notepad++/notepad++.exe' -multiInst -notabbar -nosession -noPlugin"(路径后的选项是启动参数,是 Nodepad++ 自己定义并解析的命令行选项) - 当 Git 需要输入消息时会用到该编辑器,如果不配置编辑器,在 Git 发起编辑操作时可能会提前终止;
- 例如 Emacs:
- 检查个人设置:
- 使用
git config --list命令即可列出当前 Git 可找到的所有设置; - 使用
git config <key>命令可查看 Git 配置中当前某个键的值。
- 使用
五、获取帮助
使用以下三种方式可查看 Git 命令的帮助:
$ git help <verb>
$ git <verb> --help
$ man git-<verb>例如 git help config
1.2 – Git 基本操作
一、获取 Git 仓库
建立 Git 项目的方法有两种:
- 把现有的项目 / 目录导入 Git;
- 从服务器上克隆现有的 Git 仓库。
(一)在现有目录中初始化 Git 仓库
进入项目目录并输入:git init ;


(二)克隆现有仓库
进入项目目录并输入:git clone <url> ,该命令提供了许多可选项:
# 当前在 C:\projects
$ git clone https://github.com/user/repo.git
# 结果:C:\projects\repo\...
$ git clone https://github.com/user/repo.git myrepo
# 结果:C:\projects\myrepo\...
$ git clone https://github.com/user/repo.git .
# 结果:C:\projects\...(要求当前目录为空)
$ git clone https://github.com/user/repo.git path/to/dir
# 结果:C:\projects\path\to\dir\...(dir 目录必须为空)二、在 Git 仓库中记录变更
工作目录下的每个文件都处于两种状态之一:
- 已跟踪(tracked):上一次快照中包含的文件;
- 又可分为:已修改;未修改;已暂存;
- 未跟踪(untracked):除已跟踪外的所有文件,即 不在上一次快照中,也不在暂存区中的文件。

(一)查看当前文件状态
检查文件状态使用 git status 命令。
# 克隆仓库后立即使用 git status 命令:
$ git status
On branch master
Your branch is up-to-date with 'origin/main'.
nothing to commit, working tree clean如果向项目中添加一个 README 文件,再使用命令。Git 不会主动添加新文件到下一次的提交范围,所以该文件会处于 未跟踪 状态:
# 新建 README.md 文件并写入内容
$ echo 'hello, world' > README.md
$ git status
On branch master
No commits yet
Untracked files:
(use "git add <file>..." to include in what will be committed)
README.md
nothing added to commit but untracked files present (use "git add" to track)(二)跟踪新文件
使用 git add <file/path> 命令让 Git 跟踪新文件:
- 如果参数为目录,则递归跟踪目录下的所有文件。
$ git add README.md
$ git status
On branch master
No commits yet
Changes to be committed:
(use "git rm --cached <file>..." to unstage)
new file: README.md(三)暂存已修改的文件
git add 是多功能命令,其核心操作是把内容写入暂存区,所以既可用来跟踪新文件,也可用来暂存文件。
# 添加一些内容到 README.md 末尾
$ echo "Welcome to salmon-isle.com!" >> README.md
$ git status
On branch master
No commits yet
Changes to be committed:
(use "git rm --cached <file>..." to unstage)
new file: README.md
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in working directory)
modified: README.md
$ git add README.md
$ git status
On branch master
No commits yet
Changes to be committed:
(use "git rm --cached <file>..." to unstage)
new file: README.md
为什么第一次的 git status 中 README.md 同时出现在了已暂存和未暂存列表中?
- 暂存文件时,Git 保存该文件在
git add时的样子; - 如果现在执行
git commit,则会提交该文件上次git add时的版本,而不是当前工作目录中的版本; - 所以,若暂存区中文件发生修改,需再执行一次
git add;
(四)显示更简洁的状态信息
执行 git status -s 或 git status --short 显示更简洁的状态信息:
$ git status -s
M README
MM Rakefile
A lib/git.rb
M lib/simplegit.rb
?? LICENSE.txt| 字母 | 含义 |
|---|---|
M | modified,已修改 |
A | added,新增并已暂存 |
D | deleted,已删除 |
R | renamed,重命名 |
C | copied,复制 |
U | updated but unmerged,冲突未解决 |
?? | untracked,未跟踪 |
!! | ignored,被忽略 |
(五)忽略文件
如果不希望某类文件被 Git 自动添加 / 出现在 Untracked 列表中(如日志文件、构建文件),可创建 .gitignore 文件,列出带匹配文件的模式(pattern):
- 空行 / 以 # 开头的行会被忽略;
- 支持标准 glob 模式;
- 正斜杠(/)开头的模式,禁止递归匹配。
- 正斜杠(/)结束的模式,表示目录。
- 感叹号(!)开头的模式,表示取反。
*.a # 忽略所有 .a 文件
!lib.a # 但跟踪 lib.a,即使上面忽略了 .a 文件
/TODO # 只忽略当前目录下的 TODO 文件,而不是 subdir/TODO
build/ # 忽略任何名为 build 的目录中的所有文件
doc/*.txt # 忽略 doc/notes.txt,但不忽略 doc/server/arch.txt
doc/**/*.pdf # 忽略 doc/ 目录及其所有子目录中的所有 .pdf 文件参考资料:
glob (programming) – Wikipedia
https://en.wikipedia.org/wiki/Glob_(programming)
GitHub 官方 .gitignore 模版库,涵盖了百余种不同项目和语言
https://github.com/github/gitignore
