-
Notifications
You must be signed in to change notification settings - Fork 14
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat(ch5): translate 589-973 #54
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -0,0 +1,340 @@ | ||||||||||||||
[590] | ||||||||||||||
目前为止有什么问题吗 | ||||||||||||||
这就是 git 大致的储存模型了 | ||||||||||||||
然后我们就要开始 | ||||||||||||||
实际地使用 git 命令 | ||||||||||||||
来理解 git 的命令 | ||||||||||||||
和这个图结构变换的关系 | ||||||||||||||
所以对于把历史 | ||||||||||||||
建模成 blob 构成的树 | ||||||||||||||
外面套一层 commit 树 # REVIEW ... | ||||||||||||||
而 commit 则是 blob 树的一个快照 | ||||||||||||||
而 blob 树则会 | ||||||||||||||
随着不同 commit 整体改变 | ||||||||||||||
然后引用则会指向图上的某一节点 | ||||||||||||||
没问题吗 好强啊 | ||||||||||||||
我们有了对象和引用以后 | ||||||||||||||
这就可以构成一整个 git 仓库了 | ||||||||||||||
这就是仓库里实际存的东西 | ||||||||||||||
从高层次(用户层)来说 | ||||||||||||||
所有的 git 命令 | ||||||||||||||
就只是在改变对象或者引用数据而已 | ||||||||||||||
现在我们来讲一些 git 命令 | ||||||||||||||
我们会和 Vim 那堂课那样交互式地演示 | ||||||||||||||
然后可以参考课堂笔记来了解细节 | ||||||||||||||
因为这个工具实在非常强大 | ||||||||||||||
我们不可能二十分钟讲完 | ||||||||||||||
*那就讲一个小时 | ||||||||||||||
然后我们进到一个叫做 `playground` 的目录 | ||||||||||||||
开个新文件夹叫做 `demo` 然后切进去 | ||||||||||||||
我们假设这是项目的根目录 | ||||||||||||||
现在是空的 毕竟我刚刚开这文件夹 | ||||||||||||||
我现在用 `git init` 命令 | ||||||||||||||
来把它初始化成一个 git 仓库 | ||||||||||||||
init = initialize = 初始化 | ||||||||||||||
然后它告诉我它在这个目录 | ||||||||||||||
下面的 `.git` 文件夹里 | ||||||||||||||
初始化了空 git 仓库 | ||||||||||||||
[629] | ||||||||||||||
如果只是跑 `ls` | ||||||||||||||
还是啥都没有 | ||||||||||||||
但是我跑 `ls -a` | ||||||||||||||
就会有个隐藏的文件夹 `.git` | ||||||||||||||
* `.` 开头的文件默认隐藏 文件夹是特殊的文件 | ||||||||||||||
而我跑 `ls .git` | ||||||||||||||
会看到一堆的文件 | ||||||||||||||
这就是本地磁盘上 git 储存数据的地方 | ||||||||||||||
也就是那些对象和引用 | ||||||||||||||
然后你在这里也可以看到 | ||||||||||||||
对象(`objs`)和引用(`refs`)两个文件夹 | ||||||||||||||
仓库的数据就存在里面 | ||||||||||||||
而另外一个学习时值得注意的命令 | ||||||||||||||
则是 `git help` | ||||||||||||||
然后你要加一个子命令名作为参数 | ||||||||||||||
来指定要看啥的帮助 | ||||||||||||||
我现在跑 `git help init` | ||||||||||||||
它就会告诉我 `git init` 的帮助信息 | ||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||||||
然后有些命令可以用来 | ||||||||||||||
了解 git 仓库的状态 | ||||||||||||||
例如 `git status` | ||||||||||||||
可以了解用户层的仓库状态 | ||||||||||||||
先不看第一行 | ||||||||||||||
第二行说我们现在还没有 commit | ||||||||||||||
因为我们刚开一个新的 git 仓库 | ||||||||||||||
自然也就没有历史 | ||||||||||||||
还有人要看吗 我要擦掉了 | ||||||||||||||
我想要一路打命令 | ||||||||||||||
一路展示引用和对象数据的变化 | ||||||||||||||
现在这个美妙的空图像 | ||||||||||||||
展现了我们~~整洁~~的空仓库 | ||||||||||||||
所以来往历史里加点东西 | ||||||||||||||
[665] | ||||||||||||||
让我开一个新的文件 | ||||||||||||||
里面只有 `hello world` | ||||||||||||||
通常来说这会是你的源代码啥的 | ||||||||||||||
现在 我想要把目录里的内容 | ||||||||||||||
变成新的快照 | ||||||||||||||
代表我仓库的第一个状态 | ||||||||||||||
你可能会猜 | ||||||||||||||
是不是有个 `git snapshot` 啥的 | ||||||||||||||
来给整个目录来个快照 | ||||||||||||||
因为某些原因 | ||||||||||||||
以及为了让操作更灵活 | ||||||||||||||
让你选择下一个快照里包含什么 | ||||||||||||||
git 并没有完全一致的功能 | ||||||||||||||
初学者经常在这里满头问号 | ||||||||||||||
所以我现在先把这个说了 | ||||||||||||||
git 里有一个概念叫做 staging 区 | ||||||||||||||
在用户层面上 | ||||||||||||||
你通过这个方式告诉 git | ||||||||||||||
你想要把哪些修改包含在下一个快照里 | ||||||||||||||
现在再跑一次 `git status` | ||||||||||||||
它会说现在没有 commit | ||||||||||||||
然后 `hello.txt` 没有被纳入版本管理 | ||||||||||||||
意思就是说 | ||||||||||||||
git 知道这里有个文件 | ||||||||||||||
但是就是不会加进下一个快照 | ||||||||||||||
现在 git 会暂时忽略它 | ||||||||||||||
然后我现在跑 `git add hello.txt` | ||||||||||||||
然后再跑 `git status` | ||||||||||||||
它就会说这些修改将被 commit: | ||||||||||||||
新文件 `hello.txt` | ||||||||||||||
然后我现在跑 git 的快照命令 | ||||||||||||||
实际上是 `git commit` | ||||||||||||||
就会在黑板上创造一个新的圈(节点) | ||||||||||||||
* 要在整个 commit 完成之后 | ||||||||||||||
* 例如要求 commit message 非空否则默认 abort | ||||||||||||||
这个文本文件会被包含在那个快照里 | ||||||||||||||
然后我现在跑这个命令 | ||||||||||||||
[708] | ||||||||||||||
它会弹出一个文本编辑器 | ||||||||||||||
让我输入这个 commit 的 message | ||||||||||||||
写一手好 commit message 非常重要 | ||||||||||||||
以后你(或者别人)往回看版本历史的时候 | ||||||||||||||
能够很方便地知道这样改变的原因 | ||||||||||||||
我这里就随便写点 | ||||||||||||||
但是课堂笔记里有个链接 | ||||||||||||||
来指导你写高质量的 commit message | ||||||||||||||
然后 git 给我打出了一些信息 | ||||||||||||||
master 先不管 | ||||||||||||||
这个 是 commit 的 hash | ||||||||||||||
现在我的历史上有了一个节点 | ||||||||||||||
节点里面是一个 | ||||||||||||||
只有一个文件节点的 blob 树 | ||||||||||||||
这个文件节点的文件名叫做 `hello.txt` | ||||||||||||||
里面写有 `hello world` # REVIEW 树套树套.. | ||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Git 其实是 DAG 套树 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 但是他这里说树( There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 做不到吧,你考虑 merge 的情况,一定可能存在有一个节点有两个父亲的情况,这必不可能是个树 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||||||
它的短 hash 是 `42fb7a2...` | ||||||||||||||
git 把它截断了 | ||||||||||||||
然后是我的 commit message | ||||||||||||||
接下来是再次提醒我加了个新文件 `hello.txt` | ||||||||||||||
现在我跑 `git log` 命令 | ||||||||||||||
这个命令能够帮助你可视化历史 | ||||||||||||||
非常有用 | ||||||||||||||
有问题吗 | ||||||||||||||
学生:这个 `42fb7a2` 是代表一整个树 | ||||||||||||||
还是 `hello` 这个功能 | ||||||||||||||
#REVIEW 也没说啥树= = | ||||||||||||||
好问题 也就是说这个 hash 到底代表什么 | ||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||||||
这是 commit 的 hash | ||||||||||||||
commit 里面有 blob 树的 hash | ||||||||||||||
以及(commit message,commit 时间等)其他信息 | ||||||||||||||
实际上 我可以用 `git cat-file -p 42fb7a2` | ||||||||||||||
这是 git 内部实现用的命令 | ||||||||||||||
会把 commit 的内容打出来 | ||||||||||||||
你会注意到它和黑板上的结构一致 | ||||||||||||||
它的 blob tree 的 hash 是这个 | ||||||||||||||
作者是这个 | ||||||||||||||
commit message 是这个 | ||||||||||||||
然后我可以继续深入 | ||||||||||||||
`cat-file -p` 这个 hash | ||||||||||||||
你可以看到树里只有一个文件 | ||||||||||||||
这个 blob 的 hash 是这个 | ||||||||||||||
[758] | ||||||||||||||
再套一层娃 | ||||||||||||||
它就会给我显示文件的实际内容了 | ||||||||||||||
所以这就是用来展示 | ||||||||||||||
git 对象数据的内部命令 | ||||||||||||||
那边还有提问? | ||||||||||||||
学生:你为啥要手动指定要加的文件 | ||||||||||||||
学生:而不是直接把所有修改 commit 了 | ||||||||||||||
问得好 | ||||||||||||||
这个同学问 为啥不直接 commit 所有改变 | ||||||||||||||
而是要来个 `git add` | ||||||||||||||
实际上 我们可以一次 commit 所有改变 | ||||||||||||||
如果你跑 `git commit -a` | ||||||||||||||
就会对所有纳入版本管理的文件的改变 | ||||||||||||||
进行 commit | ||||||||||||||
也就是在前一个快照里有 | ||||||||||||||
而且之后被修改过的文件 | ||||||||||||||
但是不包括新文件 | ||||||||||||||
也有 `git add` 的变体 | ||||||||||||||
`git add :/` 会从项目根目录递归 stage 所有文件 | ||||||||||||||
#REVIEW 没有任何问题 只是给你看看可爱的 :/ | ||||||||||||||
在高层次来说 | ||||||||||||||
把 `git add` 和 `git commit` 分开 | ||||||||||||||
`git commit` 不对整个目录进行快照 | ||||||||||||||
这样设计的原因是 | ||||||||||||||
你通常来说并不想把所有东西加入快照 #REVIEW svn 哈哈 | ||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 别啊,SVN 也是可以设置 ignore 的,只是没 Git 灵活 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ignore 和 stage 还是有区别? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 是,所以说没 git 灵活(Git 可以随时随地随意调整,SVN 必须写死在文件里) |
||||||||||||||
举几个例子 | ||||||||||||||
[785] | ||||||||||||||
一个是我在勤奋工作 #REVIEW packing | ||||||||||||||
我写了两个新功能 | ||||||||||||||
我并不是很想把新功能 A 和 B | ||||||||||||||
打到一个快照里 | ||||||||||||||
说我实现了 A 和 B | ||||||||||||||
我更想分成两个快照 | ||||||||||||||
先是实现 A | ||||||||||||||
然后是实现 B | ||||||||||||||
然后第一个快照有 A 功能 | ||||||||||||||
第二个有 A 和 B 功能 | ||||||||||||||
有了 `git add` 和 staging 区 | ||||||||||||||
才能够使我这样做 | ||||||||||||||
另外一个是 | ||||||||||||||
假设我在修 bug | ||||||||||||||
然后我输出调试代码里满地都是 | ||||||||||||||
然后我终于找到了是多加了 1 | ||||||||||||||
然后我把它修了以后想来个新快照 | ||||||||||||||
但是那些快照最好不要有输出调试 | ||||||||||||||
而只是去掉那个 +1 | ||||||||||||||
我可以手动删掉所有调试输出 | ||||||||||||||
而 git 就很香 | ||||||||||||||
它可以让我选择 add 哪一块修改 | ||||||||||||||
例如只 add 删掉这个 -1 这行 | ||||||||||||||
然后就可以 commit 来个新快照 | ||||||||||||||
之后就可以把输出调试全部丢掉了 | ||||||||||||||
这是 staging 区的两种用法 | ||||||||||||||
也因此没有直接快照所有修改的命令 | ||||||||||||||
学生:还有一个例子 你目录下面有个日志文件 | ||||||||||||||
Jon 说到了 | ||||||||||||||
你目录下面有个你程序打出来的日志文件 | ||||||||||||||
你快照的时候把这个加入快照没意思啊 | ||||||||||||||
以及其他的一些 例如编译时的 `.o` 和可执行文件啥的 | ||||||||||||||
这些东西你也不应该加进版本历史里 | ||||||||||||||
[836] | ||||||||||||||
接着前面讲 | ||||||||||||||
我清个屏 | ||||||||||||||
然后展示一下 `git log` 命令 | ||||||||||||||
这个命令可以用来把版本历史可视化 | ||||||||||||||
十分有用 | ||||||||||||||
默认情况下 | ||||||||||||||
`git log` 会展示扁平化的版本历史 | ||||||||||||||
即便版本历史是一个图 | ||||||||||||||
它还是会以线性的形式展示 | ||||||||||||||
我觉得这样十分令人头大 | ||||||||||||||
所以我基本上不单独用 `git log` | ||||||||||||||
我可以给它加一些参数 | ||||||||||||||
使得 `git log` 以图的形式展现 | ||||||||||||||
你可以把它当作咒语先记着 | ||||||||||||||
如果你真的想深入了解这些选项 | ||||||||||||||
可以去查阅文档 | ||||||||||||||
现在来看没什么区别 | ||||||||||||||
因为我们图上只有一个节点 | ||||||||||||||
所以图形式和扁平的形式并没有多大区别 | ||||||||||||||
我现在创建一个新快照 | ||||||||||||||
然后再回来跑这个命令 | ||||||||||||||
看看会发生什么 | ||||||||||||||
我现在在 `hello.txt` 尾部加一行 | ||||||||||||||
所以现在 `cat hello.txt` | ||||||||||||||
会有之前的内容和新加的内容 | ||||||||||||||
然后跑 `git commit` | ||||||||||||||
这样并不会有什么用 | ||||||||||||||
会告诉你没有要 commit 的东西 | ||||||||||||||
为什么呢 | ||||||||||||||
因为我没把要加入下一个快照的改变 | ||||||||||||||
加到 staging 区里 | ||||||||||||||
git 也就不知道要快照什么了 | ||||||||||||||
那我现在 `git add hello.txt` | ||||||||||||||
`git status` 就会说这个改变将要被 commit | ||||||||||||||
这个文件修改 | ||||||||||||||
然后就可以 `git commit` | ||||||||||||||
随便打个 commit message | ||||||||||||||
然后就打了个新快照 | ||||||||||||||
现在我的历史上就有了新节点 | ||||||||||||||
它的 hash 是 `62da510` | ||||||||||||||
然后我现在再跑之前那个 | ||||||||||||||
带有好几个参数的 `git log` | ||||||||||||||
它现在就更像个图了 | ||||||||||||||
[884] | ||||||||||||||
注意这里其实是把黑板上的图转了一下 | ||||||||||||||
竖着画而不是横着画 | ||||||||||||||
越新的 commit 在越上面 | ||||||||||||||
这是一个 commit 和它的 hash | ||||||||||||||
然后下面有 commit message 和一些信息 | ||||||||||||||
这是我接下来要说的东西 | ||||||||||||||
我们现在一直在谈对象 #REVIEW 草( | ||||||||||||||
也就是我们仓库里实际的内容 | ||||||||||||||
接下来我们来聊聊 | ||||||||||||||
用来给仓库里内容命名成人类能理解的东西 | ||||||||||||||
称为引用 | ||||||||||||||
`master` 是你初始化仓库的时候 | ||||||||||||||
默认创建的引用 | ||||||||||||||
它一般用来指代你代码仓库的主开发分支 | ||||||||||||||
也就是最新最热的分支 | ||||||||||||||
你可以把 `master` 当作指向这个 commit 的指针 | ||||||||||||||
然后在加新 commit 的时候 | ||||||||||||||
这个指针就会被改变 指向新 commit | ||||||||||||||
然后是这个 `HEAD` | ||||||||||||||
这是 git 里一个特殊的引用 | ||||||||||||||
[909] | ||||||||||||||
它和 `master` 同样是引用 但是有点特殊 #REVIEW | ||||||||||||||
`HEAD` 通常用来指代你现在所在的版本 | ||||||||||||||
有问题吗 | ||||||||||||||
那边有人要提问 | ||||||||||||||
学生:我用 GitHub 要开个账号来做在线开发 | ||||||||||||||
学生:git 和 GitHub 有什么关系 | ||||||||||||||
学生:它们是同一个东西还是有什么神秘交易 | ||||||||||||||
#REVIEW p__ 和 p___hub 什么关系 | ||||||||||||||
问得好 | ||||||||||||||
这位同学问 | ||||||||||||||
用 GitHub 要注册一个账号 | ||||||||||||||
所以 GitHub 和 git 有什么关系 | ||||||||||||||
答案是 | ||||||||||||||
GitHub 托管 git 仓库 | ||||||||||||||
所以你可以在上面开个账号储存 git 仓库 | ||||||||||||||
然后用它和其他人协作 | ||||||||||||||
git 这个命令行工具和 GitHub 是独立的 | ||||||||||||||
你并不需要 GitHub 才能用 git | ||||||||||||||
甚至不一定要用 GitHub 协作 | ||||||||||||||
还有其他的 git 仓库托管服务提供商 | ||||||||||||||
例如 BitBucket 和 GitLab 等 | ||||||||||||||
总之 GitHub 托管 git 仓库 | ||||||||||||||
还有问题吗 | ||||||||||||||
学生:所以我们现在用 git | ||||||||||||||
学生:整出了图上的两个 commit | ||||||||||||||
学生:如果我想在想把它放上 GitHub | ||||||||||||||
学生:是不是有登录啥的命令 | ||||||||||||||
所以提问是你要怎么把仓库传上 GitHub | ||||||||||||||
是的 有另一套命令来完成这些工作 | ||||||||||||||
[934] | ||||||||||||||
你可以让你本地的版本历史副本(仓库) | ||||||||||||||
和远程的副本交互 | ||||||||||||||
这是另一套 `git remote` 命令 | ||||||||||||||
把你的副本数据传输到远程 | ||||||||||||||
或者从远程把数据获取到你的本地副本 | ||||||||||||||
我们晚点会讲到这个 | ||||||||||||||
或者在课程笔记或者补充视频里 | ||||||||||||||
还有问题吗 | ||||||||||||||
好 还有几个基本命令要展示一下 | ||||||||||||||
所以目前为止 | ||||||||||||||
我新建了一个文件并修改了一下 | ||||||||||||||
展示了版本历史 | ||||||||||||||
但是除了读它 | ||||||||||||||
我们并没有真正把它用起来 | ||||||||||||||
而一个实用的命令是 `git checkout` | ||||||||||||||
这是一个扭曲的命令 | ||||||||||||||
你可以用它做好多种事情 | ||||||||||||||
其中一个是在版本历史之间横跳 | ||||||||||||||
我可以给 `git checkout` 一个 commit hash | ||||||||||||||
并不需要输入一整串 只要一个前缀 | ||||||||||||||
[962] | ||||||||||||||
就像我刚刚说的那样 | ||||||||||||||
# REVIEW and it is a smart refresh of what i am talking about | ||||||||||||||
它会把我的工作目录的状态 | ||||||||||||||
改变到这个 commit 时的状态 | ||||||||||||||
然后我现在 `cat hello.txt` | ||||||||||||||
就像在第一次 commit 的时候一样 | ||||||||||||||
只有一行 | ||||||||||||||
第二行是后面加的 | ||||||||||||||
然后我现在 `git log` | ||||||||||||||
它真的非常有用 会把所有东西都告诉你 | ||||||||||||||
跑了以后你就会发现和之前有点点微妙的区别 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.