mirror of
https://github.com/Dichgrem/Blog.git
synced 2025-08-01 09:19:32 -04:00
506 lines
14 KiB
Markdown
506 lines
14 KiB
Markdown
+++
|
||
title = "乱七八糟:Git使用简明手册"
|
||
date = 2023-12-15
|
||
|
||
[taxonomies]
|
||
tags = ["乱七八糟"]
|
||
+++
|
||
|
||
|
||
|
||
前言 Git,作为现代软件开发中不可或缺的版本控制工具,常常让初学者感到困惑。本文旨在介绍 Git 的全流程安装和基本使用,希望能够帮助新手更轻松地理解和掌握 Git 的基本概念和操作。
|
||
<!-- more -->
|
||
## 安装git
|
||
|
||
- Windows:[Git-download](https://git-scm.com/download/)
|
||
|
||
- Archlinux:`sudo pacman -S git`
|
||
|
||
## 原理
|
||
|
||
一个Git仓库的目录里面包括``工作目录``(即我们要追踪的代码)以及``.git``目录(Git 在这里存储自己的数据)。Git 维护了三棵“树”:第一个是你的 `工作目录`,它持有实际文件;第二个是 `暂存区(Index)`,它像个缓存区域,临时保存你的改动;最后是 `HEAD`,它指向你最后一次提交的结果。
|
||
|
||
|
||

|
||
|
||
## 创建新仓库
|
||
|
||
首先我们需要得到一个Git仓库,一般有两种方法:
|
||
|
||
- 在本地初始化之后连接到远程;
|
||
- 在远程创建后”下载“到本地。
|
||
|
||
**方法一**
|
||
创建新文件夹,在你的项目目录中运行以下命令:
|
||
```
|
||
git init --initial-branch=main
|
||
```
|
||
这里设置默认仓库主分支名称为 main,避免因为 main/master 名称不同导致的推送问题。
|
||
|
||
> Git目前默认的主分支为 master,和 github 默认分支 main 不同,这使得默认配置下 git 往往连接失败。除了创建的时候设定外还可以通过以下方法改变默认分支。
|
||
```
|
||
git config --global init.defaultBranch main //将默认分支修改成main
|
||
```
|
||
**方法二**
|
||
|
||
克隆远端服务器上的仓库:
|
||
|
||
- HTTPS方法:``git clone https://github.com/Dichgrem/script.git``
|
||
- 或者使用SSH方法:``git clone git@github.com:Dichgrem/script.git``
|
||
|
||
>建议使用SSH方法,如果你使用HTTPS方法,则提交代码时需要手动输入用户名/密码,使用SSH方法则只需要在``~/.ssh/config``中配置即可。
|
||
|
||
## 配置
|
||
|
||
Git的设置文件为.gitconfig,它可以在用户主目录下(全局配置),也可以在项目目录下(项目配置)。
|
||
|
||
- 显示当前的Git配置
|
||
```
|
||
git config --list
|
||
```
|
||
- 编辑Git配置文件
|
||
```
|
||
git config -e [--global]
|
||
```
|
||
- 设置提交代码时的用户信息
|
||
```
|
||
git config [--global] user.name "[name]"
|
||
git config [--global] user.email "[email address]"
|
||
```
|
||
- 设置大小写敏感(windows不区分大小写的解决办法)
|
||
```
|
||
git config core.ignorecase false
|
||
```
|
||
## 连接远程仓库
|
||
|
||
连接到远程仓库并推送需要证明你有权写入仓库。早期Github可以使用密码认证,现在则使用密钥认证。
|
||
|
||
- 生成密钥:
|
||
```
|
||
ssh-keygen -t rsa -b 4096 -C "your_email@example.com"
|
||
```
|
||
- 生成的文件位于``~/.ssh/config``路径下,带.pub后缀的文件为公钥,不带.pub后缀的为私钥,使用``cat ~/.ssh/id_rsa.pub``将公钥添加到github/gitee的设置-SSH中。
|
||
|
||
- 随后使用 `ssh-add` 命令将生成的密钥添加到 SSH 代理中。
|
||
```
|
||
ssh-add ~/.ssh/github_key
|
||
ssh-add ~/.ssh/gitee_key
|
||
```
|
||
- 在 `~/.ssh/config` 文件中配置不同的主机别名以及相应的密钥文件。编辑该文件并添加内容,例如:
|
||
```
|
||
# GitHub repository 1
|
||
|
||
Host github1
|
||
|
||
HostName github.com
|
||
|
||
User git
|
||
|
||
IdentityFile ~/.ssh/github_key
|
||
|
||
# GitHub repository 2
|
||
|
||
Host github2
|
||
|
||
HostName gitee.com
|
||
|
||
User git
|
||
|
||
IdentityFile ~/.ssh/gitee_key
|
||
```
|
||
|
||
- 连接到github:
|
||
```
|
||
ssh -T git@github.com
|
||
```
|
||
- 添加远程仓库:
|
||
```
|
||
git remote add origin <remote_repository_url>
|
||
|
||
# 例如:git remote add origin git@github.com:Dichgrem/dichos.git
|
||
```
|
||
> 如果你运行``git remote -v``发现URL为HTTP格式则可以用下面的命令改为Git格式:
|
||
```
|
||
# 例如:git remote set-url origin git@github.com:Dichgrem/dichos.git
|
||
```
|
||
|
||
## 创建分支
|
||
```
|
||
git branch main
|
||
```
|
||
这将创建一个名为 main 的分支。
|
||
|
||
- 删除分支
|
||
```
|
||
git branch -d master
|
||
```
|
||
- 使用大写强制删除
|
||
```
|
||
git branch -D master
|
||
```
|
||
|
||
|
||
## 添加和提交
|
||
|
||
你可以提出更改(把它们添加到暂存区),使用如下命令:
|
||
```
|
||
git add <filename>
|
||
git add *
|
||
```
|
||
这是 git 基本工作流程的第一步;使用如下命令以实际提交改动:
|
||
```
|
||
git commit -m "代码提交信息"
|
||
# 例如:git commit -m "Initial commit"
|
||
```
|
||
现在,你的改动已经提交到了 **HEAD**,但是还没到你的远端仓库。
|
||
|
||
- 添加指定文件到暂存区
|
||
```
|
||
git add [file1] [file2] ...
|
||
```
|
||
- 添加指定目录到暂存区,包括子目录
|
||
```
|
||
git add [dir]
|
||
```
|
||
- 添加当前目录的所有文件到暂存区
|
||
```
|
||
git add .
|
||
```
|
||
添加每个变化前,都会要求确认
|
||
- 对于同一个文件的多处变化,可以实现分次提交
|
||
```
|
||
git add -p
|
||
```
|
||
- 删除工作区文件,并且将这次删除放入暂存区
|
||
```
|
||
git rm [file1] [file2] ...
|
||
```
|
||
- 停止追踪指定文件,但该文件会保留在工作区
|
||
```
|
||
git rm --cached [file]
|
||
```
|
||
- 改名文件,并且将这个改名放入暂存区
|
||
```
|
||
git mv [file-original] [file-renamed]
|
||
```
|
||
## 推送改动
|
||
|
||
你的改动现在已经在本地仓库的 **HEAD** 中了。执行如下命令以将这些改动提交到远端仓库:
|
||
```
|
||
git push origin main
|
||
```
|
||
可以把 **main** 换成你想要推送的任何分支,如**master**或者**test**
|
||
|
||
如果你的远程仓库是最新的,可以使用以下命令更新本地仓库:
|
||
```
|
||
git pull
|
||
```
|
||
## 合并分支
|
||
|
||
分支是用来将特性开发绝缘开来的。比如你在本地的test分支新增了一个功能,想要合并到主分支中。
|
||
|
||
创建一个叫做“test”的分支,并切换过去:
|
||
```
|
||
git checkout -b test
|
||
```
|
||
新增某些功能后切换回主分支:
|
||
```
|
||
git checkout master
|
||
```
|
||
在主分支上执行合并操作,将 test 分支的改动合并到主分支:
|
||
```
|
||
git merge test
|
||
```
|
||
推送完成后可以把新建的分支删掉:
|
||
```
|
||
git branch -d test
|
||
```
|
||
|
||
### 分支常用操作
|
||
```
|
||
- 列出所有本地分支
|
||
git branch
|
||
|
||
- 列出所有远程分支
|
||
git branch -r
|
||
|
||
- 列出所有本地分支和远程分支
|
||
git branch -a
|
||
|
||
- 列出所有本地分支,并展示没有分支最后一次提交的信息
|
||
git branch -v
|
||
|
||
- 列出所有本地分支,并展示没有分支最后一次提交的信息和远程分支的追踪情况
|
||
git branch -vv
|
||
|
||
- 列出所有已经合并到当前分支的分支
|
||
git branch --merged
|
||
|
||
- 列出所有还没有合并到当前分支的分支
|
||
git branch --no-merged
|
||
|
||
- 新建一个分支,但依然停留在当前分支
|
||
git branch [branch-name]
|
||
|
||
- 新建一个分支,并切换到该分支
|
||
git checkout -b [branch]
|
||
|
||
- 新建一个与远程分支同名的分支,并切换到该分支
|
||
git checkout --track [branch-name]
|
||
|
||
- 新建一个分支,指向指定commit
|
||
git branch [branch] [commit]
|
||
|
||
- 新建一个分支,与指定的远程分支建立追踪关系
|
||
git branch --track [branch] [remote-branch]
|
||
|
||
- 切换到指定分支,并更新工作区
|
||
git checkout [branch-name]
|
||
|
||
- 切换到上一个分支
|
||
git checkout -
|
||
|
||
- 建立追踪关系,在现有分支与指定的远程分支之间
|
||
git branch --set-upstream-to=[remote-branch]
|
||
git branch --set-upstream [branch] [remote-branch] - 已被弃用
|
||
|
||
- 合并指定分支到当前分支
|
||
git merge [branch]
|
||
|
||
- 中断此次合并(你可能不想处理冲突)
|
||
git merge --abort
|
||
|
||
- 选择一个commit,合并进当前分支
|
||
git cherry-pick [commit]
|
||
|
||
- 删除分支
|
||
git branch -d [branch-name]
|
||
|
||
#新增远程分支 远程分支需先在本地创建,再进行推送
|
||
git push origin [branch-name]
|
||
|
||
- 删除远程分支
|
||
git push origin --delete [branch-name]
|
||
git branch -dr [remote/branch]
|
||
```
|
||
|
||
## 标签
|
||
|
||
Git 的 tag 功能主要用于``给仓库历史中的某个特定提交打上“标签”``,通常用于标记版本发布点(例如 v1.0、v2.0 等),以``便于后续的版本定位、回溯和发布管理``。
|
||
|
||
### 标签类型
|
||
|
||
Git 提供两种类型的标签:
|
||
|
||
- 附注标签(Annotated Tag)会创建成一个完整的 Git 对象,存储打标签者的名字、邮箱、日期和标签说明,还可采用 GPG 进行签名。推荐用于正式发布,因为包含更多元数据和安全信息。
|
||
|
||
- 轻量标签(Lightweight Tag)实际上只是对某个提交的引用,不保存额外信息,类似一个固定的分支。适用于临时标记或非正式用途。
|
||
|
||
### 创建标签
|
||
|
||
- 创建附注标签
|
||
|
||
使用 -a 参数表示“annotated”,并用 -m 提供标签说明。例如,给当前提交创建一个名为 v1.0 的附注标签:
|
||
```
|
||
git tag -a v1.0 -m "发布版本 v1.0"
|
||
```
|
||
这会在 Git 数据库中生成一个完整的标签对象,可通过 git show v1.0 查看标签信息和对应的提交详情。
|
||
|
||
如果需要给旧提交贴标签,可以在命令末尾指定提交的 SHA 值(部分 SHA 也可):
|
||
```
|
||
git tag -a v1.0 <commit-sha> -m "发布版本 v1.0"
|
||
```
|
||
|
||
- 创建轻量标签
|
||
|
||
直接指定标签名即可,不加任何参数:
|
||
```
|
||
git tag v1.0-light
|
||
```
|
||
轻量标签仅仅是一个提交引用,因此查看时不会显示附加信息。
|
||
|
||
### 列出标签
|
||
- 列出所有标签
|
||
```
|
||
git tag
|
||
```
|
||
- 还可以使用通配符过滤:
|
||
```
|
||
git tag -l "v1.*"
|
||
```
|
||
这样便于管理和筛选大量标签。
|
||
- 查看标签详细信息
|
||
```
|
||
git show v1.0
|
||
```
|
||
这会显示标签对象的元数据以及对应的提交记录。
|
||
|
||
### 推送标签
|
||
``默认情况下,git push 不会将本地标签推送到远程仓库。推送标签有两种方式:``
|
||
- 推送单个标签
|
||
```
|
||
git push origin v1.0
|
||
```
|
||
- 一次性推送所有标签
|
||
```
|
||
git push origin --tags
|
||
```
|
||
### 删除标签
|
||
- 删除本地标签
|
||
```
|
||
git tag -d v1.0
|
||
```
|
||
- 删除远程标签
|
||
```
|
||
git push origin --delete v1.0
|
||
```
|
||
## 日志
|
||
|
||
如果你想了解本地仓库的历史记录,最简单的命令就是使用:
|
||
```
|
||
git log
|
||
```
|
||
- 只看某一个人的提交记录:
|
||
```
|
||
git log --author=bob
|
||
```
|
||
- 一个压缩后的每一条提交记录只占一行的输出:
|
||
```
|
||
git log --pretty=oneline
|
||
```
|
||
- 看看哪些文件改变了:
|
||
```
|
||
git log --name-status
|
||
```
|
||
|
||
## 删除前一个提交记录
|
||
有时候手滑或者不想使用一个commit说明,可以用以下命令撤销上一个 commit:
|
||
```
|
||
git reset --soft HEAD~1
|
||
```
|
||
这个命令会撤销上一个 commit,但保留文件修改(代码仍然在工作区)。适用于 想要重新提交(amend)或调整 commit 的情况。
|
||
|
||
如果你想彻底删除更改(不保留代码修改),可以使用:
|
||
```
|
||
git reset --hard HEAD~1
|
||
```
|
||
> 注意:--hard 会清除未提交的更改,无法恢复。
|
||
|
||
## `.git` 目录中主要文件和子目录的结构及其作用
|
||
|
||
### 📁 `.git` 目录结构概览
|
||
|
||
```
|
||
.git/
|
||
├── HEAD
|
||
├── config
|
||
├── description
|
||
├── hooks/
|
||
├── index
|
||
├── info/
|
||
│ └── exclude
|
||
├── logs/
|
||
│ ├── HEAD
|
||
│ └── refs/
|
||
├── objects/
|
||
│ ├── info/
|
||
│ └── pack/
|
||
├── refs/
|
||
│ ├── heads/
|
||
│ ├── remotes/
|
||
│ └── tags/
|
||
```
|
||
|
||
### 🗂️ 核心文件和目录说明
|
||
|
||
* **HEAD**:指向当前检出的分支或提交。例如,`ref: refs/heads/main` 表示当前位于 `main` 分支。
|
||
|
||
* **config**:仓库级别的配置文件,包含用户名、邮箱、远程仓库等信息.
|
||
|
||
* **description**:用于描述仓库,仅供 GitWeb 等工具使用。
|
||
|
||
* **hooks/**:存放 Git 钩子脚本的目录,可用于在特定操作前后执行自定义脚本,如 `pre-commit`、`post-merge` 等.
|
||
|
||
* **index**:暂存区(staging area)的索引文件,记录了即将提交的文件信息。
|
||
|
||
* **info/**:包含辅助信息,如 `exclude` 文件用于定义仓库级别的忽略规则。
|
||
|
||
* **logs/**:记录了引用(如分支、标签)的更新历史,有助于追踪操作记录。
|
||
|
||
* **objects/**:存储 Git 的所有对象,包括:
|
||
|
||
* **blob**:文件内容。
|
||
* **tree**:目录结构。
|
||
* **commit**:提交对象,记录提交信息和指向的树对象。
|
||
* **tag**:标签对象。
|
||
这些对象以 SHA-1 哈希命名,前两位作为子目录,其余作为文件名。
|
||
|
||
* **refs/**:存储所有引用,包括:
|
||
|
||
* **heads/**:本地分支。
|
||
* **remotes/**:远程分支。
|
||
* **tags/**:标签。
|
||
|
||
## Commit规范
|
||
|
||
### 提交信息的基本格式
|
||
|
||
- Header(头部)
|
||
格式:
|
||
```
|
||
<type>[可选的 scope]: <简短描述>
|
||
```
|
||
|
||
type 表示提交类型,如:feat(新功能)、fix(修复bug)等。
|
||
scope 是可选的,用于指出变更影响的模块或范围。
|
||
简短描述 用于概述本次提交的核心内容,通常使用祈使语气。
|
||
|
||
- Body(正文)
|
||
用于详细说明变更的动机、方法以及可能的影响,建议每行不超过 72 个字符。
|
||
|
||
- Footer(脚注)
|
||
可选部分,用来引用相关 issue、任务或说明破坏性变更(例如:BREAKING CHANGE: ...)。例如:
|
||
|
||
```
|
||
Fixes #123
|
||
```
|
||
这可以在提交后自动关闭相关问题。
|
||
|
||
### 常见的 Commit 类型
|
||
```
|
||
- feat:新功能的添加
|
||
示例:feat(user): 添加用户注册功能
|
||
|
||
- fix:修复 Bug
|
||
示例:fix(parser): 修复解析错误导致程序崩溃
|
||
|
||
- docs:文档相关的修改
|
||
示例:docs(readme): 更新使用说明
|
||
|
||
- style:代码格式、排版等不影响代码逻辑的调整
|
||
示例:style: 优化代码缩进和空格
|
||
|
||
- refactor:代码重构,不涉及新功能或 Bug 修复
|
||
示例:refactor: 优化数据处理逻辑
|
||
|
||
- perf:性能优化
|
||
示例:perf: 提升数据查询速度
|
||
|
||
- test:添加或修改测试代码
|
||
示例:test: 补充用户登录单元测试
|
||
|
||
- build:构建相关的变更,如依赖管理、构建脚本等
|
||
示例:build: 更新 webpack 配置
|
||
|
||
- ci:持续集成相关的修改
|
||
示例:ci: 调整 GitHub Actions 配置
|
||
|
||
- chore:其他杂项维护,不涉及源代码或测试文件的修改
|
||
示例:chore: 更新项目依赖
|
||
|
||
- revert:回滚到上一个版本的提交
|
||
示例:revert: 撤销上次提交
|
||
```
|
||
---
|
||
**Done.**
|