深入Git-上篇

简介: 前言作为一个开发者,想必大家都清楚Git。无论大家在工作中是使用命令行还是可视化工具来操作Git,应该都已经熟悉和掌握其基本的使用。而本系列文章的目的在于向大家介绍Git背后的基本原理,例如其如何实现不同版本的代码保存及版本切换。此外,还会向大家介绍一些好用的命令,解决在平常使用中的困惑。

「这是我参与2022首次更文挑战的第10天,活动详情查看:2022首次更文挑战


前言


作为一个开发者,想必大家都清楚Git。无论大家在工作中是使用命令行还是可视化工具来操作Git,应该都已经熟悉和掌握其基本的使用。而本系列文章的目的在于向大家介绍Git背后的基本原理,例如其如何实现不同版本的代码保存及版本切换。此外,还会向大家介绍一些好用的命令,解决在平常使用中的困惑。


.git目录结构


我们先学习下Git的目录结构


通过命令行来初始化个仓库


mkdir mygit
cd mygit
git init
复制代码


我们使用tree命令来打印此时的.git目录结构

.
├── HEAD
├── config
├── description
├── hooks
│   ├── applypatch-msg.sample
│   ├── commit-msg.sample
│   ├── fsmonitor-watchman.sample
│   ├── post-update.sample
│   ├── pre-applypatch.sample
│   ├── pre-commit.sample
│   ├── pre-push.sample
│   ├── pre-rebase.sample
│   ├── pre-receive.sample
│   ├── prepare-commit-msg.sample
│   └── update.sample
├── info
│   └── exclude
├── objects
│   ├── info
│   └── pack
└── refs
    ├── heads
    └── tags
复制代码


HEAD


HEAD文件保存着一个指针,实际指向当前工作环境对应的分支


ref: refs/heads/master
复制代码


当我们切换分支的时候,实际上HEAD的内容也会跟着变化


config


config对应我们仓库的一些配置

[core]
  repositoryformatversion = 0
  # 视文件权限的修改是否为差异
  filemode = true
  # 裸仓库 在使用 git init --bare 时会创建裸仓库也就是没有.git文件夹而是将所有文件暴露在主目录
  bare = false
  logallrefupdates = true
  # 忽略文件名的大小写
  ignorecase = true
  precomposeunicode = true
复制代码


在初始化时config只有core部分的配置,实际在后面我们会加入一些用户配置

git config user.name xxx
git config user.email emain
复制代码
[user]
  name = xxx
  email = email
复制代码


以及仓库分支的配置

