Git 的正确使用姿势与最佳实践|青训营笔记

177 阅读10分钟

这是我参与「第三届青训营 -后端场」笔记创作活动的的第3篇笔记。 主要介绍Git的相关知识和基本使用。

一 Git是什么

  • 版本控制系统:一种记录一个或若干文件内容变化,以便将来查阅特定版本修订情况的系统
  • Git:一种分布式版本控制系统
为什么需要版本控制?
1 更好的关注变更,了解到每个版本的改动是什么,方便对改动的代码进行检查,预防事故发生
2 能够随时切换到不同的版本,回滚误删误该的问题代码

版本控制类型
本地版本控制(RCS)    本地代码的版本控制
集中式版本控制(SVN)  提供一个远端服务器来维护代码版本,本地不保存代码版本,解决多人协作问题
分布式版本控制(Git)  每个仓库都能记录历史版本,解决只有一个服务器保存版本的问题

二 Git的基本概念

Git有四个工作区域
1 工作区 平时存放项目代码的地方
2 暂存区 用于临时存放改动,实际上是一个文件(index)
3 本地仓库 安全存放数据的地方,保存所有版本的数据,其中HEAD指向最新放入仓库的版本
4 远程仓库 托管代码的服务器

工作区(git add) -> 暂存区(git commit) -> 本地仓库(git push) -> 远程仓库
远程仓库(git pull) -> 本地仓库(git reset) -> 暂存区(git checkout) -> 工作区

image.png

三 Git的基本使用

2.1 常见问题

1 为什么我配置了git,但是没办法拉取代码?
免密认证没有配置
Instead of没有配置,配置的SSH免密,但是使用的还是HTTP协议访问

2 为什么我fetch了远端分支,但是本地当前的分支分支历史没有变化?
Fetch会把代码拉取到本地的远端分支,但是并不会合并到当前分支,所以当前分支历史没有变化

2.2 常用命令

git branch                              列出所有本地分支
git branch -r                           列出所有远程分支
git branch [branch-name]                新建一个分支,但仍留在当前分支
git checkout -b [branch-name]           新建一个分支,并切换到该分支
git merge [branch]                      合并指定分支到当前分支
git branch -d [branch-name]             删除分支
git push origin --delete [branch-name]  删除远程分支
git branch -dr [remote/branch-name]     删除远程分支

git remote -h              查看帮助命令
git remote -v              查看远程仓库的url
git remote rm origin       移除当前
git remote add origin      添加ssh链接

2.3 流程

  • 配置用户名和邮箱
git config --global user.name programAA
git config --global user.email 784562470@qq.com

配置级别,低级别的配置会覆盖高级别的配置
--global   保存在~/.gitconfig
--system   保存在etc/config
--local    保存在.git/confit

  • 添加远端仓库的ssh链接和配置远程仓库的秘钥
添加远端仓库的ssh链接
git remote add origin git@github.com:programAA/demo.git

免密配置
SSH可以通过公私钥的机制,把生成的公钥存在服务端,从而实现免密访问
目前的key有四种,dsa,rsa、ecdsa、ed25519,默认使用rsa,推荐使用ed25519
ssh-keygen -t ed25519 -C "784562470@qq.com"
秘钥默认存在~/.ssh/id_ed25519.pub,把.pub文件的内容添加到github账号
  • 初始化
git init    初始化git仓库
tree .git   查看初始化的目录结构

.git
├── branches
├── config
├── description
├── HEAD
├── hooks
├── info
│   └── exclude
├── objects
│   ├── info
│   └── pack
└── refs
    ├── heads
    └── tags

  • 添加改动到暂存区
touch readme.md
git add .
tree .git

.git
├── branches
├── config
├── description
├── HEAD
├── hooks
├── index
├── info
│   └── exclude
├── objects
│   ├── 15
│   │   └── 49b67ca5936e6893c89221d508697e7e97d42b
│   ├── info
│   └── pack
└── refs
    ├── heads
    └── tags


  • 提交改动到本地仓库
git commit -m "add readme"
tree .git

.git
├── branches
├── COMMIT_EDITMSG
├── config
├── description
├── HEAD
├── hooks
├── index
├── info
│   └── exclude
├── logs
│   ├── HEAD
│   └── refs
│       └── heads
│           └── master
├── objects
│   ├── 10
│   │   └── e51eca774c5f903246a9e85808908e9a4cd188
│   ├── 15
│   │   └── 49b67ca5936e6893c89221d508697e7e97d42b
│   ├── 1e
│   │   └── a2e4d545152761e06358d544289c2b494b8e08
│   ├── info
│   └── pack
└── refs
    ├── heads
    │   └── master
    └── tags

  • 推送内容到远程仓库
