引言

Git是工作中最常用的版本控制工具,本文中将介绍其常用的命令。

根据作用的不同,可以分为基本命令、撤销命令、合并命令与远程仓库命令,下面将依次介绍这些命令。

基本原理

git 中提供了底层api供我们直接对底层数据结构进行调用,其中git cat-file [-t] [-p] hashcode,其中-t可以查看hash值对应文件的类型,-p可以查看hash之对应的内容

基本对象

在最初的版本里实际上只有3种对象,分别是blob,tree和changeset(后续被改名为commit).本文主要对这三种对象进行介绍。基本的对象有tag域与binary data域。

Blob

在blob对象中,其tag的取值为blob,并在binary data域中存储了文件的内容,是最简单的object。但并不会保存文件名相关的信息。那么在一个工程项目中,我们有时候仅会对文件的名字进行改动,这时候则需要引出tree对象对这一变化进行追踪。

tree

tree的tag值为tree,binary data中维护了一个list。list的每一个item可以是一个tree对象,也可以是一个blob对象。 在每一个item中,有如下的属性:

  • 权限和类型
  • 路径
  • 对象的sha1(类似于指针)

    从这个角度来看,tree的list中既可以引用blob对象,也可以引用tree对象,循环往复,构成一颗文件结构树。

    tree结构图[1]

利用tree与blob进行项目的追踪与维护

我们知道,若文件内容发生变化,则会生成新的blob对象与新的sha1值。对于tree对象,我们使用sha1值作为对blob对象的引用,那么该目录中的文件内容发生变化而引起对应的blob对象发生变化是,会导致tree维护的list中的内容发生变化,那么tree本身的sha1值也会发生变化。这就意味着,我们需要生成一个新的tree对象,来维护这一变化。

举个例子

对于如下结构的目录:

.

├── foo

│ └── a.txt

└── b.txt

如果我们将a.txt中的内容从"111"修改为"222", 那么整体的tree将会有如下结构:



可以看到新内容与旧内容分别维护了各自的根目录对应的tree,并复用没有修改内容的blob节点。

commit

仅靠tree对象与blob对象并不能记录与提交版本相关的信息。为了回溯任意一个版本,我们还需要一个对象对版本的提交信息进行维护——commit对象。

commit对象的tag是commit,binaray data域有以下内容:

  • tree相关的信息
  • parent
  • author
  • committer

    其中,当我们提交一个新的commit时,会有一个对应的tree对象的与之关联。parent的个数可以是0个或者多个,维护着到上一个commit的sha1指针。可以通过该指针回溯到任意一个历史版本。从这个角度看,我们可以将git理解为基于一个key-value的数据库与默克尔树形成的有向无环图(DAG)的存储系统[3]。

tag

tag代表将分支永久化,生成tag后,这个tag对应的内容将永不可变,所以一般应用或者软件版本的发布一般用tag。

索引区

在我们的tree结构中,如果要访问一个具体的blob对象,需要使用深度优先遍历,通过路径上的信息来得到最终blob的完整路径。如果我们想要对比不同commit版本的文件之间的差异的话,就需要对两棵不同版本的tree进行深度遍历,当树很深时会涉及大量磁盘i/o。

为了提高i/o的速度,可以引入一个缓存,来提高文件读取的速度,这就是暂存区。通常相关的数据存储在./git/index。git使用mmap技术,访问文件内容。这里的文件内容指的是一系列entry对象,每一个entry对象中维护了对应的blob对象的映射与完整路径与其他相关的信息,entry对象在内存中按完整路径进行升序排列。这样,在后续的比较中就可以使用二分查找快速定位到相同文件名的不同版本完整地址,并进行比较。


命令

1. 基本命令

1.1 git add

当输入git add命令后,git会将文件生成对应的blob文件,并保存在git仓库中。但是并没有在tree上进行相应的结构映射,而只是在索引区建立了直接的索引。而tree结构的建立,需要等到commit命令才执行。

1.2 git commit

git commit后就会生成本次版本的对应树结构,涉及到一系列tree对象与commit对象的生成。(注意,blob对象在git add时就已经生成)

1.3 git checkout

该命令根据参数的不同,有许多效果。其主要的作用是在不同的分支之间切换。

查看代码[4]
git checkout # 列出本地所有分支
git checkout [<branch>] # 切换到该分支
git checkout -b [<branch>] # 创建并切换到该分支
git checkout -d [<branch>] # 删除该分支
-f # 强制执行

