Git原理(02)
11. pack文件
11.1 背景
新建一个代码仓库作为演示
1 | xiong@Surface-pro6 MINGW64 /c/Files/git-demo2 |
将一个大小为7.32M的文件放到工作区
将该文件进行添加和提交,使用
du -h来查看文件夹的占用情况1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17xiong@Surface-pro6 MINGW64 /c/Files/git-demo2 (master)
git add word_note.docx
xiong@Surface-pro6 MINGW64 /c/Files/git-demo2 (master)
git commit -m "1st commit"
[master (root-commit) 534c54e] 1st commit
1 file changed, 0 insertions(+), 0 deletions(-)
create mode 100644 word_note.docx
xiong@Surface-pro6 MINGW64 /c/Files/git-demo2 (master)
du -h .git/objects
1.0K .git/objects/17
1.0K .git/objects/53
7.0M .git/objects/b8
0 .git/objects/info
0 .git/objects/pack
7.0M .git/objects将文件进行小的改动,随之再进行添加和提交
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15xiong@Surface-pro6 MINGW64 /c/Files/git-demo2 (master)
git add word_note.docx
xiong@Surface-pro6 MINGW64 /c/Files/git-demo2 (master)
git commit -m "2nd commit"
[master 67a095b] 2nd commit
1 file changed, 0 insertions(+), 0 deletions(-)
xiong@Surface-pro6 MINGW64 /c/Files/git-demo2 (master)
git add word_note.docx
xiong@Surface-pro6 MINGW64 /c/Files/git-demo2 (master)
git commit -m "3rd commit"
[master 5153efa] 3rd commit
1 file changed, 0 insertions(+), 0 deletions(-)查看此时文件夹占用情况
1
2
3
4
5
6
7
8
9
10
11
12
13
14xiong@Surface-pro6 MINGW64 /c/Files/git-demo2 (master)
du -h .git/objects
1.0K .git/objects/17
7.0M .git/objects/4b
1.0K .git/objects/51
1.0K .git/objects/53
1.0K .git/objects/67
1.0K .git/objects/ae
7.0M .git/objects/b8
7.0M .git/objects/e4
1.0K .git/objects/fc
0 .git/objects/info
0 .git/objects/pack
21M .git/objects1
2
3
4
5
6
7
8xiong@Surface-pro6 MINGW64 /c/Files/git-demo2 (master)
ls -lh
total 7.4M
-rw-r--r-- 1 xiong 197609 7.4M Aug 22 17:21 word_note.docx
xiong@Surface-pro6 MINGW64 /c/Files/git-demo2 (master)
git ls-files -s
100644 e4d8fff037528cc82c6f923a5200f3dfa1876d6b 0 word_note.docx进行三次提交后objects文件夹已经达到了21M,虽然此时工作区内容只有7.4M
在git里,文件会先压缩成blob对象进行存储。这虽在一定程度上减小了内存开销,但是由于每次对文件在工作区修改后,对文件进行添加和提交时,都会存储整个对象的压缩文件。根据开发实际场景,每次文件的改动都不会有较大的改动,而每次再新生成一份blob文件,就会增大内存开销。在此背景下提出了使用git gc进行压缩的方案
11.2 git gc 进行文件压缩
①使用git gc进行文件压缩
1 | xiong@Surface-pro6 MINGW64 /c/Files/git-demo2 (master) |
②查看现在.git文件夹中的内存占用
1 |
|
21M内容压缩成7.3M
③查看objects中的内容
1 | xiong@SURFACE-PRO6 C:\Files\git-demo2 |
blob文件全部被压缩,生成了pack
查看pack文件夹中文件的大小
1
2
3
4
5xiong@Surface-pro6 MINGW64 /c/Files/git-demo2 (master)
ls -lh .git/objects/pack
total 7.3M
-r--r--r-- 1 xiong 197609 1.3K Aug 22 20:18 pack-3181db0c2b5d97f6d38c69d9a43358790246aa10.idx
-r--r--r-- 1 xiong 197609 7.3M Aug 22 20:18 pack-3181db0c2b5d97f6d38c69d9a43358790246aa10.pack查看.dex文件里存储的内容:
git verify-pack -v 文件路径1
2
3
4
5
6
7
8
9
10
11
12
13
14
15xiong@Surface-pro6 MINGW64 /c/Files/git-demo2 (master)
git verify-pack -v .git/objects/pack/pack-3181db0c2b5d97f6d38c69d9a43358790246aa10.idx
5153efa4cf47077622e7771888cae3deb87db41e commit 225 149 12
67a095b95ff121fb3e1bc648b98814e1c8f6c148 commit 225 148 161
534c54ea578f0d6517cb5d38ddced88d4c4158b4 commit 177 119 309
b80edea2a581ed6917723b45871f0af11beb714d blob 7683972 7330028 428
4b574b366e9bb3ad454462ba510db98a01837b66 blob 167961 166370 7330456 1 b80edea2a581ed6917723b45871f0af11beb714d
e4d8fff037528cc82c6f923a5200f3dfa1876d6b blob 98578 97543 7496826 2 4b574b366e9bb3ad454462ba510db98a01837b66
fcd21cca77d88e7c8bda0ac43e72c8b5a6c7a4be tree 42 53 7594369
aef20abb0786e52ac2234180cf18ad488023f7f2 tree 42 52 7594422
172344478aef4544529c644e29130d7d8f1b041f tree 42 53 7594474
non delta: 7 objects
chain length = 1: 1 object
chain length = 2: 1 object
.git/objects/pack/pack-3181db0c2b5d97f6d38c69d9a43358790246aa10.pack: ok里面存储有之前三次添加和提交所产生对象的完整记录
只有b80ede所对应的blob文件所存储的是第一次提交时对象的完整内容,另外两个blob文件(后面跟有一串SHA1值),所记录的是与原始文件存在的差异
应用场景
当从远程克隆仓库到本地时,使用pack文件进行传输就可以节省传输时间,不过在传输到本地后,如果要检索到特定的某一次commit,则需要花费一点时间和内存去解压缩pack文件
11.3 解压缩
使用git unpack-objects < 输入流
使用git help unpack-objects查看命令描述
名字
git 拆包对象 - 从包装的存档中拆开对象
概要
1
git unpack-objects [-n] [-q] [-r] [--strict]
描述
从标准输入中读取包装的存档 (.pack),扩展其中包含的对象,并以”松散”(每个文件一个对象)格式将其写入存储库。
存储库中已经存在的对象不会从包装文件中拆开。因此,如果您在目标存储库内的包装文件上使用此命令,则不会拆开任何内容
选项
-n
干运行。检查包文件,而不实际拆开对象。
-q
命令通常显示百分比进度。此标志将抑制它。
-r
解包损坏的打包文件时,该命令在第一次损坏时终止。这个标志告诉它继续前进,尽最大努力恢复尽可能多的对象。
-严格
不要编写内容或链接中断的对象。
-最大输入大小=<尺寸>
如果包大于<大小>, 则死亡
注意点
1 | xiong@SURFACE-PRO6 C:\Files\git-demo2 |
当我们要使用unpack时,我们需要将.pack文件移到外面。虽然此时的objects文件夹里没有objects文件,但是所有的文件都被存储在pack里,所以系统任然会认为存储库中已经存在这些文件,验证如下:
1 | xiong@Surface-pro6 MINGW64 /c/Files/git-demo2 (master) |
1 | xiong@SURFACE-PRO6 C:\Files\git-demo2 |
虽然使用了unpack文件,但是系统仍然认为仓库里有对象
如果要解压当前pack文件,做法如下
将pack文件移出object文件夹
1
2xiong@Surface-pro6 MINGW64 /c/Files/git-demo2 (master)
mv .git/objects/pack/pack-3181db0c2b5d97f6d38c69d9a43358790246aa10.pack .git/此时git会认为代码仓库是空的
使用unpack进行解压
1
2
3xiong@Surface-pro6 MINGW64 /c/Files/git-demo2 (master)
git unpack-objects < .git/pack-3181db0c2b5d97f6d38c69d9a43358790246aa10.pack
Unpacking objects: 100% (9/9), 7.24 MiB | 6.10 MiB/s, done.查看objects文件目录
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38xiong@SURFACE-PRO6 C:\Files\git-demo2
tree .git/objects /f
卷 Local Disk 的文件夹 PATH 列表
卷序列号为 C0000100 F296:2801
C:\FILES\GIT-DEMO2\.GIT\OBJECTS
├─17
│ 2344478aef4544529c644e29130d7d8f1b041f
│
├─4b
│ 574b366e9bb3ad454462ba510db98a01837b66
│
├─51
│ 53efa4cf47077622e7771888cae3deb87db41e
│
├─53
│ 4c54ea578f0d6517cb5d38ddced88d4c4158b4
│
├─67
│ a095b95ff121fb3e1bc648b98814e1c8f6c148
│
├─ae
│ f20abb0786e52ac2234180cf18ad488023f7f2
│
├─b8
│ 0edea2a581ed6917723b45871f0af11beb714d
│
├─e4
│ d8fff037528cc82c6f923a5200f3dfa1876d6b
│
├─fc
│ d21cca77d88e7c8bda0ac43e72c8b5a6c7a4be
│
├─info
│ commit-graph
│ packs
│
└─pack
pack-3181db0c2b5d97f6d38c69d9a43358790246aa10.idx解压成功,将对象写入到objects文件夹里
12. git垃圾对象的清理
12.1 多次添加产生垃圾对象
在使用git进行版本控制的时候,通常会对一个文件在本地进行多次的修改和添加,最后才提交代码仓库。只有最后提交到代码仓库的那次才是有效的,之前所添加到索引区的文件就成为了垃圾对象。对于此类垃圾对象,使用git prune进行垃圾对象清理
初始新的代码仓库git-demo3进行测试,新建文件test.txt,每次做一点修改就进行添加
1 | xiong@Surface-pro6 MINGW64 /c/Files/git-demo3 |
查看此时objects中的内容
1 | xiong@SURFACE-PRO6 C:\Files\git-demo3 |
经过3次add,产生了三个blob对象
进行一次commit,并使用git gc进行文件压缩,查看结果
1 | xiong@Surface-pro6 MINGW64 /c/Files/git-demo3 (master) |
1 | xiong@SURFACE-PRO6 C:\Files\git-demo3 |
1 | xiong@Surface-pro6 MINGW64 /c/Files/git-demo3 (master) |
被压缩的对象是最后一次的blob、tree和commit对象
此时可以看到有两个对象并未被压缩到pack文件里,这两个文件就是垃圾对象
12.1.2 使用git prune清理垃圾对象
git prune
名字
git prune从对象数据库中修剪所有无法到达的对象
概要
1
git prune [-n] [-v] [--progress] [--expire <time>] [--] [<head>…]
描述
注意:在大多数情况下,用户应该运行git gc,它会调用git prune。请参阅下面的”注意”部分。
运行
git fsck --unreachable使用refs/下所有可用的refs,可以选择在命令行上指定其他对象集,并从对象数据库中删除无法从这些head对象中访问的所有未打包对象。此外,它还通过运行git prune-packed来修剪包中的未打包对象。它还从.git/shallow中删除任何ref.ref都无法访问的条目/选项
-n
–dry-run
不移除任何事物,只是显示哪些事物将会被移除
-v
–verbose
显示所有背移除的对象
–progress
显示所有进程
expire
仅使早于
–
不要将任何其他参数解释为选项
- ...
除了从我们的任何引用中都可以访问的对象之外,还要保持从列出的
s中可以访问的对象。
例子
要修剪存储库未使用的对象或通过其从存储库借用的其他对象,请执行以下操作:
.git/objects/info/alternates1
git prune $(cd ../another && git rev-parse --all)
git fsck
名字
git-fsck - 验证数据库中对象的连接和有效性
概要
1
2
3
4git fsck [--tags] [--root] [--unreachable] [--cache] [--no-reflogs]
[--[no-]full] [--strict] [--verbose] [--lost-found]
[--[no-]dangling] [--[no-]progress] [--connectivity-only]
[--[no-]name-objects] [<object>*]描述
验证数据库中对象的连接和有效性。
选项
<object>
要作为不可访问性跟踪的头部处理的对象。
如果未提供任何对象,git fsck默认使用索引文件、refs命名空间中的所有SHA-1引用以及所有reflogs(除非提供了–no reflogs)作为头。–unreachable
打印存在但无法从任何引用节点访问的对象。
–[no-]dangling
打印存在但从未直接使用的对象(默认)–不能使用任何悬空来从输出中忽略此信息。
–root
显示根节点
–tags
显示标签
–cache
将索引中记录的任何对象也作为不可达跟踪的头节点。
–no-reflogs
不要考虑仅由reflog中的条目引用的可到达的提交。此选项仅用于搜索以前在ref中但现在不在ref中但仍在相应reflog中的提交。
–full
不仅要检查GIT_OBJECT_目录($GIT_DIR/objects)中的对象,还要检查GIT_alternate_OBJECT_目录或$GIT_DIR/objects/info/alternates中列出的备用对象池中的对象,以及备用对象池中的$GIT_DIR/objects/pack和相应的pack子目录中的打包GIT归档中的对象。现在这是默认值;你可以关闭它,不需要完全关闭。
……
使用prune -n显示会被删除的对象
1 | xiong@Surface-pro6 MINGW64 /c/Files/git-demo3 (master) |
使用git fsck查看悬空的对象
1 | xiong@Surface-pro6 MINGW64 /c/Files/git-demo3 (master) |
使用
git prune删除1
2xiong@Surface-pro6 MINGW64 /c/Files/git-demo3 (master)
git prune查看objects
1
2
3
4
5
6
7
8
9
10
11
12xiong@SURFACE-PRO6 C:\Files\git-demo3
tree .git/objects /f
卷 Local Disk 的文件夹 PATH 列表
卷序列号为 C0000100 F296:2801
C:\FILES\GIT-DEMO3\.GIT\OBJECTS
├─info
│ commit-graph
│ packs
│
└─pack
pack-b9d4bdcbfa833a54a35bc737eaba5f5088f6d956.idx
pack-b9d4bdcbfa833a54a35bc737eaba5f5088f6d956.pack悬空的两个对象被删除了
12.2 删除未合并分支产生的对象
对于新建的分支,如果想完整的删除分支,先使用git -D 分支名强制删除,但是这样操作,分支上所做的操作还是可以被还原,分支上的文件也仍然存在,而且使用git prune不会认为是
创建分支,在分支上添加内容
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15xiong@Surface-pro6 MINGW64 /c/Files/git-demo3 (master)
git checkout -b tmp
Switched to a new branch 'tmp'
xiong@Surface-pro6 MINGW64 /c/Files/git-demo3 (tmp)
echo 'tmp'>tmp.txt
xiong@Surface-pro6 MINGW64 /c/Files/git-demo3 (tmp)
ls
test.txt tmp.txt
xiong@Surface-pro6 MINGW64 /c/Files/git-demo3 (tmp)
git add tmp.txt
warning: LF will be replaced by CRLF in tmp.txt.
The file will have its original line endings in your working directory分析一次add的情况
切换到master分支
1
2
3
4
5
6
7
8
9
10
11
12xiong@Surface-pro6 MINGW64 /c/Files/git-demo3 (tmp)
git checkout master
Switched to branch 'master'
A tmp.txt
xiong@Surface-pro6 MINGW64 /c/Files/git-demo3 (master)
git prune -n
xiong@Surface-pro6 MINGW64 /c/Files/git-demo3 (master)
git fsck
Checking object directories: 100% (256/256), done.
Checking objects: 100% (3/3), done.切换到tmp分支
1
2
3
4
5
6
7xiong@Surface-pro6 MINGW64 /c/Files/git-demo3 (master)
git checkout tmp
Switched to branch 'tmp'
A tmp.txt
xiong@Surface-pro6 MINGW64 /c/Files/git-demo3 (tmp)
git prune -n对于只add过一次但还没提交的文件,系统不认为是悬空文件
分析add两次,提交一次的情况
修改tmp.txt文件,进行一次提交
1
2
3
4
5
6
7xiong@Surface-pro6 MINGW64 /c/Files/git-demo3 (tmp)
vim tmp.txt
xiong@Surface-pro6 MINGW64 /c/Files/git-demo3 (tmp)
git add tmp.txt
warning: LF will be replaced by CRLF in tmp.txt.
The file will have its original line endings in your working directory在tmp分支上查看悬空对象
1
2
3
4
5
6
7
8
9
10
11xiong@Surface-pro6 MINGW64 /c/Files/git-demo3 (tmp)
git commit -m '1st commit from tmp'
[tmp 1915cf6] 1st commit from tmp
1 file changed, 2 insertions(+)
create mode 100644 tmp.txt
xiong@Surface-pro6 MINGW64 /c/Files/git-demo3 (tmp)
git fsck
Checking object directories: 100% (256/256), done.
Checking objects: 100% (3/3), done.
dangling blob a9a5aecf429fd8a0d81fbd5fd37006bfa498d5c1切换到master分支上查看悬空对象
1
2
3
4
5
6
7
8
9xiong@Surface-pro6 MINGW64 /c/Files/git-demo3 (tmp)
git checkout master
Switched to branch 'master'
xiong@Surface-pro6 MINGW64 /c/Files/git-demo3 (master)
git fsck
Checking object directories: 100% (256/256), done.
Checking objects: 100% (3/3), done.
dangling blob a9a5aecf429fd8a0d81fbd5fd37006bfa498d5c1分支上的悬空对象,其他分支也能检测到
切换到master分支强制删除tmp
1
2
3xiong@Surface-pro6 MINGW64 /c/Files/git-demo3 (master)
git branch -D tmp
Deleted branch tmp (was 1915cf6).objects目录没有任何变化
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24xiong@SURFACE-PRO6 C:\Files\git-demo3
tree .git/objects /f
卷 Local Disk 的文件夹 PATH 列表
卷序列号为 C0000100 F296:2801
C:\FILES\GIT-DEMO3\.GIT\OBJECTS
├─0c
│ 190188dbbf78236873f4d98402eb35440cf292
│
├─19
│ 15cf671b63040967ff38cf434df3a6860da113
│
├─62
│ 189d1a10cc2a544c4e5b9c4aba9493cf5782dc
│
├─a9
│ a5aecf429fd8a0d81fbd5fd37006bfa498d5c1
│
├─info
│ commit-graph
│ packs
│
└─pack
pack-b9d4bdcbfa833a54a35bc737eaba5f5088f6d956.idx
pack-b9d4bdcbfa833a54a35bc737eaba5f5088f6d956.pack在此种情况下,tmp分支上的对象可以认为是垃圾对象
执行
git prune删除对象:不会认为tmp分支上的add(最后一次的)和commit是垃圾对象1
2xiong@Surface-pro6 MINGW64 /c/Files/git-demo3 (master)
git prune1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21xiong@SURFACE-PRO6 C:\Files\git-demo3
tree .git/objects /f
卷 Local Disk 的文件夹 PATH 列表
卷序列号为 C0000100 F296:2801
C:\FILES\GIT-DEMO3\.GIT\OBJECTS
├─0c
│ 190188dbbf78236873f4d98402eb35440cf292
│
├─19
│ 15cf671b63040967ff38cf434df3a6860da113
│
├─62
│ 189d1a10cc2a544c4e5b9c4aba9493cf5782dc
│
├─info
│ commit-graph
│ packs
│
└─pack
pack-b9d4bdcbfa833a54a35bc737eaba5f5088f6d956.idx
pack-b9d4bdcbfa833a54a35bc737eaba5f5088f6d956.pack只有一个之前被检测到的悬空对象被删除了
执行
git gc:不会认为tmp分支上的add(最后一次的)和commit是垃圾对象,并将其压缩到pack里1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19xiong@Surface-pro6 MINGW64 /c/Files/git-demo3 (master)
git gc
Enumerating objects: 6, done.
Counting objects: 100% (6/6), done.
Delta compression using up to 8 threads
Compressing objects: 100% (3/3), done.
Writing objects: 100% (6/6), done.
Total 6 (delta 0), reused 3 (delta 0), pack-reused 0
xiong@Surface-pro6 MINGW64 /c/Files/git-demo3 (master)
git verify-pack -v .git/objects/pack/pack-17c963e06e14119b3281aa3a1fa16ebbc8817341.idx
1915cf671b63040967ff38cf434df3a6860da113 commit 234 154 12
63a64804613dbfaa16cfc5c7fb320b501f539d75 commit 177 120 166
74ec2e70bd5e4936b3d076b469751e584f434a9a blob 12 15 286
85d321b0acc1f7618da3b8a24a51c743a0133932 tree 36 46 301
0c190188dbbf78236873f4d98402eb35440cf292 tree 71 74 347
62189d1a10cc2a544c4e5b9c4aba9493cf5782dc blob 8 15 421
non delta: 6 objects
.git/objects/pack/pack-17c963e06e14119b3281aa3a1fa16ebbc8817341.pack: ok
对于这种情况,使用下面的命令可以进行解决file - How to remove unused objects from a git repository? - Stack Overflow
1 | git -c gc.reflogExpire=0 -c gc.reflogExpireUnreachable=0 \ |
1 | xiong@Surface-pro6 MINGW64 /c/Files/git-demo3 (master) |
不仅经过压缩了的可以这样进行处理,未压缩的也可以
1 | xiong@Surface-pro6 MINGW64 /c/Files/git-demo3 (master) |
清理前查看objects文件夹
1 | tree .git/objects /f |
清理
1 | xiong@Surface-pro6 MINGW64 /c/Files/git-demo3 (master) |
清理后查看objects文件夹
1 | xiong@SURFACE-PRO6 C:\Files\git-demo3 |
13. fast forward合并

