Git是版本控制系统(VCSs)的标准。
以下为自底向上介绍Git,从数据模型开始,再到接口,并理解接口是如何操作数据模型的。
快照(Snapshots)
Git通过一系列快照来管理 顶级目录中的文件和文件夹 的历史记录。
文件被称为Blob(数据对象,也就是一组数据)。
目录被称为tree,将名字和Blob对象或树对象进行映射(使得目录中可以包含其他目录)。
快照是被追踪的最顶层的树。
树例:
<root> (tree) | +- foo (tree) | | | + bar.txt (blob, contents = "hello world") | +- baz.txt (blob, contents = "git is wonderful")
这个顶层的树包含了两个元素:一个名为foo的树(它本身包含了一个blob对象bar.txt),以及一个blob对象baz.txt。
关联快照
在Git中,历史记录是一个由快照组成的有向无环图(代表Git中的每个快照都有一系列“父辈(之前的一系列快照)”)。
某个快照可能由多个父辈而来。例如,经过合并后的两条分支。
在Git中,这些快照被称为“提交(commit)”。可视化表示这些历史提交记录可能是这样的:
o <-- o <-- o <-- o ^ \ --- o <-- o
其中的o表示一次提交(快照)。箭头指向了当前提交的父辈。
上面的分岔在开发完成后可能会合并并创建一个新的提交,会同时包含这些特性。
例如(粗体为最新的合并):
o <-- o <-- o <-- o <---- o ^ / \ v --- o <-- o
Git中的提交不可改变,但不代表错误不能被修改(会提交为一个新的提交记录)。而引用(reference)则被更新为指向这些新的提交。
数据模型
(伪代码表示,一种简洁的历史模型)
// 文件就是一组数据 type blob = array<byte> // 一个包含文件和目录的目录 type tree = map<string, tree | blob> // 每个提交都包含一个父辈,元数据和顶层树 type commit = struct { parent: array<commit> author: string message: string snapshot: tree }
对象和内存寻址
Git中的对象可以是blob、树或提交。当它们引用其他对象时,它们并没有真正的在硬盘上保存这些对象,而是仅仅保存了它们的哈希值作为引用。
例如,上面例子中的树可以通过 git cat-file -p 698281bc680d1995c5f4caaf3359721a5a58d48d 来进行可视化。
100644 blob 4448adbf7ecd394f42ae135bbeed9676e894af85 baz.txt 040000 tree c68d233a33c5c06e0340e4c224f0afca87c8ce87 foo
树本身也会包含一些指向其他内容的指针例如 baz.txt
(blob) 和 foo
(树)。如果我们用 git cat-file -p 4448adbf7ecd394f42ae135bbeed9676e894af85
,即通过哈希值查看 baz.txt 的内容,会得到以下信息:
git is wonderful
引用
快照可以用哈希值来标记,但难以记忆。针对这一问题,Git的解决方法是给这些哈希值赋予人类可读的名字,也就是引用(references)。引用是指向提交的指针,可以被更新(指向新的提交)。eg. master引用通常会指向主分支的最新一次提交。
references = map<string, string> def update_reference(name, id): references[name] = id def read_reference(name): return references[name] def load_reference(name_or_id): if name_or_id in references: return load(references[name_or_id]) else: return load(name_or_id)
Git可以使用诸如master这样可读的名称来表示历史记录中某个特定的提交。
标记当前位置(这样可以在创建新的快照的时候知道它的相对位置,设置它的父辈)有一个特殊的索引HEAD。
仓库(repositories)
给出Git仓库的定义:对象(objects)和引用(references)。
在硬盘上,Git仅存储对象和引用:因为其数据模型仅包含这些东西。所有的git命令都对应着对提交树的操作,例如增加对象、增加或删除引用。
暂存区
允许指定下次快照中要包括哪些改动。
Git的命令行接口
基础
git help <command> 获取git命令的帮助信息
git init 创建一个新的git仓库,其数据会存放在一个名为.git的目录下
git status 显示当前的仓库状态
git add <filename> 添加文件到暂存区
git commit 创建一个新的提交
git log 显示历史日志
git log --all --graph --decorate 可视化历史记录(有向无环图)
git diff <filename> 显示与暂存区文件的差异
git diff <revision> <filename> 显示某个文件两个版本之间的差异
git checkout <revision> 更新HEAD和目前的分支
分支和合并
git branch 显示分支
git branch <name> 创建分支
git checkout -b <name> 创建分支并切换到该分支(相当于git branch <name>;git checkout <name>)
git merge <revision> 合并到当前分支
git mergetool 使用工具来处理合并冲突
git rebase 将一系列补丁变基(rebase)为新的基线
远端操作
git remote 列出远端
git remote add <name> <url> 添加一个远端
git push <remote> <local branch>:<remote branch> 将对象传送至远端并更新远端引用
git branch --set-upstream-to=<remote>/<remote branch> 创建本地与远端分支的关联关系
git fetch 从远端获取对象/索引
git pull 相当于git fetch;git merge
git clone 从远端下载仓库
撤销
git commit --amend 编辑提交的内容或信息
git reset HEAD <file> 恢复暂存的文件
git checkout -- <file> 丢弃修改
git restore git2.32版本后取代git reset进行许多撤销操作
Git 高级操作
git config
: Git 是一个 高度可定制的工具
git clone --depth=1
: 浅克隆(shallow clone),不包括完整的版本历史信息
git add -p
: 交互式暂存
git rebase -i
: 交互式变基
git blame
: 查看最后修改某行的人
git stash
: 暂时移除工作目录下的修改内容
git bisect
: 通过二分查找搜索历史记录
.gitignore
: 指定故意不追踪的文件
资源推荐
标签:git,快照,name,Git,blob,提交 From: https://www.cnblogs.com/yhish/p/17844406.html