git push <远程主机> <本地仓库>:<远程仓库>
git push origin master
git push origin master:main
origin 代表 git@github.com:programAA/demo.git
远程仓库默认和本地仓库同名,不存在时自动创建

tree .git

.git
├── branches
├── COMMIT_EDITMSG
├── config
├── description
├── HEAD
├── hooks
├── index
├── info
│   └── exclude
├── logs
│   ├── HEAD
│   └── refs
│       ├── heads
│       │   └── master
│       └── remotes
│           └── origin
│               ├── main
│               └── master
├── objects
│   ├── 10
│   │   └── e51eca774c5f903246a9e85808908e9a4cd188
│   ├── 15
│   │   └── 49b67ca5936e6893c89221d508697e7e97d42b
│   ├── 1e
│   │   └── a2e4d545152761e06358d544289c2b494b8e08
│   ├── info
│   └── pack
└── refs
    ├── heads
    │   └── master
    ├── remotes
    │   └── origin
    │       ├── main
    │       └── master
    └── tags
查看文件内容
> git cat-file -p 1549b67ca5936e6893c89221d508697e7e97d42b
demo

> git cat-file -p 1ea2e4d545152761e06358d544289c2b494b8e08
100644 blob 1549b67ca5936e6893c89221d508697e7e97d42b	readme.md

> git cat-file -p 10e51eca774c5f903246a9e85808908e9a4cd188
tree 1ea2e4d545152761e06358d544289c2b494b8e08
author programAA <784562470@qq.com> 1653480646 +0800
committer programAA <784562470@qq.com> 1653480646 +0800

add readme
  • 拉取远程仓库代码
git pull <远程主机名> <远程分支名>:<本地分支名>
git pull origin main:main
tree .git

.git
├── branches
├── COMMIT_EDITMSG
├── config
├── description
├── FETCH_HEAD
├── HEAD
├── hooks
├── index
├── info
│   └── exclude
├── logs
│   ├── HEAD
│   └── refs
│       ├── heads
│       │   ├── main
│       │   ├── master
│       │   └── test
│       └── remotes
│           └── origin
│               ├── main
│               └── master
├── objects
│   ├── 10
│   │   └── e51eca774c5f903246a9e85808908e9a4cd188
│   ├── 15
│   │   └── 49b67ca5936e6893c89221d508697e7e97d42b
│   ├── 1e
│   │   └── a2e4d545152761e06358d544289c2b494b8e08
│   ├── 92
│   │   └── ed13e9275e463cebc37241360ba9da2ebfefcc
│   ├── a3
│   │   └── 05b88416241fabfc292c27697ac440e5dbf320
│   ├── a5
│   │   └── 064323edfb0bd97bcef5d18b58ce75f9716e00
│   ├── ef
│   │   └── 8252553dd57b348a8f6cb7df5a30f91698374d
│   ├── info
│   └── pack
├── ORIG_HEAD
└── refs
    ├── heads
    │   ├── main
    │   ├── master
    │   └── test
    ├── remotes
    │   └── origin
    │       ├── main
    │       └── master
    └── tags
        ├── v0.0.1
        └── v0.0.2
        
 > git cat-file -p ef8252553dd57b348a8f6cb7df5a30f91698374d
tree a305b88416241fabfc292c27697ac440e5dbf320
parent 10e51eca774c5f903246a9e85808908e9a4cd188
author sea <33782687+programAA@users.noreply.github.com> 1653482994 +0800
committer GitHub <noreply@github.com> 1653482994 +0800
gpgsig -----BEGIN PGP SIGNATURE-----

 wsBcBAABCAAQBQJijiXyCRBK7hj4Ov3rIwAAYHwIABPGcbNukns9JJi7OHzk/ein
 hPwLmRsO9QIzQIS3sxCN+JIR9Sp3SFbTUbexGVEhTmRoggdQRsxCqXPVsYVVQ75w
 PXEFUvzaGYXkjA1jhMa3tkbsYmjVlmEYIsrGB8Tniw2DYU3E8UpzXnEhVWj+kwAG
 0cMWy1LGF9UG0xbE0dj5PLbBKxtc8q9vOVw+pgWtHroNt1eRpRzlZBJNY8EKMCS8
 OEAG30JdBW9YnIEU/K+APR/Ic8vVDYYw91FrLUHpcXLrOn3slLysvyMh68bN1JBw
 8WGgtBjsCZIkj760wTqVl3AY99+84QmACuRf6fW5aqGKEgQGJE2THAGdv6VcJas=
 =RdxK
 -----END PGP SIGNATURE-----


Create demo.cpp        
        