如果当前分支是在master上新建的,而且master分支并未再次进行commit,则满足fast forward的要求
将当前分支切换到master分支,再执行git merge 分支名进行分支合并,实际上只是做了一个指针的移动

测试
当前仓库只有一次提交,且指针指向master分支
1 | xiong@Surface-pro6 MINGW64 /c/Files/git-demo3 (master) |
基于当前分支,创建一个新的分支进行演示
1 | xiong@Surface-pro6 MINGW64 /c/Files/git-demo3 (master) |
在新分支上产生一次commit:执行完毕后新分支超前master分支一次提交
1 | xiong@Surface-pro6 MINGW64 /c/Files/git-demo3 (dev) |
切换到master分支,先查看.git文件,进行分支合并
1 | xiong@SURFACE-PRO6 C:\Files\git-demo3 |
1 | xiong@Surface-pro6 MINGW64 /c/Files/git-demo3 (master) |
Updating 63a6480..596b3cd:把指针从63a6480,指向596b3cd
合并后查看.git文件
1 | xiong@SURFACE-PRO6 C:\Files\git-demo3 |
分别查看HEAD与ORIG_HEAD
1 | xiong@Surface-pro6 MINGW64 /c/Files/git-demo3 (master) |
ORIG_HEAD指向前一次commit,git在进行版本控制时,认为merge是比较危险的操作,所以提供了上一次的HEAD指向,以便于进行回滚操作
回滚演示:将master回滚到未merge前的状态
1 | xiong@Surface-pro6 MINGW64 /c/Files/git-demo3 (master) |
在此种状态下不能立即切换到dev分支,需要先对当前回滚产生的test2.txt进行操作
1 | xiong@Surface-pro6 MINGW64 /c/Files/git-demo3 (master) |
14. 3 way merge
14.1 无冲突的merge
在开发时,如果master分支上有人进行了一次commit

