前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Git汇总--对象及版本库存储

Git汇总--对象及版本库存储

作者头像
奋飛
发布2021-08-31 17:03:28
2560
发布2021-08-31 17:03:28
举报
文章被收录于专栏:Super 前端Super 前端

下述内容为团队内部分享整理所得,实用性较强,整体性偏差! PS:关于完整的Git内容,请参照之前发表过一系列文章,详见:Git Pro深入浅出(一)Git Pro深入浅出(二)Git Pro深入浅出(三) 推荐两个地址:ProGitGotGit

阅读完内容,你会很快的解决下面问题,并了解其底层原理。

问题1:如何丢弃本地工作区修改的内容?

代码语言:javascript
复制
$ git checkout -- <filename>

问题2:如何丢弃本地工作区和暂存区修改的内容?

代码语言:javascript
复制
$ git checkout HEAD <filename>

问题3:误删了文件且已经提交推送到远程仓库,如何恢复?

代码语言:javascript
复制
# 查看远程前一次提交的文件树 支持管道过滤 | grep 
$ git ls-files --with-tree=origin/HEAD^
# 查看前一次提交的指定文件内容 > welcome.txt
$ git cat-file -p origin/HEAD^:<filename>
# 当然,也可以采用reflog形式

问题4:如何忽略某文件?如何只让其本地生效?

.git/info/exclude中配置

简介

Git作者Linus Torvalds,其是一款分布式版本控制系统。

  • CVS:集中式版本控制系统。CVS采用客户端/服务器架构设计,版本库位于服务器端,实际上就是一个RCS文件容器。每一个RCS文件以“.v”作为文件名后缀,用于保存对应文件的历次更改历史。RCS文件中只保留一个版本的完全拷贝,其他历次更改仅将差异存储其中,使得存储变得更加高效。每个文件都拥有各自独立的版本号。
  • SVN:集中式版本控制系统。拥有全局版本号,每提交一次,SVN的版本号就会自动加一。利用轻量级拷贝,SVN在不同的名字空间下创建不同的目录实现里程碑和分支的创建,轻松地解决了CVS中存在的里程碑、分支创建速度慢又不可见的问题。SVN还有一个突破,就是在工作区跟踪目录(.svn目录)下为当前目录中的每一个文件都保存一份冗余的原始拷贝(工作区的根目录和每一个子目录下都有一个.svn目录)。这样做的好处一个是提高了网络的效率,在提交时仅传输变更差异,另外一个好处是部分操作不再需要网络连接,如本地修改的差异比较,以及本地更改的回退等。
  • Git:分布式版本控制系统。每个人都拥有一个完整的版本库。分布式版本控制系统的几乎所有操作包括查看提交日志、提交、创建里程碑和分支、合并分支、回退等都直接在本地完成而不需要网络连接。协同工作模型(版本库间推送、拉回,及补丁文件传送等)让开源项目的参与度有爆发式增长。
git.png
git.png

Git对象

git init 会创建一个 .git 目录。这个目录包含了几乎所有 Git 存储和操作的对象。 如若想备份或复制一个版本库,只需把这个目录拷贝至另一处即可。

代码语言:javascript
复制
$ ll .git
-rw-r--r--    1 ligang  staff     6B 11  1 10:13 COMMIT_EDITMSG
-rw-r--r--    1 ligang  staff   212B 10 31 10:02 FETCH_HEAD
-rw-r--r--    1 ligang  staff    23B  8 21 15:23 HEAD
-rw-r--r--    1 ligang  staff    41B 10 31 10:02 ORIG_HEAD
drwxr-xr-x    2 ligang  staff    64B  8 15  2017 branches
-rw-r--r--    1 ligang  staff   311B  8 15  2017 config
-rw-r--r--    1 ligang  staff    73B  8 15  2017 description
drwxr-xr-x   31 ligang  staff   992B  5 10 14:44 hooks
-rw-r--r--    1 ligang  staff   6.9M 11  1 10:13 index
drwxr-xr-x    4 ligang  staff   128B  5  9 16:11 info
drwxr-xr-x    4 ligang  staff   128B  5  9 16:11 logs
drwxr-xr-x  152 ligang  staff   4.8K 11  1 10:13 objects
-rw-r--r--    1 ligang  staff   166B  5  9 16:11 packed-refs
drwxr-xr-x    6 ligang  staff   192B  7  3 09:53 refs

-rw-r–r--:第一位用于标识文件类型,d表示目录、l表示连结文件、-表示文件;其他表示系统用户权限rw-rw-(Owner)r–(Group)r–(Other)【r可读、w可写、x可执行】

版本库位于工作区根目录下的.git目录中,且仅此一处,在工作区的子目录下则没有任何其他跟踪文件或目录。Git的这种设计,将版本库放在工作区根目录下,所有的版本控制操作(除了和其他远程版本库之间的互操作)都在本地即可完成。

代码语言:javascript
复制
$ git log -1 --pretty=raw
# 本次提交的唯一标识
commit b93afd2cce7e065dd4e7c33d1c6a4b3a7a75b259
# 本次提交所对应的目录树
tree 1e0c5cb85e1d2b4ff6875a5bbaa9183389ace668
# 本地提交的父提交(上一次提交)
parent 3365948518aad171336a52674cbdf0450679b4dc
author ligang <381510688@qq.com> 1543761152 +0800
committer ligang <381510688@qq.com> 1543761152 +0800

    feat(git): git 汇总

研究Git对象ID的一个重量级武器就是git cat-file命令。