> git cat-file -p a305b88416241fabfc292c27697ac440e5dbf320
100644 blob a5064323edfb0bd97bcef5d18b58ce75f9716e00	demo.cpp
100644 blob 1549b67ca5936e6893c89221d508697e7e97d42b	readme.md        

> git cat-file -p a5064323edfb0bd97bcef5d18b58ce75f9716e00
#include <iostream>
using namespace std;

int main(){
    cout << "Hello, World!" << endl;
}
      
> git cat-file -p 1549b67ca5936e6893c89221d508697e7e97d42b
demo  

2.4 Object

4Object 类型
1 tag
2 commit   10e51eca774c5f903246a9e85808908e9a4cd188
3 tree     1ea2e4d545152761e06358d544289c2b494b8e08
4 blob     1549b67ca5936e6893c89221d508697e7e97d42b

Branch(分支)一般用于开发阶段,是可以不断添加Commit进行迭代的
Tag(标签)一般表示一个稳定版本,指向的Commit一般不会变更
创建新分支
git checkout -b test
tree .git

.git
├── branches
├── COMMIT_EDITMSG
├── config
├── description
├── HEAD
├── hooks
├── index
├── info
│   └── exclude
├── logs
│   ├── HEAD
│   └── refs
│       ├── heads
│       │   ├── master
│       │   └── test
│       └── remotes
│           └── origin
│               ├── main
│               └── master
├── objects
│   ├── 10
│   │   └── e51eca774c5f903246a9e85808908e9a4cd188
│   ├── 15
│   │   └── 49b67ca5936e6893c89221d508697e7e97d42b
│   ├── 1e
│   │   └── a2e4d545152761e06358d544289c2b494b8e08
│   ├── info
│   └── pack
└── refs
    ├── heads
    │   ├── master
    │   └── test
    ├── remotes
    │   └── origin
    │       ├── main
    │       └── master
    └── tags

> cat .git/refs/heads/test
10e51eca774c5f903246a9e85808908e9a4cd188
> cat .git/refs/heads/master
10e51eca774c5f903246a9e85808908e9a4cd188
创建tag
git tag v0.0.1
tree .git

.git
├── branches
├── COMMIT_EDITMSG
├── config
├── description
├── HEAD
├── hooks
├── index
├── info
│   └── exclude
├── logs
│   ├── HEAD
│   └── refs
│       ├── heads
│       │   ├── master
│       │   └── test
│       └── remotes
│           └── origin
│               ├── main
│               └── master
├── objects
│   ├── 10
│   │   └── e51eca774c5f903246a9e85808908e9a4cd188
│   ├── 15
│   │   └── 49b67ca5936e6893c89221d508697e7e97d42b
│   ├── 1e
│   │   └── a2e4d545152761e06358d544289c2b494b8e08
│   ├── info
│   └── pack
└── refs
    ├── heads
    │   ├── master
    │   └── test
    ├── remotes
    │   └── origin
    │       ├── main
    │       └── master
    └── tags
        └── v0.0.1

> cat .git/refs/tags/v0.0.1 
10e51eca774c5f903246a9e85808908e9a4cd188

> git cat-file -p 10e51eca774c5f903246a9e85808908e9a4cd188
tree 1ea2e4d545152761e06358d544289c2b494b8e08
author programAA <784562470@qq.com> 1653480646 +0800
committer programAA <784562470@qq.com> 1653480646 +0800

add readme
git tag -a v0.0.2 -m "add feature 1"
tree .git

.git
├── branches
├── COMMIT_EDITMSG
├── config
├── description
├── HEAD
├── hooks
├── index
├── info
│   └── exclude
├── logs
│   ├── HEAD
│   └── refs
│       ├── heads
│       │   ├── master
│       │   └── test
│       └── remotes
│           └── origin
│               ├── main
│               └── master
├── objects
│   ├── 10
│   │   └── e51eca774c5f903246a9e85808908e9a4cd188
│   ├── 15
│   │   └── 49b67ca5936e6893c89221d508697e7e97d42b
│   ├── 1e
│   │   └── a2e4d545152761e06358d544289c2b494b8e08
│   ├── 92
│   │   └── ed13e9275e463cebc37241360ba9da2ebfefcc
│   ├── info
│   └── pack
└── refs
    ├── heads
    │   ├── master
    │   └── test
    ├── remotes
    │   └── origin
    │       ├── main
    │       └── master
    └── tags
        ├── v0.0.1
        └── v0.0.2

        
> cat .git/refs/tags/v0.0.2 
92ed13e9275e463cebc37241360ba9da2ebfefcc

> git cat-file -p 92ed13e9275e463cebc37241360ba9da2ebfefcc
object 10e51eca774c5f903246a9e85808908e9a4cd188
type commit
tag v0.0.2
tagger programAA <784562470@qq.com> 1653482243 +0800

add feature 1