其余的一些命令参数如--merge,可以通过与其他命令的组合来实现,对结果把控更可靠。

2. 撤销命令

git reset

这条命令指定退回到某一个版本的提交。

查看代码
--mixed # 工作区不变,其余内容退回到指定版本
-hard # 所有内容退回到指定版本
-soft # 回退到指定版本
该命令后可以指定文件名,用于对指定文件进行版本回退
需要谨慎使用 --hard参数,该参数会删除回退版本后的commit版本。另外永远不要将已经push并merge到origin中的branch的内容进行回退,否则会导致本地仓库的不同步。如果非要使用,后续则需要git push -f进行强制推送

git revert

其用法与 git reset类似,但是与reset不同的是,其不会删除一些历史commit记录,而是使用创建一个新的commit的方式来达到撤销历史修改的记录。对于一些已经push或产生其他副作用的修改,最好使用revert方式进行撤销操作。而reset则多用于本地的撤销修改。注:revert的commitid选则回退版本后一个的commitid。

关于Revert功能的一个小插曲

3. 合并命令

git merge

会在两个parent commit上创建一个新的分支,若不存在冲突,则直接fast-forward merge。

查看代码
git merge [<branch>] # 将指定的分支合并到当前分支上

若合并产生冲突,会在日志中提示,并且在合并操作产生的commit中,会标出冲突的部位。当我们以手动的方式修改完冲突后,使用git add 通知git已完成冲突合并,并用commit完成这次merge(此时会自动带上 merge的message)

git rebase

从字面上来理解,是为当前分支重新确定一个基。达到的效果与merge类似,但是其commit的拓扑结构是不一致的。当执行完rebase后,是将当前分支以“类似”嫁接的形式,嫁接到某个指定的分支上,而不是类似于merge,将两个分支合并起来。

举个例子

当前我们的分支结构如下:



我们正在dev分支上,想将dev的修改记录应用到master分支上,但又不想以merge的方式进行。此时我们可以使用rebase,为dev分支重新确定一个基。执行完git rebase master后,效果如下:



完成了类似嫁接的操作, 将dev的原始分叉点重新定位在master分支的最新的commit上,并生成了与dev分支长度相同的新的一系列commit。

4. 远程仓库命令

git fetch

该命令会在本地仓库中更新所有在远程端被追踪的分支,并用灰色的标记来标记这些属于remote的分支

举个例子

远程与本地分支的原始状态



执行完git fetch后本地仓库的状态:

git pull

该命令相当于一条组合命令,在默认的参数下相当于git fetch + git merge [<remote_branch>],当然我们可以指定参数git>],当然我们可以指定参数git pull --rebase,那么就会使用git rebase来替代第二条命令。注意,默认只会将当前分支对应的远程分支合并进来。

举个例子

原始状态



执行完git pull

git push

该命令会将本地分支的内容推送到对应的远程分支上。从理论上来讲,所有的push操作都应该进行fast-forward merge,若仍存在一些不同则会发生reject错误。遇到这种情况时,通常需要先将远程的内容pull到本地进行合并后,再进行push。

参考

[1]Git Internals

[2]Explain Git with D3 (onlywei.github.io)

[3]这才是Git原理

[4]Git-SCM