在dev分支查看当前提交情况
1
2
3
4
5
6
7
8
9
10
11
12
13xiong@Surface-pro6 MINGW64 /c/Files/git-demo3 (dev)
git log
commit 596b3cd55b27dc3cb5f85c291f73ac8e367aa930 (HEAD -> dev)
Author: xiongzhuo <xiongzhuo@outlook.com>
Date: Mon Aug 23 13:38:02 2021 +0800
2nd commit
commit 63a64804613dbfaa16cfc5c7fb320b501f539d75 (master)
Author: xiongzhuo <xiongzhuo@outlook.com>
Date: Mon Aug 23 08:34:07 2021 +0800
1st commitdev超前于master分支一次提交
切换到master分支进行一次提交,模拟描述的情况
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31xiong@Surface-pro6 MINGW64 /c/Files/git-demo3 (dev)
git checkout master
Switched to branch 'master'
xiong@Surface-pro6 MINGW64 /c/Files/git-demo3 (master)
echo 'test3' > test3.txt
xiong@Surface-pro6 MINGW64 /c/Files/git-demo3 (master)
git add test3.txt
warning: LF will be replaced by CRLF in test3.txt.
The file will have its original line endings in your working directory
xiong@Surface-pro6 MINGW64 /c/Files/git-demo3 (master)
git commit -m '3rd commit'
[master ee44067] 3rd commit
1 file changed, 1 insertion(+)
create mode 100644 test3.txt
xiong@Surface-pro6 MINGW64 /c/Files/git-demo3 (master)
git log
commit ee44067f519231c20405f26c9a9fbef7c45e296a (HEAD -> master)
Author: xiongzhuo <xiongzhuo@outlook.com>
Date: Mon Aug 23 14:23:08 2021 +0800
3rd commit
commit 63a64804613dbfaa16cfc5c7fb320b501f539d75
Author: xiongzhuo <xiongzhuo@outlook.com>
Date: Mon Aug 23 08:34:07 2021 +0800
1st commit进行
git merge1
2
3
4
5
6xiong@Surface-pro6 MINGW64 /c/Files/git-demo3 (master)
git merge dev
Merge made by the 'recursive' strategy.
test2.txt | 1 +
1 file changed, 1 insertion(+)
create mode 100644 test2.txt此时会进入一个编辑器,要求输入commit信息

