https://missing.csail.mit.edu/
https://missing-semester-cn.g…
https://www.bilibili.com/vide…
笔记
Git 的数据模型
Git 通过一系列快照来治理其历史记录。快照则是被追踪的最顶层的树。能够认为 git commit
会创立一个快照。
type object = blob | tree | commit
// 文件就是一组数据
type blob = array<byte>
// 一个蕴含文件和目录的目录
type tree = map<string, tree | file>
// 每个提交都蕴含一个父辈,元数据和顶层树
type commit = struct {
parent: array<commit>
author: string
message: string
snapshot: tree
}
// 还有援用(reference),比方
// HEAD, master, origin/HEAD, origin/master
// 都是援用
// 援用是指向提交的指针,与对象不同的是,它是可变的(援用能够被更新,指向新的提交)
实际上,Git 在贮存数据时,所有的对象都会基于它们的 SHA-1 hash 进行寻址。Blobs、trees 和 commits 都一样,它们都是对象。当它们援用其余对象时,它们并没有真正的在硬盘上保留这些对象,而是仅仅保留了它们的哈希值作为援用。例如,下面为代码中的 parent: array<commit>
其实际上不是一个 commit 数组,而是一个哈希值数组,这些哈希值指向真正的对象,也就是一些 commits。
objects = map<string, object>
def store(object):
id = sha1(object)
objects[id] = object
def load(id):
return objects[id]
例如,git cat-file -p 698281b
(698281b 是某个 tree,也就是某个文件夹的哈希值的一部分前缀)的后果是:
100644 blob 4448adbf7ecd394f42ae135bbeed9676e894af85 baz.txt
040000 tree c68d233a33c5c06e0340e4c224f0afca87c8ce87 foo
而 git cat-file -p 4448adb
(4448adb 是 baz.txt 的哈希值的一部分前缀)的后果即为 baz.txte 的内容。
Git 的命令行接口
历史 :
git log --all --graph --decorate --oneline
:可视化历史记录(有向无环图),zsh 的 git 插件定义了很多别名,比方该命令的别名是 gloga,去掉 –all 的别名是 gloggit diff <filename>
:显示与上一次提交之间的差别git diff <old-revision> [<new-revision>] <filename>
:显示某个文件两个版本之间的差别,new-revision 默认是 HEADgit diff --cached <filename>
:不加 cached 标识的 diff 的意思是显示尚未暂存的改变,加了之后是查看已暂存的将要增加到下次提交里的内容
批改、撤销和合并 :
git add -p
:交互式暂存,例如交互过程中能够按 s 键进行 split,对文件中各个中央的改变别离抉择暂存与否git checkout -- <file>
:抛弃(尚未暂存的)批改git reset [<tree-ish>] <file>
:勾销暂存,把文件从暂存区放回工作区,<tree-ish> 默认为 HEADgit reset [--soft | --mixed [-N] | --hard | --merge | --keep] [<commit>]
:(见下图)撤销 commit,把 commit 放回暂存区(soft),或放回工作区(mixed),或抛弃(hard),实质是对 HEAD 的挪动git reset [--soft | --mixed [-N] | --hard] HEAD^
,上一条的特例,比拟罕用git rebase <branch>
:在一个过期的分支下面开发的时候,执行rebase
以此同步master
分支最新变动git rebase -i HEAD~n
:交互式变基,可用于批改 commit 信息,合并 commit 等等git mergetool
:应用工具来解决合并抵触git stash
:把工作区暂存起来,容许你切换到其余分支,博主有时候在谬误的分支上进行了批改,会用这个命令把批改暂存起来,而后换到正确的工作分支后应用git stash pop
远端操作 :
git clone --shallow
:克隆仓库,然而不包含版本历史信息git remote add <name> <url>
:增加一个远端git push <remote> <local branch>:<remote branch>
:将对象传送至远端并更新远端援用git branch --set-upstream-to=<remote>/<remote branch>
:创立本地和远端分支的关联关系
其余 :
.gitignore
: 指定 成心不追踪的文件git blame
:查看最初批改某行的人git bisect
:通过二分查找搜寻历史记录git init --bare
:简直用不到,在课程视频中,讲师在某一个空文件夹中应用该命令,将该文件夹作为 remote,而后将一个已有的仓库 push 到该文件夹git config --global core.excludesfile ~/.gitignore_global
:在~/.gitignore_global
中创立全局疏忽规定- Removing sensitive data from a repository
杂项
- 图形用户界面 : Git 的 图形用户界面客户端 有很多,然而咱们本人并不应用这些图形用户界面的客户端,咱们抉择应用命令行接口
- Shell 集成 : 将 Git 状态集成到您的 shell 中会十分不便。(zsh,bash)。Oh My Zsh 这样的框架中个别以及集成了这一性能
- 编辑器集成 : 和下面一条相似,将 Git 集成到编辑器中好处多多。fugitive.vim 是 Vim 中集成 GIt 的罕用插件
- 工作流 : 咱们曾经解说了数据模型与一些根底命令,但还没探讨到进行大型项目时的一些常规 (有很多 不同的 解决办法)
- GitHub: Git 并不等同于 GitHub。在 GitHub 中您须要应用一个被称作拉取申请(pull request)的办法来向其余我的项目奉献代码
- Other Git 提供商 : GitHub 并不是惟一的。还有像 GitLab 和 BitBucket 这样的平台。
资源
- Pro Git, 强烈推荐 !学习前五章的内容能够教会您晦涩应用 Git 的绝大多数技巧,因为您曾经了解了 Git 的数据模型,前面的章节提供了很多乏味的高级主题(Pro Git 中文版)
- 如何编写 良好的提交信息
- Git 是一个 高度可定制的 工具
- Oh Shit, Git!?!,简短的介绍了如何从 Git 谬误中复原;
- Git for Computer Scientists,简短的介绍了 Git 的数据模型
- Git from the Bottom Up 具体的介绍了 Git 的实现细节,而不仅仅局限于数据模型
- How to explain git in simple words
- Learn Git Branching 通过基于浏览器的游戏来学习 Git
课后习题
习题 2
是谁最初批改来 README.md
文件?
$ git log --all -n1 --pretty=format:"%an" README.md
最初一次批改 _config.yml
文件中 collections:
行时的提交信息是什么?
$ git blame _config.yml | grep "collections:" | head -n1 | awk '{print $1}' | sed -E "s/\^//" | xargs git show
# OR
$ git blame _config.yml | grep "collections:" | head -n1 | awk '{print $1}' | sed -E "s/\^//" | xargs git log -n1 --pretty=format:"%s%n%n%b"