赞
踩
本文地址:https://blog.csdn.net/hancoder/article/details/120748968
本文是视频笔记:UP主 麦兜搞IT
# 查看类型 $ git cat-file -t ce0136 blob # 查看内容 # 不存储文件名 $ git cat-file -p ce0136 hello # 查看大小 $ git cat-file -s ce0136 6 git ls-files -s # 查看压缩包 git verify-pack -v .git/objects/pack/...idx # 压缩 git gc # 删除垃圾 git prune # 查看远程分支和本地以为的远程分支差异 git branch -vv
进入空目录,执行git init
将会出现.git目录
./.git
./.git/objects
./.git/objects/info
./.git/objects/pack
./.git/hooks
./.git/info
./.git/info/exclude
./.git/HEAD
./.git/branches
./.git/description
./.git/refs
./.git/refs/heads
./.git/refs/tags
./.git/config # 配置
$ cat .git/config [core] repositoryformatversion = 0 filemode = true bare = false logallrefupdates = true $ git config user.name "demo" $ git config user.email "demo@demo.com" $ cat .git/config [core] repositoryformatversion = 0 filemode = true bare = false logallrefupdates = true [user] # 新增内容 name = demo email = demo@demo.com $ git config -l core.repositoryformatversion=0 core.filemode=true core.bare=false core.logallrefupdates=true user.name=demo user.email=demo@demo.com
如下案例演示更改内容时,git不保存东西,当前修改仅在
工作区
中
$ echo "hello">hello.txt $ cat hello.txt hello ====================================== . ./hello.txt ./.git ./.git/objects ./.git/objects/info ./.git/objects/pack ./.git/hooks ./.git/info ./.git/info/exclude ./.git/HEAD ./.git/branches ./.git/description ./.git/refs ./.git/refs/heads ./.git/refs/tags ./.git/config
查看当前状态
$ git status
On branch master
No commits yet
Untracked files:
(use "git add <file>..." to include in what will be committed)
hello.txt # 未被跟踪的文件
nothing added to commit but untracked files present (use "git add" to track)
暂存区==索引区
$ git add hello.txt ===================== . ./hello.txt ./.git ./.git/objects ./.git/objects/info ./.git/objects/ce ./.git/objects/ce/013625030ba8dba906f756967f9e9ca394464a ./.git/objects/pack ./.git/hooks ./.git/info ./.git/info/exclude ./.git/HEAD ./.git/index ./.git/branches ./.git/description ./.git/refs ./.git/refs/heads ./.git/refs/tags ./.git/config
$ tree .git/ .git/ ├── branches ├── config ├── description ├── HEAD ├── hooks ├── index ├── info │ └── exclude ├── objects │ ├── ce │ │ └── 013625030ba8dba906f756967f9e9ca394464a │ ├── info │ └── pack └── refs ├── heads └── tags
# 查看类型
$ git cat-file -t ce0136
blob
# 查看内容 # 不存储文件名
$ git cat-file -p ce0136
hello
# 查看大小
$ git cat-file -s ce0136
6
关于不存文件名的验证就是新建另外一个文件,文件内容跟hello.txt一样,git add后发现
.git/objects
目录下没有变化
查看当前状态。
$ git status
On branch master
No commits yet
Changes to be committed:
(use "git rm --cached <file>..." to unstage)
new file: hello.txt
特征:
blob 文件内容的字节长度\0 文件内容
blob 6\0 hello | bashasum
t$ cat .git/objects/ce/013625030ba8dba906f756967f9e9ca394464a
# 输出原始内容的压缩 大小<原始大小B+附加压缩信息的内容B
xK⚌⚌OR0c⚌H⚌⚌⚌⚌⚌
.git/index
$ cat .git/index
DIRCafd⚌
⚌@afd⚌
⚌(!>⚌⚌⚌⚌⚌6%
⚌۩⚌V⚌⚌⚌⚌FJ hello.txtIђ⚌⚌⚌⚌W⚌vLt, # 乱码但不是可以看到文件名
$ git ls-files # 查看当前索区文件
hello.txt
$ git ls-files -s # 附带文件内容
# 文件权限 blob文件内容 0 文件名
100644 ce013625030ba8dba906f756967f9e9ca394464a 0 hello.txt
从这里可以看出我们就能在git commit
时知道文件名和文件内容了
$ git commit -m "first111"
[master (root-commit) 3afed10] first111
1 file changed, 1 insertion(+)
create mode 100644 hello.txt
.git/ ├── branches ├── COMMIT_EDITMSG ├── config ├── description ├── HEAD ├── hooks ├── index ├── info │ └── exclude ├── logs # 新 │ ├── HEAD │ └── refs │ └── heads │ └── master ├── objects │ ├── 3a # 新 │ │ └── fed103e52db5eb0e0f8ffaacf8cf914c26fb80 │ ├── aa # 新 │ │ └── a96ced2d9a1c8e72c56b253a0e2fe78393feb7 │ ├── ce │ │ └── 013625030ba8dba906f756967f9e9ca394464a │ ├── info │ └── pack └── refs ├── heads │ └── master # 新 └── tags
查看新增的两个object是什么
$ git cat-file -t 3afe commit # 看提交的内容 $ git cat-file -p 3afe # 这个下面看 tree aaa96ced2d9a1c8e72c56b253a0e2fe78393feb7 # 作者 时间 时区 author demo <demo@demo.com> 1634104255 +0800 committer demo <demo@demo.com> 1634104255 +0800 # 自己输入的 first111 ========================================== # 当前内容tree $ git cat-file -t aaa9 tree $ git cat-file -p aaa9 100644 blob ce013625030ba8dba906f756967f9e9ca394464a hello.txt
结构:
commit
|
tree
|
blob1 blob2
还生成了logs
还生成了heads
$ cat .git/refs/heads/master
# 输出commit对象
3afed103e52db5eb0e0f8ffaacf8cf914c26fb80
# 查看当前指针,也就是当前在哪个分支
$ cat .git/HEAD
ref: refs/heads/master
修改下文件
$ echo " hi">> hello.txt
$ cat hello.txt
hello
hi
.git目录无变化
$ git add hello.txt $ tree .git/ .git/ ├── branches ├── COMMIT_EDITMSG ├── config ├── description ├── HEAD ├── hooks ├── index ├── info │ └── exclude ├── logs │ ├── HEAD │ └── refs │ └── heads │ └── master ├── objects │ ├── 3a │ │ └── fed103e52db5eb0e0f8ffaacf8cf914c26fb80 │ ├── aa │ │ └── a96ced2d9a1c8e72c56b253a0e2fe78393feb7 │ ├── ce │ │ └── 013625030ba8dba906f756967f9e9ca394464a │ ├── dc # 新增blob对象 │ │ └── 0b2eb8c8ef67436d8209ddab5793e84ae5125c │ ├── info │ └── pack └── refs ├── heads │ └── master └── tags
# 查看文件指向,是我们新生成的blob对象
$ git ls-files -s
100644 dc0b2eb8c8ef67436d8209ddab5793e84ae5125c 0 hello.txt
$ git cat-file -t 100b commit ================ $ git cat-file -p 100b tree 48f49d9582feffae9f1c2bc5c6fdc5008cee1c66 # 标注了parent上个版本commit parent 3afed103e52db5eb0e0f8ffaacf8cf914c26fb80 author demo <demo@demo.com> 1634106985 +0800 committer demo <demo@demo.com> 1634106985 +0800 2nd ================= $ git cat-file -t 48f4 tree $ git cat-file -p 48f4 100644 blob dc0b2eb8c8ef67436d8209ddab5793e84ae5125c hello.txt
$ tree .git/ .git/ ├── branches ├── COMMIT_EDITMSG ├── config ├── description ├── HEAD ├── hooks ├── index ├── info │ └── exclude ├── logs │ ├── HEAD │ └── refs │ └── heads │ └── master ├── objects │ ├── 10 │ │ └── 0b7ac61f2ae0fbf0c26200c5d3cdd4c3c9a377 │ ├── 3a │ │ └── fed103e52db5eb0e0f8ffaacf8cf914c26fb80 │ ├── 48 │ │ └── f49d9582feffae9f1c2bc5c6fdc5008cee1c66 │ ├── aa │ │ └── a96ced2d9a1c8e72c56b253a0e2fe78393feb7 │ ├── ce │ │ └── 013625030ba8dba906f756967f9e9ca394464a │ ├── dc │ │ └── 0b2eb8c8ef67436d8209ddab5793e84ae5125c │ ├── info │ └── pack └── refs ├── heads │ └── master └── tags
创建空文件夹
$ mkdir folder1
$ git status
On branch master
nothing to commit, working tree clean
# 说明空文件夹不算任何改变
$ cd folder1/
$ echo "file3v1">file3.txt
$ cd ..
$ git status
On branch master
Untracked files:
(use "git add <file>..." to include in what will be committed)
folder1/
nothing added to commit but untracked files present (use "git add" to track)
$ git add . $ tree .git/ .git/ ├── branches ├── COMMIT_EDITMSG ├── config ├── description ├── HEAD ├── hooks ├── index ├── info │ └── exclude ├── logs │ ├── HEAD │ └── refs │ └── heads │ └── master ├── objects │ ├── 10 │ │ └── 0b7ac61f2ae0fbf0c26200c5d3cdd4c3c9a377 │ ├── 3a │ │ └── fed103e52db5eb0e0f8ffaacf8cf914c26fb80 │ ├── 48 │ │ └── f49d9582feffae9f1c2bc5c6fdc5008cee1c66 │ ├── 9e # 新增 # 文件夹没有对应的对象 │ │ └── b2346b92a4411971092afb38de6fe0df1b8717 │ ├── aa │ │ └── a96ced2d9a1c8e72c56b253a0e2fe78393feb7 │ ├── ce │ │ └── 013625030ba8dba906f756967f9e9ca394464a │ ├── dc │ │ └── 0b2eb8c8ef67436d8209ddab5793e84ae5125c │ ├── info │ └── pack └── refs ├── heads │ └── master └── tags
$ git cat-file -p 9eb2
file3v1
$ git ls-files -s
100644 9eb2346b92a4411971092afb38de6fe0df1b8717 0 folder1/file3.txt
100644 dc0b2eb8c8ef67436d8209ddab5793e84ae5125c 0 hello.txt
$ git commit -m "3d" [master 9865570] 3d 1 file changed, 1 insertion(+) create mode 100644 folder1/file3.txt ├── objects │ ├── 10 │ │ └── 0b7ac61f2ae0fbf0c26200c5d3cdd4c3c9a377 │ ├── 13 │ │ └── 300f3a735cb3e605fee5fd6f14459238ce2423 │ ├── 3a │ │ └── fed103e52db5eb0e0f8ffaacf8cf914c26fb80 │ ├── 48 │ │ └── f49d9582feffae9f1c2bc5c6fdc5008cee1c66 │ ├── 6b # 新增 │ │ └── d9bece9288dc1eb31805f0acf0a7ca2af03f8b │ ├── 98 # 新增 │ │ └── 65570f017280ca316972dd135d18023b9ba59f │ ├── 9e │ │ └── b2346b92a4411971092afb38de6fe0df1b8717 │ ├── aa │ │ └── a96ced2d9a1c8e72c56b253a0e2fe78393feb7 │ ├── ce │ │ └── 013625030ba8dba906f756967f9e9ca394464a │ ├── dc │ │ └── 0b2eb8c8ef67436d8209ddab5793e84ae5125c │ ├── info │ └── pack
$ git cat-file -t 9865 commit $ git cat-file -p 9865 tree 13300f3a735cb3e605fee5fd6f14459238ce2423 parent 100b7ac61f2ae0fbf0c26200c5d3cdd4c3c9a377 author demo <demo@demo.com> 1634109138 +0800 committer demo <demo@demo.com> 1634109138 +0800 3d $ git cat-file -p 1330 040000 tree 6bd9bece9288dc1eb31805f0acf0a7ca2af03f8b folder1 100644 blob dc0b2eb8c8ef67436d8209ddab5793e84ae5125c hello.txt # 上面可以看出文件夹是个tree $ git cat-file -t 6bd9 tree $ git cat-file -p 6bd9 100644 blob 9eb2346b92a4411971092afb38de6fe0df1b8717 file3.txt
commit时只生成tree和commit对象。add时生成blob对象
也就是说每个tree是个文件夹
git的文件状态
branches are named pointers to commits
分支指向commit
HEAD文件指向当前分支最新的commit
$ cat .git/HEAD
ref: refs/heads/master
$ cat .git/refs/heads/master
9865570f017280ca316972dd135d18023b9ba59f
$ git cat-file -t 9865
commit
$ cat .git/logs/HEAD
0000000000000000000000000000000000000000 3afed103e52db5eb0e0f8ffaacf8cf914c26fb80 demo <demo@demo.com> 1634104255 +0800 commit (initial): first111
3afed103e52db5eb0e0f8ffaacf8cf914c26fb80 100b7ac61f2ae0fbf0c26200c5d3cdd4c3c9a377 demo <demo@demo.com> 1634106985 +0800 commit: 2nd
100b7ac61f2ae0fbf0c26200c5d3cdd4c3c9a377 9865570f017280ca316972dd135d18023b9ba59f demo <demo@demo.com> 1634109138 +0800 commit: 3d
切换分支就是切换HEAD指向
$ git branch
* master
$ git branch dev
$ git branch
dev
* master
$ git branch -d dev
Deleted branch dev (was 9865570).
$ git branch
* master
$ git branch dev
切换
$ git branch dev $ git checkout dev Switched to branch 'dev' $ git branch * dev master $ cat .git/refs/heads/ dev master $ git log commit 9865570f017280ca316972dd135d18023b9ba59f (HEAD -> dev, master) Author: demo <demo@demo.com> Date: Wed Oct 13 15:12:18 2021 +0800 3d commit 100b7ac61f2ae0fbf0c26200c5d3cdd4c3c9a377 Author: demo <demo@demo.com> Date: Wed Oct 13 14:36:25 2021 +0800 2nd commit 3afed103e52db5eb0e0f8ffaacf8cf914c26fb80 Author: demo <demo@demo.com> Date: Wed Oct 13 13:50:55 2021 +0800 first111
$ git branch * dev master $ echo "dev">dev.txt $ ls dev.txt folder1 hello.txt $ git add . $ git commit -m "dev 1st" [dev 4c807f2] dev 1st 1 file changed, 1 insertion(+) create mode 100644 dev.txt $ git log commit 4c807f2a27eb709abef22491166c30a6d71166de (HEAD -> dev) Author: demo <demo@demo.com> Date: Wed Oct 13 15:50:13 2021 +0800 dev 1st commit 9865570f017280ca316972dd135d18023b9ba59f (master) Author: demo <demo@demo.com> Date: Wed Oct 13 15:12:18 2021 +0800 3d
t$ tree .git --sort=ctime .git ├── branches ├── description ├── info │ └── exclude ├── refs │ ├── tags │ └── heads │ ├── master │ └── dev ├── hooks ├── logs │ ├── refs │ │ └── heads │ │ ├── master │ │ └── dev │ └── HEAD ├── config ├── HEAD ├── COMMIT_EDITMSG ├── index └── objects ├── info ├── pack ├── ce │ └── 013625030ba8dba906f756967f9e9ca394464a ├── 3a │ └── fed103e52db5eb0e0f8ffaacf8cf914c26fb80 ├── aa │ └── a96ced2d9a1c8e72c56b253a0e2fe78393feb7 ├── dc │ └── 0b2eb8c8ef67436d8209ddab5793e84ae5125c ├── 10 │ └── 0b7ac61f2ae0fbf0c26200c5d3cdd4c3c9a377 ├── 48 │ └── f49d9582feffae9f1c2bc5c6fdc5008cee1c66 ├── 9e │ └── b2346b92a4411971092afb38de6fe0df1b8717 ├── 13 │ └── 300f3a735cb3e605fee5fd6f14459238ce2423 ├── 6b │ └── d9bece9288dc1eb31805f0acf0a7ca2af03f8b ├── 98 │ └── 65570f017280ca316972dd135d18023b9ba59f ├── 38 # blob │ └── f8e886e1a6d733aa9bfa7282568f83c133ecd6 ├── 4c # commit │ └── 807f2a27eb709abef22491166c30a6d71166de └── a1 # tree └── 396e6bd4f6d8082630af880d795a4c28b67deb 25 directories, 24 files $ git cat-file -t 38f8 blob $ git cat-file -t 4c80 commit $ git cat-file -t a139 tree
删除分支后特有的对象不会删除
会指向commit,没有分支名字
要保存的话需要保存到分支
git switch -c <new-branch>
# 这个命令更好用
git checkout -b <分支名>
# 或者取消操作
git switch -
也就是说如果没merge前合并了分支,我们可以先checkout到commit上,
# 查看所有分支的log
git reflog
git checkout commit号
git checkout -b 新分支名
# 就可以合并了
git diff
比较工作区和暂存区的区别;或是当前索引区和代码仓库的区别
当前工作区和索引区的差别
index 索引区的blob...当前工作区虚拟的blob
a是索引区,b是工作区
本地已经有仓库时如何提交到远程仓库
# 指定远程仓库
git remote add origin git@github.com:han/git-demo.git
git push -u origin master
$tree .git 25 directories, 24 files $ git remote add origin https://gitee.com/HanFerm/git-demo.git $tree .git 25 directories, 24 files $ cat .git/config [core] repositoryformatversion = 0 filemode = true bare = false logallrefupdates = true [user] name = demo email = demo@demo.com [remote "origin"] url = https://gitee.com/HanFerm/git-demo.git fetch = +refs/heads/*:refs/remotes/origin/*
$ git push -u origin master Username for 'https://gitee.com': hanferm Password for 'https://hanferm@gitee.com': Enumerating objects: 10, done. Counting objects: 100% (10/10), done. Delta compression using up to 40 threads Compressing objects: 100% (4/4), done. Writing objects: 100% (10/10), 685 bytes | 685.00 KiB/s, done. Total 10 (delta 0), reused 0 (delta 0) remote: Powered by GITEE.COM [GNK-6.1] To https://gitee.com/HanFerm/git-demo.git * [new branch] master -> master Branch 'master' set up to track remote branch 'master' from 'origin'. $tree .git 25+4 directories, 24+2 files
$ cat .git/refs/remotes/origin/master 9865570f017280ca316972dd135d18023b9ba59f $ cat .git/refs/heads/master 9865570f017280ca316972dd135d18023b9ba59f # 说明本地master分支和远程master分支是同步的 $ git cat-file -t 9865 commit $ git cat-file -p 9865 tree 13300f3a735cb3e605fee5fd6f14459238ce2423 parent 100b7ac61f2ae0fbf0c26200c5d3cdd4c3c9a377 author demo <demo@demo.com> 1634109138 +0800 committer demo <demo@demo.com> 1634109138 +0800 3d $ git log commit 9865570f017280ca316972dd135d18023b9ba59f (HEAD -> , master, origin/master) Author: demo <demo@demo.com> Date: Wed Oct 13 15:12:18 2021 +0800 3d
gitlab中心有了如gitTest.git
文件夹,和本地的.git文件一致
du -h /
git gc
再使用du -h .git/objects查看时会发现减小很多内存,是压缩到了.git/objects/pack中
有规则的文件压缩才显著
如果两个文件的SHA1值相等,是不同的blob,因为是blob size\0这样的形式进行hash的
git gc时输出delta=3,因为压缩了3个blob对象
看内容:git verify-pack -v .git/objects/pack/...idx
git clone拉过来的都是压缩后的对象
解压缩:git unpack-objects
git help unpack-objects
在仓库里的文件不会解压缩,要想解压缩需要将.pack文件移除,然后git unpack-objects < AAA.pack文件
比如两次git add一次commit就会产生垃圾对象
git gc只是压缩了需要的文件,而垃圾对象blob并没有删除,我们可以使用git prune
命令删除垃圾对象
git gc只在大多数情况下删除垃圾对象,有时候不删除
可以使用git prune -n
查看此次要删除的垃圾对象
git fsck
可以看到悬空对象
但是把分支删除了之后对象也还在时,prune就不起作用了,git gc也会把删除掉分支的对象压缩了,上面的命令查出来均不认为是垃圾对象。此时可以使用更复杂的命令
这种场景是没有冲突的场景,仅仅是领先于master而已,拼接在master前部即可
git merge branch2
Updating 8d44旧指针...bd57新指针
Fast-forward
# merge后多了个ORIG_HEAD目录,记录HEAD的之前状态
# HEAD往前移动一步,此时工作区就有未add内容了
git reset ORIG_HEAD
看指定的对象,会发现有2个parent
# 下面命令会发生冲突
(master)git merge bugfix
$ git status
both modified
$ cat test.txt
<<<<<< HEAD
add from master
========
add from bugfix
>>>>>>>> bugfix
$ git ls-files -s
git merge发生冲突时显示的内容就是根据这3个index结合而成的
修改完后git commit
即可,无需加-m ""
,因为已经有信息了
git log
后跟正常合并没差别
此时要求dev有master最新的commit
执行rebase后会同步master最新的commit
(dev) $ git rebase master
因为同步后原来dev的新提交由于跟时间等有原因,SAH1值会变,
有冲突时先解决冲突。
但是有问题的情况是如果原来的已经push到远程,这样就都了一些SHA1,push
就会出错
还有问题是如果dev push到远程后别人已经基于它修改了,此时你rebase后强制push到远程仓库,别人就push不上去,所以别人也在使用的dev不要rebase。此外不要在master上rebase。
git tag <tagname>
git tag -a <tag name> -m <tag msg>
# 查看本地仓库分支
git branch
# 查看远程仓库分支
git branch -r
# 远程信息被压缩到packed-refs文件中
# 检查本地以为的远程仓库和真正的远程仓库分支情况与同步
git fetch
# 查看远程仓库和本地关联情况
git remote show origin
下面要说明的是压缩的packed-refs不是实时的,也就不是最新的SHA1
最新的远程信息在remotes下
此时再git log会发现没有origin的指针信息了,因为远程已经超前于log了
下面观察远程新建分支后本地的变化
但是远程分支删除时使用git fetch
是无效果的,下面的两种命令可以解决该问题
git remote show origin
输出的tracked代表本地有对应的分支,
使用
git branch -vv
可以查看远程分支和本地分支是否自己各自创建的同名分支
pull=fetch+merge
fetch完后本地知道了origin/master的指向,然后master merge origin/master后两个master才同步,此时就是一个fast forward merge
如果本地master和远程master冲突:
此时本地以为的origin和远程又不同步了,所以需要push,push后就又一致了
建议:明知道有冲突建议先fetch,然后git diff origin/master
看看有没有冲突
执行完fetch后master和dev的顺序发生了变化。切换分支后只要不运行fetch,该FEACH_HEAD就不会变
这个排名有什么用呢?
# 直接敲git push若分支没有和远程分支关联,会不成功,此时可以
git push
git push --set-upstream origin feature-1意思是要在远程创建名为feature-1的分支
git push origin feature-1也可以推送,--set-upstream的意思是进行关联,如果不带的话我们-vv还是看不到关联,下次还是不能输入git push
--set-upstream的简写是-u
# 删除远程分支
git push origin -d feature-1
什么是hook:在某些操作前后触发
红色无法避免跳过
黄色可跳过
.sample
是不生效的
比如下面的pre,他是验证如果内容是如果使用了非ASCII码的名字,就会exit 1代表检查未通过。exit 0
才执行通过
$ cat pre-commit.sample #!/bin/sh # # An example hook script to verify what is about to be committed. # Called by "git commit" with no arguments. The hook should # exit with non-zero status after issuing an appropriate message if # it wants to stop the commit. # # To enable this hook, rename this file to "pre-commit". if git rev-parse --verify HEAD >/dev/null 2>&1 then against=HEAD else # Initial commit: diff against an empty tree object against=$(git hash-object -t tree /dev/null) fi # If you want to allow non-ASCII filenames set this variable to true. allownonascii=$(git config --bool hooks.allownonascii) # Redirect output to stderr. exec 1>&2 # Cross platform projects tend to avoid non-ASCII filenames; prevent # them from being added to the repository. We exploit the fact that the # printable range starts at the space character and ends with tilde. if [ "$allownonascii" != "true" ] && # Note that the use of brackets around a tr range is ok here, (it's # even required, for portability to Solaris 10's /usr/bin/tr), since # the square bracket bytes happen to fall in the designated range. test $(git diff --cached --name-only --diff-filter=A -z $against | LC_ALL=C tr -d '[ -~]\0' | wc -c) != 0 then cat <<\EOF Error: Attempt to add a non-ASCII file name. This can cause problems if you want to work with people on other platforms. To be portable it is advisable to rename the file. If you know what you are doing you can disable this check using: git config hooks.allownonascii true EOF exit 1 fi # If there are whitespace errors, print the offending file names and fail. exec git diff-index --check --cached $against --
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。