青训营笔记:Git 基本原理与使用

基本介绍

原理:

  1. 每个库都有完整的提交历史,可以在本地进行代码提交;
  2. 每次提交记录都是完整的文件快照,而不是记录增量;
  3. 通过 Push Pull 等操作完成和远端代码的同步。
    优点:
  4. 分布式开发,每个库都有完整的提交历史,支持本地提交,强调个体;
  5. 分支管理功能强大,方便团队合作,多人协作开发;
  6. 校验和机制保证完整性,一般只添加数据,很少执行删除操作,不容易导致代码丢失。
    缺点:
  7. 相对 SVN 更复杂,学习成本更高;
  8. 对于大文件支持一般(可使用 git-lfs 弥补)

init

初始化一个 Git 仓库

1
git init

参数:
–initial-branch 初始化的分支
–bare 创建一个裸仓库(纯 Git 目录,没有工作目录)
–template 通过模板创建预先构建好的自定义 Git 目录

config

基本命令

1
2
3
git config --system 配置项 参数
git config --global 配置项 参数
git config --local 配置项 参数

配置命令别称

1
2
git config --global alias.cin "commit --amend --no-edit"
# cin = commit --amend --no-edit

remote

远程仓库管理

基本使用

查看所有远程服务器

1
git remote -v

输出示例

1
2
origin_http     https://github.com/git/git.git (fetch)
origin_http https://github.com/git/git.git (push)

查看配置文件,可以直接修改 .git/config 配置文件以修改 remote。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
cat .git/config

[core]
repositoryformatversion = 0
filemode = false
bare = false
logallrefupdates = true
symlinks = false
ignorecase = true
[remote "origin_ssh"]
url = git@github.com:git/git.git
fetch = +refs/heads/*:refs/remotes/origin_ssh/*
[remote "origin_http"]
url = https://github.com/git/git.git
fetch = +refs/heads/*:refs/remotes/origin_http/*

同一个 Origin 设置不同的 Push 和 Fetch 路径:

1
2
git remote set-url --add --push origin [push url]
git remote set-url --add --fetch origin [push url]

免密配置

1
2
3
4
# 将密码保存在内存中
git config --global credential.helper cache --timeout=3600'
# 将密码保存在磁盘中
git config --global credential.helper store

SSH Remote

通过 SSH 公私钥的机制实现免密访问,密钥类型有:

  • DSA (不推荐)
  • RSA(不推荐)
  • ECDSA
  • ED25519

add & commit

1
git add .

将工作区的修改加入暂存区,存储于 .git/objects/ 文件夹中。

1
2
3
4
5
6
7
8
9
10
11
git commit -m "readme"
[master (root-commit) 0fbab7f] readme
1 file changed, 1 insertion(+)
create mode 100644 README.md

git cat-file -p 0fbab7f
tree db78f3594ec0683f5d857ef731df0d860f14f2b2
author XXX 1653394554 +0800
committer XXX 1653394554 +0800

readme

通过 Commit 的 TreeID 寻找 Tree,寻找

Objects

Blob:存储文件内容
Tree:存储文件的目录信息
Commit:存储提交信息

  1. 通过 Commit 寻找 TreeID
  2. 通过 TreeID 获取目录树
  3. 从目录树中获取 BlobID
  4. 通过 BlobID 获取文件文件内容

Tag:存储版本信息以及版本说明

Tag

1
git tag v0.0.1
1
git tag -a v0.0.2 -m "Add feature 1"
1
2
3
cat .git/refs//tags/v0.0.1
0fbab7ff5def6345e53a42c878718f21cc4c43ff
# 这里是 Commit ID,指向一个 Commit
1
2
3
4
5
6
7
8
9
10
11
cat .git/refs/tags/v0.0.2
9559fc5035d6b5764b32096af91042e72e1b243b
# 指向一个 Tag Object

git cat-file -p 9559fc5035d6b5764b32096af91042e72e1b243b
object 0fbab7ff5def6345e53a42c878718f21cc4c43ff # 这里还是 Commit ID
type commit
tag v0.0.2
tagger XXX 1653442595 +0800

add feature 1

追溯历史版本

进行第二次提交,ref 指向了新的版本,查看 Object 内容:

1
2
3
4
5
6
7
git cat-file -p 31db32cf6c374bd21e1ddcb740da705fc41cf6e6
tree 22e3db29d5f8afddff55a957299a6fdca1713c21
parent 0fbab7ff5def6345e53a42c878718f21cc4c43ff #通过 parent 获取上一个版本
author XXX 1653443065 +0800
committer XXX 1653443065 +0800

update README

修改历史版本

1
2
3
4
5
6
# 修改最近的一次 commit
commit --amend
# 修改最近 N 次 Commit
rebase -i HEADD~N
# 从所有提交中删除某个文件
filter --branch

修改 Commit:新增 Commit Object,不删除旧的 Commit Object

查看悬空的 Commit

1
git fsck --lost-found	
1
2
3
Checking object directories: 100% (256/256), done.
dangling blob e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
dangling commit 31db32cf6c374bd21e1ddcb740da705fc41cf6e6

删除多余的 Object(Git GC)

Reflog 记录操作日志,防止误操作后数据丢失

1
git reflog expire --expire=now --all
1
2
3
git gc
#指定修剪多久之前的对象,默认两周前
git gc --prune=now

会将 Object 打包为 Pack

Clone & Pull & Fetch

Clone:拉取完整仓库,可以指定分治

Fetch:将某些分支拉到本地

Pull:git fetch + git merge

Push

1
git push origin master

代码合并

Fast-forward:不产生 Merge 节点

1
git merge test --ff-only

Tree-way-merge:产生新的 Merge 节点

1
git merge test --no-ff