Git 基础

基础配置

配置 user.name 和 user.email

git config --global user.name 'your_name' git config --global user.email 'your_email'

config 的三个作用域

缺省等同于 local

git config --local // local 只对某个仓库有效 git config --global // global 只对当前用户所在仓库有效 git config --system // system 对系统所有登录的用户有效

显示 config 的配置,加 --list

git config --list --local git config --list --global git config --list --system

创建 git 仓库

已存在项目

cd [your_project] git init

新建项目

git init [your_project]

提交信息

git commit -m "init"
git add [file_name]
git log

文件重命名

基础操作

mv readme readme.md
git status git add readme.md git rm readme git status

简化操作

git reset --hard // 清理暂存区所有工作信息
git mv readme readme.md // 等同于上述操作,简化操作
git commit -m "perf: move reame to readme.md"

查看版本演变历史

git log
git log --oneline // 查看只包含提交信息的记录(一行简洁方式)
git log -n4 --oneline // 最近的 n 次
git branch -v // 查看本地分支
git log --all // 查看所有分支的日志信息
git log --all --graph // 图形化的日志信息
git log --oneline --all -n4 // 所有分支最近的 4 次提交记录
git log --oneline --all -n4 --graph // 所有分支最近的 4 次图形化提交记录
git help --web log // 查看 web 界面的 git log文档

图形界面工具

gitk // 弹出 git 自带的图形化工具 gitk --all // 查看所有信息

.git 目录

HEAD

文本文件,指向当前分支。

ref: refs/heads/master

config

[core] repositoryformatversion = 0 filemode = false bare = false logallrefupdates = true symlinks = false ignorecase = true [remote "origin"] url = git@github.com:iheora/notes.git fetch = +refs/heads/*:refs/remotes/origin/* [branch "master"] remote = origin merge = refs/heads/master [gui] wmstate = normal geometry = 1061x563+96+96 233 255

refs

refs/tags 针对重要版本,可以打标签

refs/heads 本地分支文件夹

refs/remotes 远程分支文件夹

git cat-file -t 查看对象类型
git cat-file -p 查看对象内容
git cat-file -s 查看对象大小

cd refs/heads cat .\master // aa4854071ab2fec2a08c9fcc58dfe939b09d6e9a git cat-file -t aa4854071ab2fec2a08c9fcc58dfe939b09d6e9a // commit 类型 git branch -av // * master aa48540 [ahead 1] docs: update

master 指针指向 commit 。master 后 存在一个 hash 值,如果 hash 值足够标识唯一性,会截断进行显示。

tag 包含的是 git 对象,指向 commit。

objects

objects 是 git 文件系统核心内容,存在多个目录。

2个字符的文件夹,以 e8 为例。下面存在多个文件。

– 0b9ebd39f834f536c1aaa96df56074ad5481ae
– 3b4ce5e9a33e0b41fe922d28093460085fe12d

// 拼接规则:e8 + 文件名 git cat-file -t e83b4ce5e9a33e0b41fe922d28093460085fe12d // blob 可能存在多种文件类型 blob(文件对象),commit,tree 等, git cat-file -p e83b4ce5e9a33e0b41fe922d28093460085fe12d // 查看文件内容

pack 目录

git 会做打包处理。

commit、tree 和 blob 关系

git commit,commit 对象,一个 commit 肯定会对应一棵树(tree)。

树相当于一个快照,存储当时 git 操作的所有信息。

tree -- tree -- blob -- blod -- tree // styles tree // styles -- blob // logo.png,对应 blob 二进制文件

blob 对应一个文件。只要文件内容相同,git 都将之视为一个 blob。可以节约内存空间。
git 文件和文件名没有关系,会根据文件内容生成 blob。

commit 可以被看做是 tree 的根节点。

文件生成 blob 对象后,再对文件进行修改,git 会把松散的 blob 做整理,把内容相近的 blob 做增量存储。

数一数 tree 的个数

新建的 Git 仓库,有且仅有 1 个 commit,仅包含 /doc/readme,请问内部含有多少个 tree,多少个 blob?

git init watch_git_objects cd watch_git_objects mkdir doc cd doc echo "hello world" > readme cd .. find .git/objects -type -f // 空目录 git add doc git status // 添加到暂存区,没有 commit find .git/objects -type -f // .git/objects/3b/18e512dba79e4c8300dd08aeb37f8e728b8dad // 加入暂存区,git 会创建 blob 文件 git cat-file -t 3b18e512db // blob git commit -m "add readme" find .git/objects -type -f // .git/object/3b/18e512dba79e4c8300dd08aeb37f8e728b8dad blob // .git/object/f5/5a12e98ffd80349f3499cc52a06b8afb93ec90 tree // .git/object/25/0bfe7259457d05a1e29ced793fac74dc10e47f commit // .git/object/2c/5264370f2630da80ee38f412213d59657af6e8 tree // 4 个

commit ,两个 tree 一个是 doc 目录,一个是 readme 文件,blob 是文件内容。

分离头指针情况的注意事项

detached HEAD。

git checkout 415c5c8 // 切换分支的时候,切换成 commit

分离头指针的情况下,可以继续做开发,然后 commit,不会影响其他分支。

提交 commit 时,git 会提示 HEAD detached at 415c5c8,即没有依赖分支做操作,只依赖 commit。 git commit -am "update" // 不经过暂存区,直接提交

分支头指针其实就是说正工作在一个没有分支的状态下,如果这时候切换其他分支而不保存,就会丢失已变更信息。

当你想做一些变更,只是尝试性的一些变更,如果发现效果不好,可以随时丢弃掉。

这时就可以使用分离头指针的现象,直接 checkout 切换到新的分支即可。

gitk --all // 图形化工具不会显示任何关于分离头指针情况的信息记录 // git 眼中如果 commit 没和 branch 或者 tag 绑定,就是无效的提交信息,很可能会被 git 当作垃圾清理 // 可以根据切换分支时的提示,对 commit 记录建立新分支

HEAD 和 branch

git checkout -b fix_readme master // 基于 master 分支创建新分支并切换 git log -n1 // HEAD -> fix_readme cat .git/HEAD // ref: refs/heads/fix_readme

HEAD 可以指代新分支的最后一次提交,也可以不和分支挂钩,和 commit 挂钩,即分离头指针的状态。

当分支切换时,HEAD 会指定新的分支。

HEAD 最终还是指向 commit,HEAD 指向分支的时候,分支里面的内容指向的还是 commit,即最后一次 commit。
不管是处于分离头状态,还是正常状态,HEAD 最后都会指向最新一次提交的 commit。

比较 commit 差异

git diff 3d4731 415c5c8 // 比较两个 commit
git diff HEAD HEAD~1 // 比较当前及前一次提交 git diff HEAD HEAD^^ // 比较当前及 HEAD 的前两次提交 // ~ 和 ^ 两种用法都可以