查看当前提交记录
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26xiong@Surface-pro6 MINGW64 /c/Files/git-demo3 (master)
git log
commit 2040a9926e6c3f6647fbae96b067fa9ac4d1caac (HEAD -> master)
Merge: ee44067 596b3cd
Author: xiongzhuo <xiongzhuo@outlook.com>
Date: Mon Aug 23 14:31:42 2021 +0800
Merge branch 'dev'
commit ee44067f519231c20405f26c9a9fbef7c45e296a
Author: xiongzhuo <xiongzhuo@outlook.com>
Date: Mon Aug 23 14:23:08 2021 +0800
3rd commit
commit 596b3cd55b27dc3cb5f85c291f73ac8e367aa930 (dev)
Author: xiongzhuo <xiongzhuo@outlook.com>
Date: Mon Aug 23 13:38:02 2021 +0800
2nd commit
commit 63a64804613dbfaa16cfc5c7fb320b501f539d75
Author: xiongzhuo <xiongzhuo@outlook.com>
Date: Mon Aug 23 08:34:07 2021 +0800
1st commit此时commit状态如下:新的merge commit比较特殊,指向两个parent

验证如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21xiong@Surface-pro6 MINGW64 /c/Files/git-demo3 (master)
git cat-file -p 2040a9
tree 1838144278c4bdebda77473c8b269f173d7c5122
parent ee44067f519231c20405f26c9a9fbef7c45e296a
parent 596b3cd55b27dc3cb5f85c291f73ac8e367aa930
author xiongzhuo <xiongzhuo@outlook.com> 1629700302 +0800
committer xiongzhuo <xiongzhuo@outlook.com> 1629700302 +0800
Merge branch 'dev'
xiong@Surface-pro6 MINGW64 /c/Files/git-demo3 (master)
cat .git/refs/heads/dev
596b3cd55b27dc3cb5f85c291f73ac8e367aa930
xiong@Surface-pro6 MINGW64 /c/Files/git-demo3 (master)
cat .git/ORIG_HEAD
ee44067f519231c20405f26c9a9fbef7c45e296a
xiong@Surface-pro6 MINGW64 /c/Files/git-demo3 (master)
cat .git/refs/heads/master
2040a9926e6c3f6647fbae96b067fa9ac4d1caac此时状态