查看一下这三个ID的类型:

代码语言:javascript
复制
$ git cat-file -t b93afd2cce7e065dd4e7c33d1c6a4b3a7a75b259
commit
$ git cat-file -t 1e0c5cb85e1d2b4ff6875a5bbaa9183389ace668
tree
$ git cat-file -t 3365948518aad171336a52674cbdf0450679b4dc
commit

查看对象的内容:

代码语言:javascript
复制
$ git cat-file -p <commitID>

Git 有一个底层命令git rev-parse 可以用于显示引用对应的提交ID

代码语言:javascript
复制
$ git rev-parse master
b93afd2cce7e065dd4e7c33d1c6a4b3a7a75b259
$ git rev-parse refs/heads/master
b93afd2cce7e065dd4e7c33d1c6a4b3a7a75b259
$ git rev-parse HEAD
b93afd2cce7e065dd4e7c33d1c6a4b3a7a75b259

可以看出它们都指向同一个对象!

git-objects.png
git-objects.png
  • 显示版本库.git 目录所在的位置
代码语言:javascript
复制
$ git rev-parse --git-dir
/Users/ligang/Documents/github/practice/.git
  • 显示工作区根目录
代码语言:javascript
复制
$ git rev-parse --show-toplevel
/Users/ligang/Documents/github/practice

git rev-parse 是Git的一个底层命令,其功能非常丰富(或者说杂乱),很多Git脚本或工具都会用到这条命令。

  • 显示分支 $ git rev-parse --symbolic --branches
  • 显示tags $ git rev-parse --symbolic --tags
  • 显示HEAD对应的SHA1哈希值 $ git rev-parse HEAD

版本库存储

本地(工作区、暂存区、HEAD)

工作区、版本库、暂存区原理图.png
工作区、版本库、暂存区原理图.png

说明

工作区

Git暂存区(stage,或称为index)

HEAD(当前分支,注意非远程)

  • HEAD实际是指向master分支的一个“游标”,HEAD全部可以使用master替换
  • objects为Git的对象库,位于 .git/objects 目录下;
  • 工作区 <==> 暂存区 命令说明git add ./将工作区变更提交到暂存区git checkout ./ git checkout -- 暂存区内容覆盖工作区git rm --cached 直接从暂存区删除文件,工作区则不做出改变
  • 暂存区 <==> HEAD 命令说明git commit -s -m ""将暂存区提交到master分支 (即master指向的目录树就是原暂存区的目录树)git reset HEAD ./使用master指向的目录树替换缓存区git checkout HEAD ./用HEAD指向的master分支内容替换暂存区及工作区的文件

重点来了! 如何还原本地工作区某文件

代码语言:javascript
复制
$ git reset HEAD <filename>
$ git checkout <filename>

# 替换命令
$ git checkout HEAD <filename>

本地(stash)

git stash 保存当前工作进度,会分别对暂存区和工作区的状态进行保存。

代码语言:javascript
复制
$ git stash [save [–patch] [-k|–[no-]keep-index] [-q|–quiet] [<message>]]
  • save "message..." 保存工作进度时使用指定说明
  • --patch 会显示工作区和HEAD的差异,通过对差异文件的编辑决定在进度中最终要保存的工作区的内容
  • -k或者--keep-index参数,在保存进度后不会将暂存区重置。缺省会将暂存区和工作区强制重置!

注意: 本地没有被版本控制系统跟踪的文件并不能保存进度,即新创建文件需要 git add

恢复工作进度,可以通过下述命令:

代码语言:javascript
复制
$ git stash apply [–index] [<stash>]
$ git stash drop [<stash>]
# 等价于上述两条命令
$ git stash pop [–index] [<stash>]

远程(remote)

代码语言:javascript
复制
$ cd .git/refs/remotes
$ ll
drwxr-xr-x   5 ligang  staff   160B 11 28 10:42 origin
drwxr-xr-x  11 ligang  staff   352B 11 27 00:11 upstream
$ ll origin 
-rw-r--r--  1 ligang  staff    32B 11  8 09:43 HEAD
-rw-r--r--  1 ligang  staff    41B 11 28 10:42 feature-v2.1
-rw-r--r--  1 ligang  staff    41B 11 28 10:42 master
$ ll upstream
-rw-r--r--  1 ligang  staff    41B 11 27 00:11 develop
-rw-r--r--  1 ligang  staff    41B 11 27 00:11 master
-rw-r--r--  1 ligang  staff    41B 11 27 00:11 themes
$ cat origin/develop
eeaa2013d901bda74eaa9fe102abe1e474b7a5d6
$ git ls-tree eeaa2013d901bda74eaa9fe102abe1e474b7a5d6

Git 这样的设计是非常巧妙的,在向远程版本库执行获取操作时,不是把远程版本库的分支原封不动地复制到本地版本库的分支中,而是复制到其命名空间中。如在克隆一个版本库时,会将远程分支都复制到目录 .git/refs/remotes/origin/ 下。这样向不同的远程版本库执行获取操作,因为远程分支相互隔离,所以就避免了相互的覆盖。

  • 添加新远程版本库
代码语言:javascript
复制
$ git remote add remote-name git@x.x.x.x:project-namespace/project-name.git
$ git remote -v
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2018-12-04 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 简介
  • Git对象
  • 版本库存储
    • 本地(工作区、暂存区、HEAD)
      • 本地(stash)
        • 远程(remote)
        相关产品与服务
        容器服务
        腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档