乐趣区

关于linux:计算机教育中缺失的一课-MIT-L6-版本控制-Git

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 的别名是 glog
  • git diff <filename>:显示与上一次提交之间的差别
  • git diff <old-revision> [<new-revision>] <filename>:显示某个文件两个版本之间的差别,new-revision 默认是 HEAD
  • git diff --cached <filename>:不加 cached 标识的 diff 的意思是显示尚未暂存的改变,加了之后是查看已暂存的将要增加到下次提交里的内容

批改、撤销和合并

  • git add -p:交互式暂存,例如交互过程中能够按 s 键进行 split,对文件中各个中央的改变别离抉择暂存与否
  • git checkout -- <file>:抛弃(尚未暂存的)批改
  • git reset [<tree-ish>] <file>:勾销暂存,把文件从暂存区放回工作区,<tree-ish> 默认为 HEAD
  • git 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"
退出移动版