[Git][基本原理与命令]的更多相关文章

  1. 【原理、命令】Git基本原理、与Svn的区别、命令

    一.Git是什么? Git是目前世界上最先进的分布式版本控制系统.工作原理 / 流程:Workspace:工作区Index / Stage:暂存区Repository:仓库区(或本地仓库)Remote ...

  2. Git 基本原理与经常使用命令

    平时使用过两种版本号控制软件 SVN 和 Git,平心而论,假设纯粹自己使用,那么绝对 Git 更加适合,本地库.远程库.离线工作.强大而灵活的分支.大名鼎鼎的Github, 这些都是选择 Git 的 ...

  3. git基本原理

    git基本原理 一.总结 一句话总结:把原理那张图图背下来 1.git中的四大区,除了远程仓库和本地仓库,剩下两个是什么? 解答:工作区和暂存区. 2.git中的四大区(例如远程仓库和本地仓库),他们 ...

  4. GIT 版本控制常用命令学习汇总

    GIT 版本控制常用命令汇总 git version 查看当前git版本信息 git help 获取全部命令帮助信息 git help <command> 获取指定命令帮助信息 git c ...

  5. git的一些命令行

    以下代码均在命令行中执行:在目标文件夹目录下: 1.初始化一个Git仓库,使用git init命令. 2.添加文件到Git仓库,分两步: 第一步,使用命令git add <file>,注意 ...

  6. git log 常用命令及技巧

    git log常用命令以及技巧 1.git log 如果不带任何参数,它会列出所有历史记录,最近的排在最上方,显示提交对象的哈希值,作者.提交日期.和提交说明.如果记录过多,则按Page Up.Pag ...

  7. Git基本常用命令

    Git基本常用命令如下: mkdir: XX (创建一个空目录 XX指目录名) pwd: 显示当前目录的路径. git init 把当前的目录变成可以管理的git仓库,生成隐藏.git文件. git ...

  8. git workflow常用命令

    git init git status git add readme.txt git add --all         Adds all new or modified files git comm ...

  9. git的一些命令

    因为项目的原因,大家把项目托管到git上,然后我不会,队友就传了一个廖雪峰的git教程,讲的很详细,不会用git的同学,可以在http://pan.baidu.com/s/1pKizolP上下载,这是 ...

  10. 关于Git的stash命令

    add 添加新文件到 Git 代码仓库的索引中 $ git add filename mv 移动或重命名文件 $ git mv old-filename new-filename rm 从工作目录和 ...

随机推荐

  1. python调用imgkit将html转图片pdf问题实例wkhtmltox

    wkhtmltox的下载地址:https://wkhtmltopdf.org/downloads.html 或者:https://github.com/wkhtmltopdf/wkhtmltopdf ...

  2. ESP8266 + mg90s(舵机)

    ESP8266+mg90s(舵机) 准备阶段 ESP8266(nodeMcu) MG90S(舵机) 面包板 线3 连线 ESP8266 MG90S(舵机) GND 棕色 VCC 红色 模拟引脚 橙色 ...

  3. 3.13 Linux建立软硬链接文件(ln命令)

    如果要想说清楚 ln 命令,则必须先解释下 ext 文件系统(Linux 文件系统)是如何工作的.我们在前面讲解了分区的格式化就是写入文件系统,而我们的 Linux 目前使用的是 ext4 文件系统. ...

  4. debian大便系统配置国内软件源

    本例在debian:buster-slim docker镜像中实验通过 1.启动docker实例 docker run -it --name debian debian:buster-slim bas ...

  5. 大便系统怎样安装RPM包

    alien包转换工具 如果我们有很喜欢的RPM包,而又没有deb版本. 怎么办~? 可以同过alien来转换或者直接安装,这个小家伙可是个很方便的东西! 基本命令如下: 首先通过apt-get ins ...

  6. vue通过ollama接口调用开源模型

    先展示下最终效果: 第一步:先安装ollama,并配置对应的开源大模型. 安装步骤可以查看上一篇博客: ollama搭建本地ai大模型并应用调用  第二步:需要注意两个配置,页面才可以调用 1)OLL ...

  7. Qml 中的那些坑(七)---ComboBox嵌入Popup时,滚动内容超过其可见区域不会关闭ComboBox弹窗

    [写在前面] 最近在写信息提交 ( 表单 ) 的窗口时发现一个奇怪的 BUG: 其代码如下: import QtQuick 2.15 import QtQuick.Controls 2.15 impo ...

  8. HAR文件

    简介 HAR(HTTP Archive format),是一种或 JSON 格式的存档格式文件,通用扩展名为 .har.Web 浏览器可以使用该格式导出有关其加载的网页的详细性能数据. 使用场景 在开 ...

  9. Jenkins篇-权限管理

    我使用 权限管理插件是Role Strategy Plugin,他可以对构建的项目进行授权管理,让不同的用户管理不同的项目,将不同环境的权限进行区分 1)安装插件 系统管理>插件管理查找Role ...

  10. 关于《完全手册Excel VBA典型实例大全——通过368个例子掌握》随书样例的下载

    按照早先下载的电子教程查看和编写vba,有些例子使用运行错误,想着看看原始文件.容易看到,网上有提供的doc或者pdf文档,都不完整,可能是{完全手册Excel_VBA典型实例大全:通过368个例子掌 ...