深入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的指针。


参考




相关文章
|
10月前
|
存储 开发工具 git
Git简介加简单的使用
Git简介加简单的使用
48 0
|
5月前
|
Shell 开发工具 git
|
5月前
|
Linux 网络安全 开发工具
Git 入门指南(二)
Git 入门指南(二)
|
12月前
|
开发工具 git
深入Git-下篇
前言 在前面的几篇文章主要介绍了一些原理性的东西。本篇文章作为收尾,将介绍一些在日常工作中比较有用的命令以及解决一些经常出现的问题场景。大家可以结合git常用命令(熟练了就是高手)进行学习。
|
存储 缓存 开发工具
git基础入门以及git常用命令
git是一个开源的分布式版本控制系统,用于敏捷高效的处理或大或小的项目,更是一个内容管理系统(CMS),工作管理系统。git是分布式的,svn不是 git把内容按元数据方式存储,而svn是按照文件 git没有一个全局的版本号,而svn有 git的内容完整性要优于svn。
210 0
git基础入门以及git常用命令
|
Shell 开发工具 git
关于Git,这篇文章还不够吗?
关于Git,这篇文章还不够吗?
|
安全 Java 网络安全
|
存储 开发工具 git
GIT详细基础笔记(1)
GIT详细基础笔记
136 0
GIT详细基础笔记(1)
|
存储 JavaScript Linux
Git入门Git简介
Git入门Git简介
97 0
Git入门Git简介
|
数据可视化 Unix 网络安全
Git入门Git使用
Git入门Git使用
91 0
Git入门Git使用