lzane / LZANE-blog

LZANE’s personal blog, talking about tech and life.
https://www.lzane.com
1 stars 1 forks source link

这才是真正的Git——Git内部原理 - LZANE | 李泽帆(靓仔) #19

Open lzane opened 4 years ago

lzane commented 4 years ago

https://www.lzane.com/tech/git-internal/

TL;DR 本文以一个具体例子结合动图介绍了Git的内部原理,包括Git是什么储存我们的代码和变更历史的、更改一个文件时,Git内部是怎么变化的、Gi

lzane commented 4 years ago

将评论从disqus迁移到gittalk了,所以以前的讨论看不到了。 另外部分讨论在知乎文章https://zhuanlan.zhihu.com/p/96631135 ,如果有需要的话可以阅读。

patrickhe commented 4 years ago

期待博主把内网上已经发的《实用技巧》一节同步过来 :-)

lzane commented 4 years ago

@patrickhe 期待博主把内网上已经发的《实用技巧》一节同步过来 :-)

更新了 https://www.lzane.com/tech/git-tips/ 内网的朋友可以内网交流呀~

zephyrJS commented 3 years ago

请问楼主的 gif 是怎么制作的,有工具推荐吗?谢谢🐶

lzane commented 3 years ago

@zephyrJS 请问楼主的 gif 是怎么制作的,有工具推荐吗?谢谢🐶

用的omnigraffle画的图,然后用Tumult Hype画逐帧动画

zeallean commented 3 years ago

好奇楼主的网页版 slide使用的什么工具生成的。

lzane commented 3 years ago

@zoorz 好奇楼主的网页版 slide使用的什么工具生成的。

reveal.js

zeallean commented 3 years ago

@zoorz 好奇楼主的网页版 slide使用的什么工具生成的。

reveal.js

多谢!

guyuejia commented 3 years ago

你好楼主。关于git checkout和git switch命令,有一些困惑,我理解这两个命令是切换分支,就是说切换head指针指向哪一个commit,可为什么切换分支后,工作区的内容也会变呢?

另外如果工作区或者暂存区有未commit的内容,切换分支后,有的时候暂存区的内容会丢失,有的时候不会丢失。这原理是什么呢?还请楼主不吝赐教,多谢!

lzane commented 3 years ago

@guyuejia 你好楼主。关于git checkout和git switch命令,有一些困惑,我理解这两个命令是切换分支,就是说切换head指针指向哪一个commit,可为什么切换分支后,工作区的内容也会变呢?

另外如果工作区或者暂存区有未commit的内容,切换分支后,有的时候暂存区的内容会丢失,有的时候不会丢失。这原理是什么呢?还请楼主不吝赐教,多谢!

git switchgit restore是用来解决git checkout现在同一api却有完全不同的功能

git checkout 的设计就是head指针指向新的commit,并更新工作区和index

理论上不会出现丢失,除非你使用-f,你可以再具体描述下出现的情况

感兴趣的话可以看下git switch的源码 https://github.com/git/git/blob/84d06cdc06389ae7c462434cb7b1db0980f63860/builtin/checkout.c#L1810 其实底层调用的跟git checkout是一样的代码

guyuejia commented 3 years ago

感谢回复,我实验了如下三种场景: 假设2个分支:master和dev A:两个分支都有文件a,master修改文件a后,不做add,直接切换到dev,可以切换。工作区或者暂存区的内容保留。 B:分支master有文件b,dev没有该文本。master修改文件b后,不管做不做add,都无法直接切换到dev分支。 可以选择强制切换,但切换后工作区或者暂存区的内容不保留,也就是对文件b的内容修改将丢失。 C:分支master新创建一个文件,不管做不做add,都可以直接切换到dev分支,并且保留工作区或者暂存区的内容,也就是文件c将会保留。

hushishuai.fly

lzane commented 3 years ago

感谢回复,我实验了如下三种场景: 假设2个分支:master和dev A:两个分支都有文件a,master修改文件a后,不做add,直接切换到dev,可以切换。工作区或者暂存区的内容保留。 B:分支master有文件b,dev没有该文本。master修改文件b后,不管做不做add,都无法直接切换到dev分支。 可以选择强制切换,但切换后工作区或者暂存区的内容不保留,也就是对文件b的内容修改将丢失。 C:分支master新创建一个文件,不管做不做add,都可以直接切换到dev分支,并且保留工作区或者暂存区的内容,也就是文件c将会保留。

@guyuejia 是的,符合预期的。主要看当前的修改是否能够在新的分支上“回放”,我分情况举下例子

A: 在master【从文件a修改成文件a'】,切换到dev时,dev也是文件a,所以可以将前面【】的操作在新分支上回放 B: 在master【从文件b修改成文件b'】,切换到dev时,dev没有文件b,所以不能回放 C: 在master【从没有文件创建文件c】,在切换到dev时,dev也是没有文件,所以可以回放

不知道这样够不够通俗易懂,本质上就是先把index和工作区变成checkout到的新分支的样子,然后再看看能否无冲突保留未提交的信息

guyuejia commented 3 years ago

场景A中: master-a文件修改成了master-a,切换dev后,应该是dev分支的文件覆盖现在工作区和暂存区,那工作区内容理论上应该是由master-a变为dev-a,但实际上还是master-a`。这是我最不理解的地方。

lzane commented 3 years ago

场景A中: master-a文件修改成了master-a,切换dev后,应该是dev分支的文件覆盖现在工作区和暂存区,那工作区内容理论上应该是由master-a变为dev-a,但实际上还是master-a`。这是我最不理解的地方。

@guyuejia 你的理解是对的,但少了一步

  1. 初始条件 master a->a' dev a
  2. 执行checkout,“dev分支的文件覆盖现在工作区和暂存区”,所以会变成 a
  3. 未提交内容a->a'可在1的结果中无冲突apply,所以结果是 a'
guyuejia commented 3 years ago

非常感谢您的解释,我大概理解了,这简单一个命令背后,git背后做了很多工作啊。

guyuejia commented 3 years ago

再次打扰楼主下,有没有哪个命令能看到index文件的内容呢?另外有命令能直接查看当前版本库中某个文件的实际内容(不用diff命令确认内容),多谢!

lzane commented 3 years ago

再次打扰楼主下,有没有哪个命令能看到index文件的内容呢?另外有命令能直接查看当前版本库中某个文件的实际内容(不用diff命令确认内容),多谢!

@guyuejia 有的,git show :a.txtgit show HEAD:a.txt