14.2 带冲突的3 way merge
上述merge时所修改的文件不是同一个,如果修改的是同一个文件,则需要解决冲突

初始化一个新的代码仓库进行测试
1 | xiong@Surface-pro6 MINGW64 /c/Files/git-demo4 |
查看master分支上的提交记录
1 | xiong@Surface-pro6 MINGW64 /c/Files/git-demo4 (master) |
切换到dev分支查看提交记录
1 | xiong@Surface-pro6 MINGW64 /c/Files/git-demo4 (master) |
执行git merge dev
1 | xiong@Surface-pro6 MINGW64 /c/Files/git-demo4 (master) |
Automatic merge failed; fix conflicts and then commit the result.:自动merge失败,解决冲突之后提交结果
查看当前git状态
1 | xiong@Surface-pro6 MINGW64 /c/Files/git-demo4 (master|MERGING) |
指出test.txt被共同修改了
查看文件内容
1 | xiong@Surface-pro6 MINGW64 /c/Files/git-demo4 (master|MERGING) |
列举出来了二者冲突的地方
查看当前索引区文件
1 | xiong@Surface-pro6 MINGW64 /c/Files/git-demo4 (master|MERGING) |
列出了test.txt的三个版本,查看这三个文件内容
1 | xiong@Surface-pro6 MINGW64 /c/Files/git-demo4 (master|MERGING) |
通过编辑器打开文件,解决冲突
1 | xiong@Surface-pro6 MINGW64 /c/Files/git-demo4 (master|MERGING) |
将修改添加到索引区
1 | xiong@Surface-pro6 MINGW64 /c/Files/git-demo4 (master|MERGING) |
修改完后此时git仍然显示test.txt文件是共同修改状态,我们需要进行add和commit就可以解决,而且此时索引区的文件又变回了一个,查看内容,正是我们修改过后的。表示此时冲突已经解决
进行commit
1 | xiong@Surface-pro6 MINGW64 /c/Files/git-demo4 (master|MERGING) |
提交完之后,(master|MERGING)变成了(master),完成了所有操作,结果也和普通的3way merge一样
16. git rebase