# 远程仓库配置
remote "origin"]
  url = ssh://git@gitlab.xxx.cn:8888/xxx.git
  fetch = +refs/heads/*:refs/remotes/origin/*
# 分支配置
[branch "master"]
  remote = origin
  merge = refs/heads/master
复制代码


hooks


hooks下面保存一些钩子文件,用于保存在特定节点执行的bash命令。初始化的时候文件里面保存的都是示例,如果需要启用可以把文件名后缀.sample删除


#!/bin/sh
#
# An example hook script to check the commit log message taken by
# applypatch from an e-mail message.
#
# The hook should exit with non-zero status after issuing an
# appropriate message if it wants to stop the commit.  The hook is
# allowed to edit the commit message file.
#
# To enable this hook, rename this file to "applypatch-msg".
. git-sh-setup
commitmsg="$(git rev-parse --git-path hooks/commit-msg)"
test -x "$commitmsg" && exec "$commitmsg" ${1+"$@"}
:
复制代码


info


里面包含exclude文件,作用和.gitignore相似,区别在于exclude文件修改不会保存在版本中而.gitignore则会。


objects


objects是git版本控制的核心,我们可以将其理解为版本仓库。下面包含两个文件夹info和pack,初始时没有内容。我们后面会重点分析这一部分。


其它


我们刚才只是分析了git初始化的目录结构,实际在使用过程中还会生成很多其它的目录及文件。我们来看个使用中的项目下的.git目录结构。


tree -I objects
复制代码


我们忽略objects目录,在后面的分析中再详细分析

├── COMMIT_EDITMSG
├── FETCH_HEAD
├── HEAD
├── ORIG_HEAD
├── config
├── description
├── hooks
│   ├── applypatch-msg
│   ├── applypatch-msg.sample
│   ├── commit-msg
│   └── update.sample
├── index
├── info
│   └── exclude
├── logs
│   ├── HEAD
│   └── refs
│       ├── heads
│       │   ├── master
│       │   └── debug
│       └── remotes
│           └── origin
│               ├── HEAD
│               ├── master
│               └── debug
├── packed-refs
└── refs
    ├── heads
    │   ├── master
    │   └── debug
    ├── remotes
    │   └── origin
    │       ├── HEAD
    │       ├── master
    │       └── debug
    └── tags
        ├── release_202003181722
        └── release_202002130082
复制代码


COMMIT_EDITMSG


临时文件,保存最后一次本地提交的commit信息。例如当我们pull远程代码更新本地仓库时,可以通过COMMIT_EDITMSG来找到我们上一次提交的位置。

修复xxx问题
复制代码


FETCH_HEAD


在我们执行fetch命令的时候会更新此文件,文件保存了我们拉取的远程分支对应的信息版本号(远程) 分支仓库地址。还有个关键字not-for-merge,其表明不需要合并的分支,什么意思呢?


例如我们当前在master分支,那么在当前分支执行pull命令的时候只会讲远程的master进行合并,就是因为有not-for-merge标记其它分支。所以当我们切换分支再fetch的时候,分支对应的not-for-merge也会更新。


f2357a770980f131fdcc5746adc4f7d2566dc86 branch 'master' of ssh://git@gitlab.xxx.cn:8888/xxx.git
632371e033b3352828dac377b1ab63ca07c3c44 not-for-merge branch 'debug' of ssh://git@gitlab.xxx.cn:8888/xxx.git
复制代码


ORIG_HEAD


2322e639d28e52544dd7565fb341eff82313de29a
复制代码

ORIG_HEAD用于备份HEAD对应的版本号,在我们执行以下操作时会进行备份


git reset
git merge
git rebase
git pull
复制代码


这也就可以理解为什么我们在解决冲突的时候,可以通过abort来放弃并退回之前版本


index


index是个二进制文件,属于git的核心实现。其对应我们所说的暂存区,所以通过其可以得到我们整个暂存区的仓库文件,当然其主要保存的是各个文件对应的指针,在此不多分析。


logs


logs中保存对应分支的操作日志,也就是我们使用reflog可以查看到的日志。

refs


refs目录用于保存当前各种分支或者tag下对应的版本号(commitId)。

分为三个部分


目录 内容
heads 本地各个分支对应的commitId
remotes 远程各个分支对应的commitId
tags 各个tag对应的commitId

从此处可以看出,分支和tag实际是指向某个commitId的指针。


参考




相关文章
|
Go Android开发 开发者
关于Xposed和Magisk的各方面比较(附Xposed框架各版本卡刷包及安装器)
说到搞机神器,不得不提江湖老大哥Xposed和后起之秀Magisk这两个框架,文章简单的介绍一下两者相似和不同之处
2067 0
|
监控 负载均衡 应用服务中间件
Passenger作用及原理梳理
我们在部署rails应用时,大多时候都使用Nginx+Passenger的方式部署,本文主要对此架构下 Passenger的作用及其工作原理进行梳理。 一、什么是Passenger? Phusion Passenger是一个开源的Web应用服务器,它能够处理HTTP请求,管理进程和资源、 系统监控以
865 0
|
网络安全 数据安全/隐私保护
ssh远程执行命令自动输入密码方式
ssh远程执行命令自动输入密码方式
3021 0
|
Java 关系型数据库 数据库连接
深入理解 @TableName 和 @TableField 注解
深入理解 @TableName 和 @TableField 注解
769 0
|
iOS开发
细谈证书与Provisioning Profile
iOS程序员大多对证书和Provisioning Profile懵逼过吧,是时候整理一下思路了,把这个问题讲讲清楚。所有配置都在[https://developer.apple.com](https://developer.apple.com),大家都可以上去摸索一下。 ### 证书 打开`钥匙串访问`可以看到里面有`证书`和`我的证书`两项,其中`证书`包含系统安装的所有证书,`我的
3457 0
|
存储 人工智能 数据库
亚马逊 AWSVS 阿里云 | 轻量应用服务器性能评测对比
亚马逊 AWSVS 阿里云 | 轻量应用服务器性能评测对比
|
应用服务中间件 nginx Web App开发
|
Java 数据库连接 数据库
深入了解Java中的MyBatis Plus注解 @FieldStrategy:灵活处理字段策略
在数据库操作中,对于字段的操作可能需要根据不同的业务需求,采取不同的处理策略,比如插入操作时某些字段需要强制设值,更新操作时某些字段需要忽略等。MyBatis Plus作为一款强大的ORM框架,提供了注解 `@FieldStrategy`,使开发者能够更加灵活地处理字段的操作策略,从而减少代码的重复和冗余。本文将详细介绍 `@FieldStrategy` 注解的用法及其在持久层开发中的应用。
1906 0
|
Linux Docker 容器
CentOS7系统安装最新版本docker实战
CentOS7系统安装最新版本docker实战
1814 0
CentOS7系统安装最新版本docker实战
|
Java 程序员
java构造器(构造方法、构造函数)
java构造器(构造方法、构造函数)