Git 幼儿园入门
"这只是一个 Git 新手基础入门(幼儿园级别)"
Git
Mind map:
VCS(版本管理系统)发展
- 服务器文档式(VCS出现之前)
- 集中式VCS
- 分布式VCS (Git [Linux支付创造] )
Git 的特点
- 最优的储存能力
- 非凡的性能
- 开源
- 很容易做备份
- 支持离线操作
- 很容易定制工作流程
DevOps 工具[全流程生命周期]
DevOps:持续交付实践
- Git
- GitHub
- GitLab [社区版本]
安装Git
- https://git-scm.com/download/mac
- https://git-scm.com/book/zh/v2 [书]
配置USER
- 配置 user.name 和 user.email
$ git config --global user.name 'your_name'
$ git config --global user.email 'your_email@domain.com'
Why git need these?
代码的每一次变更时,时间点与变更人 都是与变更信息捆绑在一起的。在Code Review时,每一次变更信息都带上了用户的Email地址,评审人员指出该用户的哪个文件有问题时,Git管控的Web系统会取出变更者的Email并发送邮件。必须配置!!
--global有什么用呢? 是什么意思呢?
config的三个作用域
config 可以配置许多仓库属性
$ git config --local
$ git config --global
$ git config --system
- --local : 只对某个仓库有效 [登录到某一个仓库 再设置该仓库]
- --global: 对当前用户的所有仓库有效 [如登录Mac系统的用户Wu的所有10个仓库,因此变更人信息设置常用global]
- --system: 对系统的所有登录用户有效 [不常用]
显示config的配置,加list
$ git config --list --local
fatal: --local can only be used inside a git repository
$ git config --list --global
filter.lfs.clean=git-lfs clean -- %f
filter.lfs.smudge=git-lfs smudge -- %f
filter.lfs.process=git-lfs filter-process
filter.lfs.required=true
user.email=wzhenglong@yahoo.com
user.name=zhenglong
$ git config --list --system
fatal: unable to read config file '/etc/gitconfig': No such file or directory
注意:--global 和 --list的位置可以对调,无影响。
建立Git仓库
两种场景:
-
把已有项目代码纳入Git管理
$ cd 项目代码所在的文件夹 $ git init
-
新建的项目直接用Git管理
$ cd 某个文件夹 $ git init your_project #在当前路劲下创建和项目名称同名的文件夹 # 该文件夹内会建立一个裸仓库,以.git后缀 $ cd your_project
-
演示
$ git init git_learning Initialized empty Git repository in /Users/zhenglongwu/Desktop/Programming/Git/git_learning/.git/ $ cd git_learning $ ls -al total 0 drwxr-xr-x 3 zhenglongwu staff 96 Sep 12 16:02 . drwxr-xr-x 3 zhenglongwu staff 96 Sep 12 16:02 .. drwxr-xr-x 9 zhenglongwu staff 288 Sep 12 16:02 .git $ cd .git $ ls -al total 24 drwxr-xr-x 9 zhenglongwu staff 288 Sep 12 16:02 . drwxr-xr-x 3 zhenglongwu staff 96 Sep 12 16:02 .. -rw-r--r-- 1 zhenglongwu staff 23 Sep 12 16:02 HEAD -rw-r--r-- 1 zhenglongwu staff 137 Sep 12 16:02 config -rw-r--r-- 1 zhenglongwu staff 73 Sep 12 16:02 description drwxr-xr-x 13 zhenglongwu staff 416 Sep 12 16:02 hooks drwxr-xr-x 3 zhenglongwu staff 96 Sep 12 16:02 info drwxr-xr-x 4 zhenglongwu staff 128 Sep 12 16:02 objects drwxr-xr-x 4 zhenglongwu staff 128 Sep 12 16:02 refs
比较局部配置与全局配置
$ git config --list --global user.email=wzhenglong@yahoo.com user.name=zhenglong # 局部配置 $ git config --local user.name 'user1' $ git config --local user.email '670362192@qq.com' $ git config --local --list user.name=user1 user.email=670362192@qq.com #
基本Git操作
# cp cp [-R [-H | -L | -P]] [-fi | -n] [-apvXc] source_file ... target_directory
# cp [-R [-H | -L | -P]] [-fi | -n] [-apvXc] source_file target_file
$ cp ../readme.txt .
$ git commit -m'Add readme'
On branch master
Initial commit
Untracked files:
readme.txt
nothing added to commit but untracked files present
## git commit报错 因为没有跟踪该文件。我们需要先跟踪该文件
$ git add readme.txt
$ git status
On branch master
No commits yet
Changes to be committed:
(use "git rm --cached <file>..." to unstage)
new file: readme.txt
$ git commit -m'Add readme'
[master (root-commit) 61841ea] Add readme
1 file changed, 0 insertions(+), 0 deletions(-)
create mode 100644 readme.txt
$ git log
commit 61841eab81f0c26cfb9a884f4617169c0741c1fd (HEAD -> master)
Author: user1 <670362192@qq.com>
Date: Thu Sep 12 19:14:42 2019 -0400
Add readme
git add filename ==> 表示文件添加到Git的暂存区中,Git已经可以开始管理这个文件了(在stage的状态)。同理,
(use "git rm --cached
git commit
git log ==> 打印git的日志,看commit是否被创建出来了(包括完成提交的作者,邮箱[都是local配置优先] 和时间)
Git的暂存区概念
暂存区应用场景举例: 代码写好后先存入暂存区内,此时有一种重构的想法并在工作目录源代码上重构,若重构失败,可从暂存区中再调回之前的版本。[暂存
:暂时存放,不是正式提交。可以让我们实验代码的多种可能性,修正到最佳后再提交]
- 暂存:git add files
- 正式提交:git commit
$ cp ../css3-windy-switch/index.html index.html
$ git status
On branch master
Untracked files:
(use "git add <file>..." to include in what will be committed)
index.html
nothing added to commit but untracked files present (use "git add" to track)
$ cp -r ../css3-windy-switch/css .
$ cp -r ../css3-windy-switch/css javascript
$ rm -r javascript
$ cp -r ../css3-windy-switch/js javascript
$ git status
On branch master
Untracked files:
(use "git add <file>..." to include in what will be committed)
css/
index.html
javascript/
git status 是最常用的一个命令,我们常常都需要去运行看看当前目录的情况,上例子中出现了untracked files: index.html,是刚复制粘贴到文件夹(Git的当前仓库)。若要将这个index.html 纳入Git管理,先要git add
注意:
- git add 可以添加多个文件(包括文件夹) 中间用空格隔开
- git add 要写文件名或者文件夹名
- git commit 只要写正式提交的备注,方便后期读懂提交仓库改动的意义
- git add -u : 在git仓库中所有被Git管理了的新修改文件(tracked)一起再提交到暂存区中
Git 文件重命名
# Method1: 手动重命名方法
$ mv readme.txt readme.md
$ git status
$ git add readme.md
$ git rm readme.txt
$ git status
# Method2: 用Git的快速重命名命令(更高效)
$ git mv readme.txt readme.md
$ git status
# 正式提交
$ git commit -m'Move readme.txt to readme.md'
$ git log
Git log查看版本演变历史
# 便捷查看(将省略提交人信息)
$ git log --oneline
# 只看最近的4次或最近的2次
$ git log -n4 --oneline
$ git log -n2 --oneline
# 查看当前的分支
$ git branch -v
# 创建一个分支叫temp,后面的数字是随意复制某一个commit的地址,在这个分支中,包含了包括所复制commit的所有之前的commit情况。
$ git checkout -b temp d4e1729be
# 其中head变成了temp分支。
$ git log --oneline
f9192c6 (HEAD -> temp) Add test
d4e1729 Add javasrcipt
7c13cfe Add index and css
61841ea Add readme
# 查看master的分支
$ git log master --oneline
# --all 查看所有分支的演变信息(父子关系)
$ git log --all --oneline
# --graph 图形化查看版本演变信息,从哪一步的代码更新开始产生分支?
$ git log --all --oneline --graph
Author & Committer
- Author 代表作者
- Committer 代表提交人
一般情况作者就是提交人。但是当某人非常喜欢项目中master分支的一个commit,他想基于这个commit创建一个temp分支研究,此时为了尊重版权。此时在temp分支中当前Author就是原作者,Commiitter就是研究人。
# 利用gltk图形化界面查看git版本历史
$ gitk
# 可以查看每一个commit的:
# 1. Author
# 2. Committer
# 3. Parent : 最早的commit没有parent
# 4. Child : 最后的commit没有child
# 5. Branches : 拥有这条commit的所有分支
# 6. Follows
# 7. Precedes
# 设置View: view ==> New view ==> All refs
# ==> Ok后可以查看所有分支版本演进历史
探究 .git 目录
$ cd .git
$ ls -al
total 56
drwxr-xr-x 14 zhenglongwu staff 448 Sep 14 20:57 .
drwxr-xr-x 9 zhenglongwu staff 288 Sep 12 21:29 ..
-rw-r--r-- 1 zhenglongwu staff 9 Sep 12 21:09 COMMIT_EDITMSG
-rw-r--r-- 1 zhenglongwu staff 21 Sep 12 21:06 HEAD
-rw-r--r-- 1 zhenglongwu staff 41 Sep 12 20:49 ORIG_HEAD
-rw-r--r-- 1 zhenglongwu staff 184 Sep 12 16:10 config
-rw-r--r-- 1 zhenglongwu staff 73 Sep 12 16:02 description
-rw-r--r-- 1 zhenglongwu staff 461 Sep 14 20:57 gitk.cache
drwxr-xr-x 13 zhenglongwu staff 416 Sep 12 16:02 hooks
-rw-r--r-- 1 zhenglongwu staff 792 Sep 12 21:09 index
drwxr-xr-x 3 zhenglongwu staff 96 Sep 12 16:02 info
drwxr-xr-x 4 zhenglongwu staff 128 Sep 12 19:14 logs
drwxr-xr-x 28 zhenglongwu staff 896 Sep 12 21:09 objects
drwxr-xr-x 4 zhenglongwu staff 128 Sep 12 16:02 refs
# .git/HEAD文件:
$ cat head
ref: refs/heads/temp
# ref代表一个引用,引用到temp分支,继续检查
$ git branch -av
master 4ba1df1 Move readme.txt to readme.md
* temp f9192c6 Add test
## *号代表当前的工作区在哪一个分支上
## 因此HEAD的内容含义代表 我们当前正在工作的Git分支是temp
## 实验: 切换到master分支再查看HEAD文件
$ git checkout master
fatal: this operation must be run in a work tree
$ cd ..
$ git checkout master
Switched to branch 'master'
$ cd -
/Users/zhenglongwu/Desktop/Programming/Git/git_learning/.git
$ cat head
ref: refs/heads/master
## 备注: git checkout 命令就是切换分支
## 结论: HEAD的文件内容会根据切换分支而改变,它告诉我们当前正在工作的是哪个分支。
# .git/config 文件
$ cat config
[core]
repositoryformatversion = 0
filemode = true
bare = false
logallrefupdates = true
ignorecase = true
precomposeunicode = true
[user]
name = user1
email = 670362192@qq.com
## Git的local用户名设置就记录在仓库的config文件中。
## 实验,修改username
$ vi config
$ cat config
...
[user]
name = userlong
email = 670362192@qq.com
$ git config --local --list
core.repositoryformatversion=0
core.filemode=true
core.bare=false
core.logallrefupdates=true
core.ignorecase=true
core.precomposeunicode=true
user.name=userlong
user.email=670362192@qq.com
$ git config --local user.name
userlong
# 反向更改
$ git config --local user.name 'long'
$ git config --local user.name
long
$ cat config
...
[user]
name = long
email = 670362192@qq.com
## 结论:config文件就是储存所有与本地仓库相关的配置信息。
# .git/refs/ 文件夹探究
$ cd refs
$ ls -al
total 0
drwxr-xr-x 4 zhenglongwu staff 128 Sep 12 16:02 .
drwxr-xr-x 14 zhenglongwu staff 448 Sep 14 21:35 ..
drwxr-xr-x 4 zhenglongwu staff 128 Sep 12 21:09 heads
drwxr-xr-x 2 zhenglongwu staff 64 Sep 12 16:02 tags
## tags也被称作里程碑,比如当前项目开发到V1.0了,可以加一个标签打一个标识
## heads对应于所有分支,分支代表的是一个独立的开发空间。比如开发软件时有前端开发和后端开发,此时前端可以创建一个分支,后端建一个分支。 彼此在自己的空间里工作是互不影响的。集成时又可以集成到一个公共的分支上。
### 再挖 .git/refs/heads/文件夹
$ cd heads
$ ls -al
total 16
drwxr-xr-x 4 zhenglongwu staff 128 Sep 12 21:09 .
drwxr-xr-x 4 zhenglongwu staff 128 Sep 12 16:02 ..
-rw-r--r-- 1 zhenglongwu staff 41 Sep 12 20:52 master
-rw-r--r-- 1 zhenglongwu staff 41 Sep 12 21:09 temp
$ cat master
4ba1df1b3b40dae8540c01b81f947a0b4b3d8c1c
## heads文件夹里存放所有的分支,master文件存的是一个HASH值代表这个master最后一次commit的指针
$ git cat-file -t 4ba1df1b3b40dae
commit
## cat-file -t 查看当前哈希值的object是什么类型,是一个commit
## 查看当前所有分支最新commit情况
$ git branch -av
* master 4ba1df1 Move readme.txt to readme.md
temp f9192c6 Add test
## 4ba1df1是短hash值,一般够用,当短的不够用时(产生重复时)再用更长一点的。
$ cat temp
f9192c679da9f6ff44f20c81d1d8ba0fb381193a
## 同理可看出temp文件里存的也是temp分支中最后一次commit的哈希值
### 继续挖 .git/refs/tags/文件夹
$ cd tags
$ ls -al
total 8
drwxr-xr-x 3 zhenglongwu staff 96 Sep 14 23:41 .
drwxr-xr-x 4 zhenglongwu staff 128 Sep 12 16:02 ..
-rw-r--r-- 1 zhenglongwu staff 41 Sep 14 23:41 js01
## 有一个tag:js01, 读它
$ cat js01
b7e1bfaf5787edb14f14981df2d32530792d83fa
$ git cat-file -t b7e1
tag
## 备注:可以少输入几位hash值,只要能识别出唯一的值。
## 加-p 深挖这个hash值代表的东西
$ git cat-file -p b7e1
object d4e1729be6ec1d96e1068171e5d355b09ae5e3e7
type commit
tag js01
tagger long <670362192@qq.com> 1568518864 -0400
js demo
## 继续挖这个object d4e1729be6ec1d96e1068171e5d355b09ae5e3e7是什么? 是一个commit
$ git cat-file -t d4e1
commit
$ git cat-file -p d4e1
tree 9c640279d65a23da23454864b9f96adb59cb3bec
parent 7c13cfe19f0c14585b0629c1095b58be53cdc7cc
author user1 <670362192@qq.com> 1568334269 -0400
committer user1 <670362192@qq.com> 1568334269 -0400
Add javasrcipt
###因此js01文件里存放的hash值代表一个tag,这个tag的hash值里存放了一个对象,这个对象的hash值代表一个commit
- git cat-file -t HASH值: 读取当前hash值代表的object类型
- git cat-file -p HASH值: 读取当前hash值代表的object里面存放的东西(应该有各种属性和代表其它object的hash值)
- .git/refs/heads: 存放所有分支
- .git/refs/heads/master:master分支最后一次commit的hash值
- .git/refs/heads/temp:temp分支最后一次commit的hash值
- .git/refs/tags: 里程碑,存放对某一次特殊意义commit 的标记
- .git/refs/tags/js01: 名叫js01的标记,该文件记录的hash值里存放了另一个commit对象的hash值,也就是标记的commit。
## !!重点: .git/objects/ 文件夹的探究
$ cd objects
$ ls -al
total 0
drwxr-xr-x 29 zhenglongwu staff 928 Sep 14 23:41 .
drwxr-xr-x 14 zhenglongwu staff 448 Sep 14 21:35 ..
....
drwxr-xr-x 3 zhenglongwu staff 96 Sep 12 19:14 77
drwxr-xr-x 3 zhenglongwu staff 96 Sep 12 20:17 7c
drwxr-xr-x 3 zhenglongwu staff 96 Sep 12 20:24 7f
drwxr-xr-x 3 zhenglongwu staff 96 Sep 12 21:09 8c
....
drwxr-xr-x 3 zhenglongwu staff 96 Sep 12 20:29 fb
drwxr-xr-x 2 zhenglongwu staff 64 Sep 12 16:02 info
drwxr-xr-x 2 zhenglongwu staff 64 Sep 12 16:02 pack
## 可以看出有两种类型的文件夹,
## 一种是只有2个字母的大部分文件夹
## 另一种是pack文件夹:Git会做自我梳理过程,当松散文件过多时会打包到这里
### 1.先深挖两字符的文件夹 .git/objects/77/
$ cd 77
$ ls -al
total 8
drwxr-xr-x 3 zhenglongwu staff 96 Sep 12 19:14 .
drwxr-xr-x 29 zhenglongwu staff 928 Sep 14 23:41 ..
-r--r--r-- 1 zhenglongwu staff 55 Sep 12 19:14 37016481fd9dbdf0ec0d9145d56358fd71feb2
##解读:文件夹里有一堆类似hash值得东西:37016481fd9dbdf0ec0d9145d56358fd71feb2。但是它不是完整的hash值,它还缺少开头两个字符--文件夹的名字,因此这串完整的hash值要在开头加上77:
7737016481fd9dbdf0ec0d9145d56358fd71feb2
$ git cat-file -t 7737016481
tree
$ git cat-file -p 773701
100644 blob e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 readme.txt
## 解读:这串hash值代表一个tree类型的object,里面存放了一个文件 readme.txt。文件的hash值是e69de29bb2d1d6...., 这个文件在git里表示的类型是blob--文件对象。
## 我们再以文件夹7f为例:
$ ls -al 7f
total 8
drwxr-xr-x 3 zhenglongwu staff 96 Sep 12 20:24 .
drwxr-xr-x 29 zhenglongwu staff 928 Sep 14 23:41 ..
-r--r--r-- 1 zhenglongwu staff 122 Sep 12 20:24 0153aaaa90651214e53926593e375803742ad5
$ git cat-file -t 7f0153aaaa
tree
$ git cat-file -p 7f0153aaaa
100644 blob c8984ae212db84b4a95e983e0af8e33215c41ec7 .DS_Store
100644 blob 230bfa8af0829fdffd7f78bf0dda6b851e482bd8 index.js
100644 blob 4d9b3a258759c53e7bc66b6fc554c51e2434437c jquery.min.js
$ git cat-file -t 230bfa8a
blob
$ git cat-file -p 230bfa8a
$("#switch").on('click', function () {
if ($("body").hasClass("slow-wind")) {
$("body").removeClass("slow-wind");
$("#switch").removeClass("switched");
}
## 结论:blob就是git的文件类型,并且使用git cat-file -p HASH值 可以直接打开文件内的记录内容。
到现在为止接触到的所有Git的数据类型:(也是接触最多的核心4类型)
- commit
- tag
- tree
- blob
Git目录总结:(常用的)
- ./git/HEAD 文件: 当前工作的git仓库分支. 直接修改其内容与 git checkout 命令同样效果。
- ./git/config 文件: 当前的local仓库所有分支的配置,直接修改文件内容与 git config --local user.name '' 一样效果
- ./git/refs 文件夹: 存放各个分支最新commit 和 tag里程碑信息
- ./git/objects 文件夹:存放git中所有的数据对应的hash值。(只要仓库中两文件的内容一模一样,在git眼里它就是一个文件,然后只有一个hash值代表这个文件?)
commit、tree、blob三个对象之间的关系
存储是git的核心技术点。版本管理系统中,文件的变更是非常频繁的,所以设计一个良好文件储存机制对于版本管理系统是非常关键的,否则版本管理会越来越混乱。
- 一个commit对应且仅对应一颗树, 这颗树代表当前commit对应的一个视图快照,就是在当时那个时间点时,项目所有的文件夹和文件的样子。
- 一个commit里包含了一棵树(项目文件夹整体快照),parent(上一个commit),author(作者),committer(提交人)四者的对应Hash值,然后加上commit时的message信息。
- 一棵树tree里包含了其它树(文件夹)和 blob(文件)的对应hash值
- 其它树tree里依然包含了其它树(子文件夹) 和 blob(文件)的对应hash值
- blob(文件)里仅包含文件的内容
因此:
commit仅储存快照tree,parent,author,committer的hash值 和 commit时附加的解释信息
tree中仅储存 tree 和 blob 的 hash值
blob中就储存 文件的内容信息。(通过blob的hash值读文件)(注意,blob和文件名一点关系都没有,只要文件的内容相同,不管文件名叫什么,都只是一个东西)
# 代码实验
$ git branch -av
* master 4ba1df1 Move readme.txt to readme.md
temp f9192c6 Add test
$ git log
...
commit d4e1729be6ec1d96e1068171e5d355b09ae5e3e7 (tag: js01)
Author: user1 <670362192@qq.com>
Date: Thu Sep 12 20:24:29 2019 -0400
Add javasrcipt
...
# 读取commit的hash值
$ git cat-file -p d4e1729be6ec
tree 9c640279d65a23da23454864b9f96adb59cb3bec
parent 7c13cfe19f0c14585b0629c1095b58be53cdc7cc
author user1 <670362192@qq.com> 1568334269 -0400
committer user1 <670362192@qq.com> 1568334269 -0400
Add javasrcipt
$ ls .git/objects/d4
e1729be6ec1d96e1068171e5d355b09ae5e3e7
# 读取tree的hash值
$ git cat-file -p 9c640279d6
040000 tree e4addc26befad478e734cb7f6919cde05fe70aa6 css
100644 blob 726ecbd247e7b0156bf6a5e39dc9ce0b1048818c index.html
040000 tree 7f0153aaaa90651214e53926593e375803742ad5 javascript
100644 blob e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 readme.txt
$ ls .git/objects/9c
640279d65a23da23454864b9f96adb59cb3bec
# 读取blob的hash值
$ git cat-file -p 726ecbd247
<!DOCTYPE html>
<html lang="en" >
<head>
<meta charset="UTF-8">
...
</body>
</html>
$ ls .git/objects/72
6ecbd247e7b0156bf6a5e39dc9ce0b1048818c
Git 命令深度解析(数一数tree的个数)
# 建立仓库
$ git init count_tree
$ cd count_tree
$ ls -al .git/objects
total 0
drwxr-xr-x 4 zhenglongwu staff 128 Sep 18 23:22 .
drwxr-xr-x 10 zhenglongwu staff 320 Sep 18 23:22 ..
drwxr-xr-x 2 zhenglongwu staff 64 Sep 18 23:22 info
drwxr-xr-x 2 zhenglongwu staff 64 Sep 18 23:22 pack
## 空仓库,没有任何对象
## 创建一个文件夹doc
$ mkdir doc
$ ls
doc
$ git status
On branch master
No commits yet
nothing to commit (create/copy files and use "git add" to track)
$ git add doc
$ git status
On branch master
No commits yet
nothing to commit (create/copy files and use "git add" to track)
$ ls -al .git/objects
total 0
drwxr-xr-x 4 zhenglongwu staff 128 Sep 18 23:22 .
drwxr-xr-x 10 zhenglongwu staff 320 Sep 18 23:22 ..
drwxr-xr-x 2 zhenglongwu staff 64 Sep 18 23:22 info
drwxr-xr-x 2 zhenglongwu staff 64 Sep 18 23:22 pack
## ==> 空文件夹不是对象, add后也没有效果
## 在文件夹doc内创建文件
$ cd doc
$ echo 'hello world'>readme.txt
$ ls
readme.txt
$ cat readme.txt
hello world
$ cd ..
$ git status
On branch master
No commits yet
Untracked files:
(use "git add <file>..." to include in what will be committed)
doc/
nothing added to commit but untracked files present (use "git add" to track)
$ ls -al .git/objects
total 0
drwxr-xr-x 4 zhenglongwu staff 128 Sep 18 23:22 .
drwxr-xr-x 10 zhenglongwu staff 320 Sep 18 23:37 ..
drwxr-xr-x 2 zhenglongwu staff 64 Sep 18 23:22 info
drwxr-xr-x 2 zhenglongwu staff 64 Sep 18 23:22 pack
## 在doc文件内创建了文件readme.txt,git status出现untracked文件,Git系统依然没有创建对象。
## push给Git系统
$ git add doc
$ git status
On branch master
No commits yet
Changes to be committed:
(use "git rm --cached <file>..." to unstage)
new file: doc/readme.txt
$ ls -al .git/objects
total 0
drwxr-xr-x 5 zhenglongwu staff 160 Sep 18 23:44 .
drwxr-xr-x 11 zhenglongwu staff 352 Sep 18 23:44 ..
drwxr-xr-x 3 zhenglongwu staff 96 Sep 18 23:44 a0
...
$ ls -al .git/objects/a0
total 8
drwxr-xr-x 3 zhenglongwu staff 96 Sep 18 23:44 .
drwxr-xr-x 5 zhenglongwu staff 160 Sep 18 23:44 ..
-r--r--r-- 1 zhenglongwu staff 29 Sep 18 23:44 423896973644771497bdc03eb99d5281615b51
$ git cat-file -t a0423896973
blob
$ git cat-file -p a0423896973
hello world!
#### 中途小结:
#### 1.创建空文件夹,Git系统不会有任何变化或提示。
#### 2.在空文件夹内部创建文本文件后,包括文件夹在内Git系统出现untracked file提示, .git/objects中没有创建对象
#### 3.将包含文件的文件夹一起git add后,.git/objects中出现blob对象,即创建的文件。
#### 4.问:git commit之后呢?会有多少创建对象?
## 实验git commit
$ git commit -m'Add readme'
[master (root-commit) 4ce2739] Add readme
1 file changed, 1 insertion(+)
create mode 100644 doc/readme.txt
$ git status
On branch master
nothing to commit, working tree clean
$ git log
commit 4ce2739c6af63445b694ef10323fd9c5ece775c2 (HEAD -> master)
Author: zhenglong <wzhenglong@yahoo.com>
Date: Wed Sep 18 23:55:02 2019 -0400
Add readme
$ git log --oneline
4ce2739 (HEAD -> master) Add readme
$ ls -al .git/objects
total 0
...
drwxr-xr-x 3 zhenglongwu staff 96 Sep 18 23:55 32
drwxr-xr-x 3 zhenglongwu staff 96 Sep 18 23:55 4c
drwxr-xr-x 3 zhenglongwu staff 96 Sep 18 23:55 7e
drwxr-xr-x 3 zhenglongwu staff 96 Sep 18 23:44 a0
...
## 比之前的a0文件夹多了32,4c和7e三个文件夹
## 32文件夹是什么呢?
$ ls -al .git/objects/32
total 8
...
-r--r--r-- 1 zhenglongwu staff 45 Sep 18 23:55 dd8f7c4977eab3ac25d95abefbfa781e58abc7
$ git cat-file -t 32dd8
tree
$ git cat-file -p 32dd8
040000 tree 7e007f7273ba9497e7595b1f84875163f9a8903d doc
$ git cat-file -p 7e007
100644 blob a0423896973644771497bdc03eb99d5281615b51 readme.txt
$ git cat-file -p a0423
hello world!
## 4c文件夹是什么呢?
$ ls -al .git/objects/4c
total 8
...
-r--r--r-- 1 zhenglongwu staff 126 Sep 18 23:55 e2739c6af63445b694ef10323fd9c5ece775c2
$ git cat-file -t 4ce27
commit
$ git cat-file -p 4ce27
tree 32dd8f7c4977eab3ac25d95abefbfa781e58abc7
author zhenglong <wzhenglong@yahoo.com> 1568865302 -0400
committer zhenglong <wzhenglong@yahoo.com> 1568865302 -0400
Add readme
## 32dd8..就是上面doc的父文件夹的hash值
## 7e文件夹是什么呢?
$ ls -al .git/objects/7e
total 8
...
-r--r--r-- 1 zhenglongwu staff 55 Sep 18 23:55 007f7273ba9497e7595b1f84875163f9a8903d
$ git cat-file -t 7e007
tree
$ git cat-file -p 7e007
100644 blob a0423896973644771497bdc03eb99d5281615b51 readme.txt
$ git cat-file -p a0423
hello world!
#### 小结4
#### 1.仓库没有任何commits前,git status:No commits yet. nothing to commit (create/copy files and use "git add" to track)
#### 2.仓库有commits后,git status:nothing to commit, working tree clean
#### 3.仓库commits后, git创建的objects有:
##### a. 32dd8 tree => doc的父文件夹 [count_tree] (内容: 一个7e007的tree --> doc)
##### b. 7e007 tree => readme.txt的父文件夹 [doc] (内容:一个a0423的blob --> readme.txt)
##### c. a0423 blob => (内容:hello world)
##### d. 4ce27 commit => (内容:tree 32dd8 的commit记录)
#### 完整总结--Git内部行为分析
用户行为 Git行为
1. git init 创建空仓库环境
2. 创建空文件夹doc 无反应
3. 写入一个文件 Git出现untracked file提示
4. git add 文件 Git创建blob对象a0423 (readme.txt)
5. git commit Git创建commit对象4ce27 (add readme)
tree对象32dd8 (count_tree)
tree对象7e007 (doc)
分离头指针注意事项?
- git checkout 到空分支后,即不指定从哪一个commit开始分支
- 在这个空分支git add甚至git commit后切回原master分支将丢失在空分支的所有新操作。
- 所有的新操作必须绑定在一个当前指定的一个分支上才行。否则文件丢失。
- 所有的hash值都是一个指针,指向它的内存空间地址。通过Git解读hash值可以阅读当前的对象的任何信息。