当我们遇到需要分支合并的时候,而且此时想让合并的分支呈线性,可以再分支上使用git reabse master,将master分支上的最近一次提交同步到当前分支上,然后系统会改写分支上的commit,使分支上的commit在master之后,最后在使用git merge的时候就使得提交呈现出线性。不过要注意这种操作不适合团队开发使用,因为容易涉及到带冲突合并的问题。
17. 标签tag
标签在创建时,指向的是当前所在分支的最新一次commit
创建tag
- git tag <tag name>:创建一个轻量级的tag(i.e. git tag v1.0)
- git tag -a <tag name> -m <tag message>:创建一个拥有关联元数据的注解tag( email,date,etc…)(i.e. git tag -a v1.0 -m “version” )
- git tag -a <tag name> <commit SHA1 value> :为以前的commit生成一个注解tag(i.e. git tag -a v1.0 c638404ba9aedab9251326c3418b8948ad9344f4)
tag列表
git tag
删除tag
git tag -d <tag name> (i.e. git tag -d v1.0)
①初始化代码仓库,为master分支的最近一次commit使用git tag <tag name>创建tag
1 | xiong@Surface-pro6 MINGW64 /c/Files/git-demo5 |
1 | xiong@SURFACE-PRO6 C:\Files\git-demo5 |
查看tag内容
1 | xiong@Surface-pro6 MINGW64 /c/Files/git-demo5 (master) |
删除tag
1 | xiong@Surface-pro6 MINGW64 /c/Files/git-demo5 (master) |
1 | xiong@SURFACE-PRO6 C:\Files\git-demo5 |
②使用git tag -a <tag name> -m <tag message>创建tag
1 | xiong@Surface-pro6 MINGW64 /c/Files/git-demo5 (master) |
查看objects
1 | xiong@SURFACE-PRO6 C:\Files\git-demo5 |
查看新增objects文件类型和文件内容
1 | xiong@Surface-pro6 MINGW64 /c/Files/git-demo5 (master) |
查看refs
1 | xiong@SURFACE-PRO6 C:\Files\git-demo5 |
删除tag
1 | xiong@Surface-pro6 MINGW64 /c/Files/git-demo5 (master) |
查看refs,标签被删除
1 | xiong@SURFACE-PRO6 C:\Files\git-demo5 |
查看objects,tag对象未被删除
1 | xiong@SURFACE-PRO6 C:\Files\git-demo5 |
③使用git tag -a <tag name> <commit SHA1 value>创建tag
1 | xiong@Surface-pro6 MINGW64 /c/Files/git-demo5 (master) |
查看objects
1 | xiong@SURFACE-PRO6 C:\Files\git-demo5 |
虽然名字一样,但是并未使用之前的tag对象,因为在生成tag对象时里面有时间戳
使用git fsck可以检测出垃圾tag
1 | xiong@Surface-pro6 MINGW64 /c/Files/git-demo5 (master) |
使用git prune 可以进行垃圾清理
1 | xiong@Surface-pro6 MINGW64 /c/Files/git-demo5 (master) |
1 | xiong@SURFACE-PRO6 C:\Files\git-demo5 |
18. 本地分支和远程分支
新建文件夹,将远程仓库克隆到本地