Git 命令
参考文献:
- Git 教程 | 菜鸟教程
- Git 使用教程:最详细、最正宗手把手教学(万字长文)
- git忽略某个目录或文件不上传
文章目录
- 工作原理
- 基本命令
- 配置
- 使用
 
- 其他命令
- 日志
- 分支
- 回退
- 标签
 
- 忽略指定文件
- 远程仓库
工作原理
Git 是由 Linus Torvalds 开发的分布式版本控制系统,能够追踪各类文件的修改历史,方便备份、分支、恢复到旧版本,还可以实现协同开发、统计工作量,等等。
首先,有三个基本概念,
- 工作区(Working Directory):即我们的工作目录及其子目录,这是项目的当前状态;
- 暂存区(Staging Area):这是临时存储区,记录了工作区中尚未提交到版本库的文件快照(在 .git/index文件中记录);
- 版本库(Repository):记录每次提交的文件快照(只读),可进一步分为本地仓库(即 .git目录)和远程仓库(比如github.com)。
它们之间的关系如图所示:

本地仓库(.git 目录)包含如下的内容,
- config文件:存储该仓库特有的配置信息,可以覆盖全局配置。
- description文件:记录了该仓库的描述信息,通常没什么用。
- HEAD文件:指向当前分支,内容形如- ref: refs/heads/master(表示处于- master分支)
- index文件:这是暂存区,记录了待提交文件的元数据(文件名、权限)及其内容的哈希值(使用 SHA-1)。
- COMMIT_EDITMSG文件:记录每次提交时,所附带的描述信息。
- branches目录:在早期- Git版本中,用于用于存储本地分支的引用,当前已很少使用。
- refs目录:存储了各种引用,主要包括:本地分支(- heads子目录)、标签(- tags子目录)、远程分支(- remotes子目录)。
- objects目录:此为核心存储目录,所有的提交(commit)、树(tree)、文件内容(Binary Large Object, blob)和标签(tag)等对象都以文件形式存储在这里;每个对象都有一个哈希值,取前两位作为子目录的名称。具体而言,- tree:记录了目录结构,包含了对相应 blob 的引用;
- blob:记录了文件内容,但是不包含文件名、文件路径等信息;如果文件内容发生变化(匹配 Hash 值),执行 git add filename命令会创建新的 blob 对象;
- commit:记录了一个版本的快照,包含一个 tree 的引用,以及提交信息(提交者、提交时间、提交说明,等等);
- tag:对于某些重要的版本,可以打上有意义的标签(比如 v1.0.0),以方便后续管理和引用。
 
- info目录:主要包含- exclude文件,作用与- .gitignore类似,用于排除一些文件或目录。
- hooks目录:包含了一些 “钩子” 脚本,会在某些 Git 操作发生之前/之后自动执行。
- logs目录:存储了每个引用的日志信息,其中- logs/HEAD文件记录了当前分支的更新和切换(旧提交哈希值,新提交哈希值,操作人信息,时间戳,操作描述),- logs/refs目录存储了各个引用的变更历史(包括- heads,- remotes和- tags子目录)
基本命令
使用 --help 可以查看帮助文档。
配置
查看 Git 配置,
git config --list
编辑 Git 配置文件,
git config -e				# 打开当前仓库的 config 文件
git config -e --global		# 打开全局的 config 文件git config --global user.name "my name"			# 配置全局的用户名
git config --global user.email my@mail.com		# 配置全局的邮箱
使用
在当前目录上创建 Git 仓库,
git init		# 工作目录中出现 .git 子目录
将工作区的修改添加到暂存区,
git add a.txt	# 追踪 a.txt 文件
git add .		# 追踪整个工作目录
将暂存区提交到 Git 仓库,
git commit -m "该提交的说明" 	# 会显示在 git log 日志里
git commit						# 自动打开注解文件,可写入一些注解
查看当前分支的状态(工作区的文件是否被追踪、文件内容是否有修改、暂存区是否尚未提交),
git status
拷贝现有的 Git 仓库,
git clone https://github.com/malb/lattice-estimator.git ./myrepo
递归更新 Git 仓库的子模块,
git submodule update --init --recursive
其他命令
日志
查看日志信息(哈希值、提交者、提交时间、提交信息),
git log
git log --oneline	# 简洁版本
git log --graph		# 分支、合并的拓扑图
该指令还包含多种参数,比如 --auther=<作者>, --since=<起始时间>, --until=<结束时间>,等等。
查看某个文件的修改历史(逐行显示:哈希值、作者、时间、内容),
git blame a.txt
git blame -L 1,3 a.txt			# 只显示第 1-3 行的内容
git blame --show-stats a.txt	# 额外显示该文件 blob, commits 对象的数量
分支
查看所有的分支,
git branch
创建新的分支,同时切换到该分支上,
git checkout -b kem		# 此时 master 和 kem 依然重合,执行 add 和 commit 之后将分离
如果想要切换回 master 分支,可以执行:
git checkout master
此时,工作区会被修改为 master 分支的最新快照。
合并分支(假设有 kem 和 pqc 两个分支,当前指向 kem),
git merge pqc		# 将 pqc 分支合并到 kem 分支上,其中 pqc 不变,而 kem 变化
如果出现冲突,这些文件中的冲突内容会被标记,需要手动解决,然后再 add 和 commit。冲突标记的含义是:
- <<<<<<<<:冲突区域的起始标记,接下来的内容是当前分支(比如- kem)的文件内容;
- ========:冲突区域的分隔标记,接下来的内容是合并分支(比如- pqc)的文件内容;
- >>>>>>>>:冲突区域的结束标记,接下来是两个分支的非冲突部分。
删除本地的分支(要求不是当前分支),
git branch -d pqc	# 删除 pqc 分支
回退
查看 HEAD 的变更日志(显示前  7 7 7 位哈希值),可以找回丢失的提交,
git reflog
git reflog show master
将分支回退到特定的提交,
git reset --soft b36f484		# 仅将 HEAD 回退到 b36f484 版本
git reset --mixed b36f484		# 也把 index 回退到 b36f484 版本(默认)
git reset --hard b36f484		# 把工作区也回退到 b36f484 版本(危险动作,未提交的修改内容将丢失)
将工作区回退到特定的提交,
git checkout b36f484			# 将整个工作区回退到 b36f484 版本
git checkout d748164 -- a.txt 	# 仅把 a.txt 回退到 d748164 版本
git checkout master				# 切换回 master 版本
如果切换的提交不是该分支的最新版本(真的回退,而非切换),将会进入 detached HEAD 状态(即 HEAD 指向了具体的提交,而非某个分支)。此时查看 git branch,会发现多了一个临时的分支。如果工作区做了修改,在该状态下的所有提交,将不被任何一个分支引用;因此,需要创建新的分支,以保存这些修改。
标签
为当前分支的最新版本打标签,
git tag v1.0.0						# 不带附注
git tag -a v1.0.1 -m "注解信息"		# 携带附注,包括:作者、时间
查看标签,
git tag				# 显示所有标签
git show v1.0.0		# 查看该标签的信息
忽略指定文件
在工作目录中,新建文件 .gitignore(就叫这个名字),内容设置为:
bin			# 排除 bin 目录
build		# 排除 build 目录
doc/*.png	# 排除 doc 目录下的所有 png 文件
log.txt		# 排除 log.txt 文件
此时执行 git status,打印内容中不再包含上述被排除的路径。执行 git add . 命令时,就忽略了这些文件的修改。
远程仓库
为了协作,可以使用 github.com 作为远程仓库的服务器,需要配置账户和 SSH 密钥。比较繁琐,这部分内容以后有时间再补充。
