git原理及常见使用方法
Git 原理入门-来自阮一峰
即使天天使用它,很多人也未必了解它的原理。Git 为什么可以管理版本?git add、git commit这些基本命令,到底在做什么,你说得清楚吗?
这篇文章用一个实例,解释 Git 的运行过程,帮助你理解 Git 的原理。
$ mkdir git-demo-project
$ cd git-demo-project
我们打算对该项目进行版本管理,第一件事就是使用git init命令,进行初始化。
$ git init
git init命令只做一件事,就是在项目根目录下创建一个.git子目录,用来保存版本信息。
$ ls .gitbranches/
config
description
HEAD
hooks/
info/
objects/
refs/
上面命令显示,.git内部还有一些子目录,这里先不解释它们的含义。
二、保存对象
$ touch test.txt
然后,把这个文件加入 Git 仓库,也就是为test.txt的当前内容创建一个副本。
$ git hash-object -w test.txte69de29bb2d1d6434b8b29ae775ad8c2e48c5391
上面代码中,git hash-object命令把test.txt的当前内容压缩成二进制文件,存入 Git。压缩后的二进制文件,称为一个 Git 对象,保存在.git/objects目录。
这个命令还会计算当前内容的 SHA1 哈希值(长度40的字符串),作为该对象的文件名。下面看一下这个新生成的 Git 对象文件。
$ ls -R .git/objects.git/objects/e6:
9de29bb2d1d6434b8b29ae775ad8c2e48c5391
上面代码可以看到,.git/objects下面多了一个子目录,目录名是哈希值的前2个字符,该子目录下面有一个文件,文件名是哈希值的后38个字符。
$ cat .git/objects/e6/9de29bb2d1d6434b8b29ae775ad8c2e48c5391
上面代码输出的文件内容,都是一些二进制字符。你可能会问,test.txt是一个空文件,为什么会有内容?这是因为二进制对象里面还保存一些元数据。
如果想看该文件原始的文本内容,要用git cat-file命令。
$ git cat-file -p e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
因为原始文件是空文件,所以上面的命令什么也看不到。现在向test.txt写入一些内容。
$ echo 'hello world' > test.txt
$ git hash-object -w test.txt3b18e512dba79e4c8300dd08aeb37f8e728b8dad
$ git cat-file -p 3b18e512dba79e4c8300dd08aeb37f8e728b8dadhello world
git update-index命令用于在暂存区记录一个发生变动的文件。
$ git update-index --add --cacheinfo 100644 \
3b18e512dba79e4c8300dd08aeb37f8e728b8dad test.txt
上面命令向暂存区写入文件名test.txt、二进制对象名(哈希值)和文件权限。
$ git ls-files --stage100644 3b18e512dba79e4c8300dd08aeb37f8e728b8dad 0 test.txt
上面代码表示,暂存区现在只有一个文件test.txt,以及它的二进制对象名和权限。知道了二进制对象名,就可以在.git/objects子目录里面读出这个文件的内容。
$ git status要提交的变更:新文件: test.txt
上面代码表示,暂存区里面只有一个新文件test.txt,等待写入历史。
四、git add 命令
上面两步(保存对象和更新暂存区),如果每个文件都做一遍,那是很麻烦的。Git 提供了git add命令简化操作。
$ git add --all
上面命令相当于,对当前项目所有变动的文件,执行前面的两步操作。
五、commit 的概念
暂存区保留本次变动的文件信息,等到修改了差不多了,就要把这些信息写入历史,这就相当于生成了当前项目的一个快照(snapshot)。
项目的历史就是由不同时点的快照构成。Git 可以将项目恢复到任意一个快照。快照在 Git 里面有一个专门名词,叫做 commit,生成快照又称为完成一次提交。
下文所有提到"快照"的地方,指的就是 commit。
六、完成提交
首先,设置一下用户名和 Email,保存快照的时候,会记录是谁提交的。
$ git config user.name "用户名"
$ git config user.email "Email 地址"
接下来,要保存当前的目录结构。前面保存对象的时候,只是保存单个文件,并没有记录文件之间的目录关系(哪个文件在哪里)。
git write-tree命令用来将当前的目录结构,生成一个 Git 对象。
$ git write-treec3b8bb102afeca86037d5b5dd89ceeb0090eae9d
上面代码中,目录结构也是作为二进制对象保存的,也保存在.git/objects目录里面,对象名就是哈希值。
$ git cat-file -p c3b8bb102afeca86037d5b5dd89ceeb0090eae9d100644 blob 3b18e512dba79e4c8300dd08aeb37f8e728b8dad test.txt
所谓快照,就是保存当前的目录结构,以及每个文件对应的二进制对象。上一个操作,目录结构已经保存好了,现在需要将这个目录结构与一些元数据一起写入版本历史。
git commit-tree命令用于将目录树对象写入版本历史。
$ echo "first commit" | git commit-tree c3b8bb102afeca86037d5b5dd89ceeb0090eae9dc9053865e9dff393fd2f7a92a18f9bd7f2caa7fa
$ git cat-file -p c9053865e9dff393fd2f7a92a18f9bd7f2caa7fatree c3b8bb102afeca86037d5b5dd89ceeb0090eae9d
author ruanyf 1538889134 +0800
committer ruanyf 1538889134 +0800first commit
上面代码中,输出结果的第一行是本次快照对应的目录树对象(tree),第二行和第三行是作者和提交人信息,最后是提交说明。
$ git log --stat c9053865e9dff393fd2f7a92a18f9bd7f2caa7facommit c9053865e9dff393fd2f7a92a18f9bd7f2caa7fa
Author: ruanyf
Date: Sun Oct 7 13:12:14 2018 +0800first committest.txt | 1 +1 file changed, 1 insertion(+)
Git 提供了git commit命令,简化提交操作。保存进暂存区以后,只要git commit一个命令,就同时提交目录结构和说明,生成快照。
$ git commit -m "first commit"
$ git checkout c9053865e9dff393fd2f7a92a18f9bd7f2caa7fa
$ git show c9053865e9dff393fd2f7a92a18f9bd7f2caa7fa
到了这一步,还没完。如果这时用git log命令查看整个版本历史,你看不到新生成的快照。
$ git log
上面命令没有任何输出,这是为什么呢?快照明明已经写入历史了。
原来git log命令只显示当前分支的变动,虽然我们前面已经提交了快照,但是还没有记录这个快照属于哪个分支。
用户可以对任意快照新建指针。比如,新建一个 fix-typo 分支,就是创建一个叫做 fix-typo 的指针,指向某个快照。所以,Git 新建分支特别容易,成本极低。
Git 有一个特殊指针HEAD, 总是指向当前分支的最近一次快照。另外,Git 还提供简写方式,HEAD^指向 HEAD的前一个快照(父节点),HEAD~6则是HEAD之前的第6个快照。
每一个分支指针都是一个文本文件,保存在.git/refs/heads/目录,该文件的内容就是它所指向的快照的二进制对象名(哈希值)。
九、更新分支
下面演示更新分支是怎么回事。首先,修改一下test.txt。
$ echo "hello world again" > test.txt
$ git hash-object -w test.txtc90c5155ccd6661aed956510f5bd57828eec9ddb
$ git update-index test.txt
$ git write-tree1552fd52bc14497c11313aa91547255c95728f37
$ echo "second commit" | git commit-tree 1552fd52bc14497c11313aa91547255c95728f37 -p c9053865e9dff393fd2f7a92a18f9bd7f2caa7fa785f188674ef3c6ddc5b516307884e1d551f53ca
上面代码中,git commit-tree的-p参数用来指定父节点,也就是本次快照所基于的快照。
现在,我们把本次快照的哈希值,写入.git/refs/heads/master文件,这样就使得master指针指向这个快照。
$ echo 785f188674ef3c6ddc5b516307884e1d551f53ca > .git/refs/heads/master
$ git logcommit 785f188674ef3c6ddc5b516307884e1d551f53ca (HEAD -> master)
Author: ruanyf
Date: Sun Oct 7 13:38:00 2018 +0800second commitcommit c9053865e9dff393fd2f7a92a18f9bd7f2caa7fa
Author: ruanyf
Date: Sun Oct 7 13:12:14 2018 +0800first commit
查找HEAD指针对应的分支,本例是master找到master指针指向的快照,本例是785f188674ef3c6ddc5b516307884e1d551f53ca找到父节点(前一个快照)c9053865e9dff393fd2f7a92a18f9bd7f2caa7fa以此类推,显示当前分支的所有快照
最后,补充一点。前面说过,分支指针是动态的。原因在于,下面三个命令会自动改写分支指针。
git commit:当前分支指针移向新创建的快照。git pull:当前分支与远程分支合并后,指针指向新创建的快照。git reset [commit_sha]:当前分支指针重置为指定快照。
How does git work internally, Shalitha Suranga
Git 常见使用方法
待续。。
git原理及常见使用方法相关推荐
- Git:代码冲突常见解决方法
Git:代码冲突常见解决方法 参考文章: (1)Git:代码冲突常见解决方法 (2)https://www.cnblogs.com/zhujiabin/p/10270181.html 备忘一下.
- 并发编程之二:线程创建方法、运行原理、常见方法(sleep,join,interrupt,park,守护线程等)
线程创建方法.运行原理.常见方法 线程的创建方法 继承Thread 实现Runnable FutureTask 线程的运行原理 栈与栈帧 线程运行情况 线程的上下文切换(Thread Context ...
- git常见问题解决方法总结
git常见问题解决方法总结 fatal: Could not read from remote repository 大概意思是:不能从远程存储库读取. 一般我们在使用git push -u orig ...
- Git 原理详解及实用指南
Git 原理详解及实用指南 什么是版本控制系统(VCS) 很多人认为 Git 难以理解的第一个门槛在于:所谓的「Git 是一个分布式版本控制系统」这句话的具体含义不够清楚.其实分布式版本控制系统(Di ...
- 图解git原理与日常实用指南
缘起 读了"扔物线"老师的小册<Git 原理详解及实用指南>感觉收获良多,于是想写点东西做一个总结,即加深自己的印象也希望能给社区小伙伴一点帮助,写的不对的地方还请多多 ...
- Paillier半同态加密:原理、高效实现方法和应用
简介: <数据安全法>已于9月1日起正式实施,两个月后<个人信息保护法>也将开始施行,意味着数据安全和隐私保护方面的监管将会在年内陆续到位.在合规收紧大背景下,"数据 ...
- git 原理详解及实用指南_如何编写良好的提交消息:实用的Git指南
git 原理详解及实用指南 To create a useful revision history, teams should first agree on a commit message conv ...
- git原理学习记录:从基本指令到背后原理,实现一个简单的git
一开始我还担心 git 的原理会不会很难懂,但在阅读了官方文档后我发现其实并不难懂,似乎可以动手实现一个简单的 git,于是就有了下面这篇学习记录. 本文的叙述思路参照了官方文档Book的原理介绍部分 ...
- Paillier 半同态加密:原理、高效实现方法和应用
一 简介 1 背景 <数据安全法>已于9月1日起正式实施,两个月后<个人信息保护法>也将开始施行,意味着数据安全和隐私保护方面的监管将会在年内陆续到位. 在合规收紧大背景下,& ...
最新文章
- OpenCV中的特征匹配+单应性以查找对象
- python使用matplotlib可视化棉签图、棉棒图(stem plot)、展示离散而有序的数据
- Vim as Python IDE on windows(转)
- 这么烂的游戏也能卖2000万吗?
- 3.JAVA基础复习——JAVA中的类与对象
- 在Java 8中使用Stream API解析文件
- 关于在vSphere环境中,安装WindowsServer2008_R2_x64系统,分区格式为GPT,隐藏分区为200M方法心得
- linux ssh 查看vg,linux SSH证书登录
- linux系统硬盘数据恢复软件下载,R-Linux|R-Linux(linux数据恢复软件)下载 v5.1中文免费版 - 121下载站...
- python 直线检测_python hough变换检测直线的实现方法
- Word多级标题测试
- hp linux 禁用u盘启动项,惠普台式机UEFI BIOS设置U盘启动
- (毕业设计资料)基于单片机51单片机智能药盒控制系统设计
- 网络基础虚拟化VRRP/MSTP冗余技术
- BetterScroll 2.0网络数据过慢,不能滚动问题
- 处女座和小姐姐(模拟)
- 初学EGE图形库(零)---从零开始CodeBlocks安装配置使用EGE图形库
- #数据结构:家谱管理
- JavaFX --- 标签、文本框、密码框、下拉框、按钮、单选按钮、复选框
- 7-1 厘米换算英尺英寸(15 分)
热门文章
- 2022-2028年中国铪行业市场研究及前瞻分析报告
- etcd 笔记(05)— etcd 代码结构、各模块功能、整体架构、各模块之间的交互、请求和应答流程
- 分享2020 几个好用的ip地址归属地查询
- SpringCloud Alibaba微服务实战(七) - 路由网关(Gateway)全局过滤
- 解决nginx负载均衡的session共享问题
- tensor和模型 保存与加载 PyTorch
- torch学习笔记(二) nn类结构-Linear
- LeetCode简单题之解码字母到整数映射
- 全文翻译(四) TVM An Automated End-to-End Optimizing Compiler
- Vitis-AI集成