Compare commits
4 Commits
master
..
61bff7beac
| Author | SHA1 | Date | |
|---|---|---|---|
| 61bff7beac | |||
| e7de4af00b | |||
| b3f44d235a | |||
| 1d8ce5a16c |
@@ -6,9 +6,14 @@
|
|||||||
# ==================== 导航栏 ====================
|
# ==================== 导航栏 ====================
|
||||||
# 顶部导航菜单项 (图标来自 Font Awesome)
|
# 顶部导航菜单项 (图标来自 Font Awesome)
|
||||||
nav:
|
nav:
|
||||||
logo: # Logo 图片 URL (留空则显示站点标题)
|
logo: /images/aaaa.png # Logo 图片 URL (留空则显示站点标题)
|
||||||
display_title: true # 是否显示站点标题
|
display_title: true # 是否显示站点标题
|
||||||
|
|
||||||
|
# 站点头像(侧边栏/关于页显示,覆盖主题默认)
|
||||||
|
avatar:
|
||||||
|
img: /images/core.jpg # 头像图片路径
|
||||||
|
effect: false # 鼠标悬停旋转效果
|
||||||
|
|
||||||
menu:
|
menu:
|
||||||
首页: / || fas fa-home
|
首页: / || fas fa-home
|
||||||
归档: /archives/ || fas fa-archive
|
归档: /archives/ || fas fa-archive
|
||||||
@@ -16,6 +21,18 @@ menu:
|
|||||||
标签: /tags/ || fas fa-tags
|
标签: /tags/ || fas fa-tags
|
||||||
关于: /about/ || fas fa-heart
|
关于: /about/ || fas fa-heart
|
||||||
|
|
||||||
|
# ==================== 首页副标题 ====================
|
||||||
|
# 首页大标题下方的副标题(打字机效果)
|
||||||
|
subtitle:
|
||||||
|
enable: true # 是否显示首页副标题
|
||||||
|
effect: true # 是否启用打字机动画
|
||||||
|
source: 4 # 1:hitokoto 2:yiyan 3:今日诗词 4:固定文本(取自下方 sub)
|
||||||
|
sub:
|
||||||
|
- 何年是歸日,雨淚下孤舟。 # 固定文本模式下的副标题内容
|
||||||
|
typed_option: # 打字机动画参数 (effect 为 true 时生效)
|
||||||
|
loop: true
|
||||||
|
showCursor: false
|
||||||
|
|
||||||
# ==================== 首页封面 ====================
|
# ==================== 首页封面 ====================
|
||||||
# 封面大图 / 横幅设置
|
# 封面大图 / 横幅设置
|
||||||
index:
|
index:
|
||||||
|
|||||||
@@ -6,15 +6,15 @@
|
|||||||
|
|
||||||
# ==================== 站点基本信息 ====================
|
# ==================== 站点基本信息 ====================
|
||||||
# 网站标题
|
# 网站标题
|
||||||
title: 62117684535a5ba2
|
title: 个人自留地
|
||||||
# 网站副标题
|
# 网站副标题
|
||||||
subtitle: ''
|
subtitle: '何年是歸日,雨淚下孤舟。'
|
||||||
# 网站描述
|
# 网站描述
|
||||||
description: 4e004e2a7528 Hexo 642d5efa7684535a5ba2
|
description: 一个记录生活的博客
|
||||||
# 网站关键词,多个关键词可用逗号分隔或写成数组
|
# 网站关键词,多个关键词可用逗号分隔或写成数组
|
||||||
keywords:
|
keywords: 博客,知识库
|
||||||
# 作者名称
|
# 作者名称
|
||||||
author: wa feng
|
author: any
|
||||||
# 网站语言
|
# 网站语言
|
||||||
language: zh-CN
|
language: zh-CN
|
||||||
# 时区,留空时通常使用系统默认时区
|
# 时区,留空时通常使用系统默认时区
|
||||||
@@ -153,6 +153,96 @@ ignore:
|
|||||||
# 当前主题名称
|
# 当前主题名称
|
||||||
theme: butterfly
|
theme: butterfly
|
||||||
|
|
||||||
|
theme_config:
|
||||||
|
menu:
|
||||||
|
首页: / || fas fa-home
|
||||||
|
归档: /archives/ || fas fa-archive
|
||||||
|
分类: /categories/ || fas fa-folder-open
|
||||||
|
标签: /tags/ || fas fa-tags
|
||||||
|
关于: /about/ || fas fa-heart
|
||||||
|
|
||||||
|
index:
|
||||||
|
banner:
|
||||||
|
enable: true
|
||||||
|
img: https://api.btstu.cn/sjbz/api.php
|
||||||
|
|
||||||
|
theme_color:
|
||||||
|
enable: true
|
||||||
|
main: '#2D8CF0'
|
||||||
|
paginator: '#2D8CF0'
|
||||||
|
button_hover: '#EE2C50'
|
||||||
|
|
||||||
|
card:
|
||||||
|
enable: true
|
||||||
|
display: spacious
|
||||||
|
margin: 30px
|
||||||
|
|
||||||
|
sidebar:
|
||||||
|
enable: true
|
||||||
|
position: right
|
||||||
|
widgets:
|
||||||
|
- type: recent_posts
|
||||||
|
limit: 5
|
||||||
|
- type: tags
|
||||||
|
limit: 10
|
||||||
|
|
||||||
|
footer:
|
||||||
|
enable: true
|
||||||
|
since: 2026
|
||||||
|
|
||||||
|
social:
|
||||||
|
GitHub: https://github.com/ || fab fa-github
|
||||||
|
|
||||||
|
post:
|
||||||
|
meta:
|
||||||
|
date: true
|
||||||
|
updated: true
|
||||||
|
categories: true
|
||||||
|
copyright: true
|
||||||
|
|
||||||
|
search:
|
||||||
|
use: local_search
|
||||||
|
placeholder: 搜索文章
|
||||||
|
local_search:
|
||||||
|
preload: false
|
||||||
|
top_n_per_article: 1
|
||||||
|
unescape: false
|
||||||
|
pagination:
|
||||||
|
enable: false
|
||||||
|
hitsPerPage: 8
|
||||||
|
|
||||||
|
comments:
|
||||||
|
use: ""
|
||||||
|
|
||||||
|
inject:
|
||||||
|
head:
|
||||||
|
- <meta name="referrer" content="no-referrer">
|
||||||
|
- <link rel="stylesheet" href="/css/custom.css">
|
||||||
|
|
||||||
|
code_blocks:
|
||||||
|
theme: pale night
|
||||||
|
macStyle: true
|
||||||
|
height_limit: 800
|
||||||
|
word_wrap: true
|
||||||
|
copy: true
|
||||||
|
language: true
|
||||||
|
shrink: false
|
||||||
|
fullpage: false
|
||||||
|
|
||||||
|
disable_top_img: false
|
||||||
|
default_top_img: transparent
|
||||||
|
index_img: transparent
|
||||||
|
archive_img: false
|
||||||
|
tag_img: transparent
|
||||||
|
tag_per_img: transparent
|
||||||
|
category_img: transparent
|
||||||
|
category_per_img: transparent
|
||||||
|
footer_img: transparent
|
||||||
|
|
||||||
|
background: https://image.987119.xyz/uploads/2026/07/18c0005c5dac2c14635.webp
|
||||||
|
index_site_info_top: 200px
|
||||||
|
index_top_img_height: 400px
|
||||||
|
|
||||||
# ==================== 部署配置 ====================
|
# ==================== 部署配置 ====================
|
||||||
# 一键部署配置,需配合对应部署插件使用
|
# 一键部署配置,需配合对应部署插件使用
|
||||||
# 文档: https://hexo.io/docs/one-command-deployment
|
# 文档: https://hexo.io/docs/one-command-deployment
|
||||||
|
|||||||
@@ -3,10 +3,22 @@
|
|||||||
"version": "0.0.0",
|
"version": "0.0.0",
|
||||||
"private": true,
|
"private": true,
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "hexo generate",
|
"start": "powershell -ExecutionPolicy Bypass -File ./tools/blog.ps1 preview",
|
||||||
"clean": "hexo clean",
|
"clean": "hexo clean",
|
||||||
"deploy": "hexo deploy",
|
"build": "hexo generate",
|
||||||
"server": "hexo server"
|
"server": "hexo server",
|
||||||
|
"preview": "powershell -ExecutionPolicy Bypass -File ./tools/blog.ps1 preview",
|
||||||
|
"deploy": "powershell -ExecutionPolicy Bypass -File ./tools/blog.ps1 deploy",
|
||||||
|
"win:clean": "powershell -ExecutionPolicy Bypass -File ./tools/blog.ps1 clean",
|
||||||
|
"win:build": "powershell -ExecutionPolicy Bypass -File ./tools/blog.ps1 build",
|
||||||
|
"win:server": "powershell -ExecutionPolicy Bypass -File ./tools/blog.ps1 server",
|
||||||
|
"win:preview": "powershell -ExecutionPolicy Bypass -File ./tools/blog.ps1 preview",
|
||||||
|
"win:deploy": "powershell -ExecutionPolicy Bypass -File ./tools/blog.ps1 deploy",
|
||||||
|
"linux:clean": "bash ./tools/blog.sh clean",
|
||||||
|
"linux:build": "bash ./tools/blog.sh build",
|
||||||
|
"linux:server": "bash ./tools/blog.sh server",
|
||||||
|
"linux:preview": "bash ./tools/blog.sh preview",
|
||||||
|
"linux:deploy": "bash ./tools/blog.sh deploy"
|
||||||
},
|
},
|
||||||
"hexo": {
|
"hexo": {
|
||||||
"version": "8.1.2"
|
"version": "8.1.2"
|
||||||
|
|||||||
@@ -0,0 +1,923 @@
|
|||||||
|
---
|
||||||
|
title: Git使用教学
|
||||||
|
date: 2026-07-08 10:00:00
|
||||||
|
tags: [编程, 教程]
|
||||||
|
categories: 教程
|
||||||
|
cover: /images/Git使用教学/github.png
|
||||||
|
description: 认识一下Git!
|
||||||
|
---
|
||||||
|
|
||||||
|
## 认识一下Git!—简介
|
||||||
|
|
||||||
|
Git是当前最先进、最主流的**分布式**版本控制系统,免费、开源!核心能力就是版本控制。再具体一点,就是面向代码文件的版本控制,代码的任何修改历史都会被记录管理起来,意味着可以恢复到到以前的任意时刻状态。支持跨区域多人协作编辑,是团队项目开发的必备基础,所以Git也就成了程序员的必备技能。
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
**🟢主要特点**:
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
Git是Linux之父被迫开发的,为了解决Linux混乱的代码管理而开发的。Linux和Git之父 **李纳斯·托沃兹**(Linus Benedic Torvalds),来自1969年的芬兰。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Git是干什么的?—基础概念
|
||||||
|
|
||||||
|
先了解下Git的基本概念,及基本框架、工作流程。
|
||||||
|
|
||||||
|
### Git概念汇总🔥
|
||||||
|
|
||||||
|
| **概念名称** | **描述** |
|
||||||
|
| --- | --- |
|
||||||
|
| **工作区**(Workspace) | 就是在电脑里能看到的代码库目录,是我们搬砖的地方,新增、修改的文件会提交到暂存区 |
|
||||||
|
| **暂存区**(stage 或 index) | 用于临时存放文件的修改,实际上上它只是一个文件(`.git/index`),保存待提交的文件列表信息。 |
|
||||||
|
| **版本库/仓库**(Repository) | Git的管理仓库,管理版本的数据库,记录文件/目录状态的地方,所有内容的修改记录(版本)都在这里。 |
|
||||||
|
| **服务端/远程仓库**(origin 或 remote) | 服务端的版本库,专用的Git服务器,为多人共享提供服务,承担中心服务器的角色。本地版本库通过push指令把代码推送到服务端版本库。 |
|
||||||
|
| **本地仓库** | 用户机器上直接使用的的的版本库 |
|
||||||
|
| **分支**(Branch) | 分支是从主线分离出去的“副本”,可以独立操作而互不干扰,仓库初始化就有一个默认主分支`master`。 |
|
||||||
|
| **头**(HEAD) | HEAD类似一个“指针”,指向当前活动 **分支** 的 **最新版本**。 |
|
||||||
|
| **提交**(Commit) | 把暂存区的所有变更的内容提交到当前仓库的活动分支。 |
|
||||||
|
| **推送**(Push) | 将本地仓库的版本推送到服务端(远程)仓库,与他人共享。 |
|
||||||
|
| **拉取**(Pull) | 从服务端(远程)仓库获取更新到本地仓库,获取他人共享的更新。 |
|
||||||
|
| **获取**(Fetch) | 从服务端(远程)仓库更新,作用同拉取(Pull),区别是不会自动合并。 |
|
||||||
|
| **冲突**(Conflict) | 多人对同一文件的工作副本进行更改,并将这些更改合并到仓库时就会面临冲突,需要人工合并处理。 |
|
||||||
|
| **合并**(Merge) | 对有冲突的文件进行合并操作,Git会自动合并变更内容,无法自动处理的冲突内容会提示人工处理。 |
|
||||||
|
| **标签**(Tags) | 标签指的是某个分支某个特定时间点的状态,可以理解为提交记录的别名,常用来标记版本。 |
|
||||||
|
| **master**(或main) | 仓库的“`master`”分支,默认的主分支,初始化仓库就有了。Github上创建的仓库默认名字为“`main`” |
|
||||||
|
| **origin/master** | 表示远程仓库(`origin`)的“`master`”分支 |
|
||||||
|
| **origin/HEAD** | 表示远程仓库(`origin`)的最新提交的位置,一般情况等于“`origin/master`” |
|
||||||
|
|
||||||
|
### 工作区/暂存区/仓库
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
工作区、暂存区、版本库是Git最基本的概念,关系如下图:
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
**🔸工作区**(Workspace)就是在电脑里能看到的代码库目录,是我们搬砖的地方,新增、修改的文件会提交到暂存区。
|
||||||
|
|
||||||
|
**🔸暂存区**(stage或index) 用于临时存放文件的修改,实际上上它只是一个文件(.git/index),保存待提交的文件列表信息。
|
||||||
|
|
||||||
|
**🔸版本库/仓库**(Repository /rɪˈpɑːzətɔːri/ 仓库)Git的管理仓库,管理版本的数据库,记录文件/目录状态的地方,所有内容的修改记录(版本)都在这里。就是工作区目录下的隐藏文件夹`.git`,包含暂存区、分支、历史记录等信息。
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
如上图,为对应本地仓库目录的结构关系。
|
||||||
|
|
||||||
|
### Git基本流程(图)
|
||||||
|
|
||||||
|
Git的工作流程核心就下面几个步骤,掌握了就可以开始写Bug了。
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
### Git状态(图)
|
||||||
|
|
||||||
|
Git在执行提交的时候,不是直接将工作区的修改保存到仓库,而是将暂存区域的修改保存到仓库。要提交文件,首先需要把文件加入到暂存区域中。因此,Git管理的文件有三(+2)种状态:
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 起步:Git安装配置
|
||||||
|
|
||||||
|
Git官网:[www.git-scm.com/](https://www.git-scm.com/ "https://www.git-scm.com/") 下载安装包进行安装。Git的使用有两种方式:
|
||||||
|
|
||||||
|
指令`git --version`查看安装版本号
|
||||||
|
|
||||||
|
```git
|
||||||
|
$ git --version
|
||||||
|
git version 2.33.0.windows.2
|
||||||
|
```
|
||||||
|
|
||||||
|
> 📢 本文是在Windows 平台上完成的,不过这个对学习Git没什么影响。
|
||||||
|
|
||||||
|
### Git的配置文件
|
||||||
|
|
||||||
|
Git有三个主要的配置文件:三个配置文件的优先级是**① < ② < ③**
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
```bash
|
||||||
|
#查看git配置
|
||||||
|
git config --list
|
||||||
|
git config -l
|
||||||
|
|
||||||
|
#查看系统配置
|
||||||
|
git config --system --list
|
||||||
|
|
||||||
|
#查看当前用户(global)全局配置
|
||||||
|
git config --list --global
|
||||||
|
|
||||||
|
#查看当前仓库配置信息
|
||||||
|
git config --local --list
|
||||||
|
```
|
||||||
|
|
||||||
|
仓库的配置是上面多个配置的集合:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
$ git config --list
|
||||||
|
$ git config -l
|
||||||
|
diff.astextplain.textconv=astextplain
|
||||||
|
http.sslbackend=openssl
|
||||||
|
http.sslcainfo=C:/Program Files/Git/mingw64/ssl/certs/ca-bundle.crt
|
||||||
|
core.autocrlf=true
|
||||||
|
core.fscache=true
|
||||||
|
core.symlinks=false
|
||||||
|
pull.rebase=false
|
||||||
|
credential.helper=manager-core
|
||||||
|
credential.https://dev.azure.com.usehttppath=true
|
||||||
|
init.defaultbranch=master
|
||||||
|
user.name=Kanding
|
||||||
|
user.email=123anding@163.com
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3.2、配置-初始化用户
|
||||||
|
|
||||||
|
当安装Git后首先要做的事情是配置你的用户信息—— 告诉Git你是谁?配置 **用户名**、**邮箱地址**,每次提交文件时都会带上这个用户信息,查看历史记录时就知道是谁干的了。
|
||||||
|
|
||||||
|
配置用户信息:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
$ git config --global user.name "Your Name"
|
||||||
|
$ git config --global user.email "email@example.com"
|
||||||
|
# 配置完后,看看用户配置文件:
|
||||||
|
$ cat 'C:\Users\Kwongad\.gitconfig'
|
||||||
|
[user]
|
||||||
|
name = Kanding
|
||||||
|
email = 123anding@163.com
|
||||||
|
```
|
||||||
|
|
||||||
|
### 配置-忽略.gitignore
|
||||||
|
|
||||||
|
工作目录中的文件并不是全都需要纳入版本管理,如日志、临时文件、私有配置文件等不需要也不能纳入版本管理,那该怎么办呢?
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
在工作区根目录下创建“`.gitignore`”文件,文件中配置不需要进行版本管理的文件、文件夹。“`.gitignore`”文件本身是被纳入版本管理的,可以共享。有如下规则:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
#为注释
|
||||||
|
*.txt #忽略所有“.txt”结尾的文件
|
||||||
|
!lib.txt #lib.txt除外
|
||||||
|
/temp #仅忽略项目根目录下的temp文件,不包括其它目录下的temp,如不包括“src/temp”
|
||||||
|
build/ #忽略build/目录下的所有文件
|
||||||
|
doc/*.txt #会忽略 doc/notes.txt 但不包括 doc/server/arch.txt
|
||||||
|
```
|
||||||
|
|
||||||
|
> 📢 各种语言项目的常用`.gitignore`文件配置:[github.com/github/giti…](https://github.com/github/gitignore "https://github.com/github/gitignore")
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Git的GUI工具们
|
||||||
|
|
||||||
|
如果不想用命令行工具,完全可以安装一个Git的GUI工具,用的更简单、更舒服。不用记那么多命令了,极易上手,不过Git基础还是需要学习了解一下的。
|
||||||
|
|
||||||
|
> ❓对于Git,建议用命令行,这样你才能真的理解Git的思想? ✔️其实都只是工具而已,适合自己的就是最好的,没必要纠结,多写点Bug更重要!
|
||||||
|
|
||||||
|
### SourceTree
|
||||||
|
|
||||||
|
SourceTree的[官网](https://www.sourcetreeapp.com/ "https://www.sourcetreeapp.com/") 下载安装包,支持Window、Mac系统,按照提示完成安装。
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
### TortoiseGit
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
[TortoiseGit](https://tortoisegit.org/ "https://tortoisegit.org/") 官网下载安装包,及中文语言包,按照提示完成安装。小乌龟的Git是集成到操作系统里的,直接右键文件夹就可以进行Git操作了。
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
### VSCode中的Git
|
||||||
|
|
||||||
|
VSCode自带的Git工具基本已经可以满足日常使用了,既有可视化功能,也能敲命令,习惯了不就不用安装其他GUI工具了。不过还是可以再安装一些VSCode插件,来增强Git功能。
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Git使用入门
|
||||||
|
|
||||||
|
### 创建仓库
|
||||||
|
|
||||||
|
创建本地仓库的方法有两种:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 准备一个文件夹“KwebNote”作为仓库目录,命令行进入该文件夹
|
||||||
|
Kwongad@Kwongad-T14 MINGW64 ~
|
||||||
|
$ cd d:
|
||||||
|
Kwongad@Kwongad-T14 MINGW64 /d
|
||||||
|
$ cd Project_Files
|
||||||
|
Kwongad@Kwongad-T14 MINGW64 /d/Project_Files
|
||||||
|
# 多次cd指令进入到仓库目录KwebNote:“cd <目录名称>”指令进入目录,“cd ..”返回上级目录(有空格)
|
||||||
|
Kwongad@Kwongad-T14 MINGW64 /d/Project_Files/github.kwong/KwebNote
|
||||||
|
|
||||||
|
# 开始初始化项目,也可指定目录:git init [文件目录]
|
||||||
|
$ git init
|
||||||
|
Initialized empty Git repository in D:/Project_Files/github.Kwong/KwebNote/.git/
|
||||||
|
```
|
||||||
|
|
||||||
|
> **📢注意**:Git指令的执行,都需在仓库目录下。
|
||||||
|
|
||||||
|
创建完多出了一个被隐藏的`.git`目录,这就是本地仓库Git的工作场所。
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
克隆远程仓库,如在github上创建的仓库“`https://github.com/kwonganding/KWebNote.git`”
|
||||||
|
|
||||||
|
```bash
|
||||||
|
$ git clone 'https://github.com/kwonganding/KWebNote.git'
|
||||||
|
Cloning into 'KWebNote'...
|
||||||
|
remote: Enumerating objects: 108, done.
|
||||||
|
remote: Counting objects: 100% (108/108), done.
|
||||||
|
remote: Compressing objects: 100% (60/60), done.
|
||||||
|
remote: Total 108 (delta 48), reused 88 (delta 34), pack-reused 0
|
||||||
|
Receiving objects: 100% (108/108), 9.36 KiB | 736.00 KiB/s, done.
|
||||||
|
Resolving deltas: 100% (48/48), done.
|
||||||
|
```
|
||||||
|
|
||||||
|
会在当前目录下创建“KWebNote”项目目录。
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
### 暂存区add
|
||||||
|
|
||||||
|
可以简单理解为,`git add`命令就是把要提交的所有修改放到暂存区(Stage),然后,执行`git commit`就可以一次性把暂存区的所有修改提交到仓库。
|
||||||
|
|
||||||
|
| **指令** | **描述** |
|
||||||
|
| --- | --- |
|
||||||
|
| git add \[file1\] \[file2\] | 添加文件到暂存区,包括修改的文件、新增的文件 |
|
||||||
|
| git add \[dir\] | 同上,添加目录到暂存区,包括子目录 |
|
||||||
|
| git add . | 同上,添加**所有**修改、新增文件(未跟踪)到暂存区 |
|
||||||
|
| git rm \[file\] | 删除工作区文件,并且将这次删除放入暂存区 |
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 添加指定文件到暂存区,包括被修改的文件
|
||||||
|
$ git add [file1] [file2] ...
|
||||||
|
|
||||||
|
# 添加当前目录的所有文件到暂存区
|
||||||
|
$ git add .
|
||||||
|
|
||||||
|
# 删除工作区文件,并且将这次删除放入暂存区
|
||||||
|
$ git rm [file1] [file2] ...
|
||||||
|
|
||||||
|
# 改名文件,并且将这个改名放入暂存区
|
||||||
|
$ git mv [file-original] [file-renamed]
|
||||||
|
```
|
||||||
|
|
||||||
|
修改文件“R.md”,未暂存:
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
执行`git add .`暂存:
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
### 提交commit-记录
|
||||||
|
|
||||||
|
`git commit`提交是以时间顺序排列被保存到数据库中的,就如游戏关卡一样,每一次提交(commit)就会产生一条记录:`id + 描述 + 快照内容`。
|
||||||
|
|
||||||
|
多个提交就形成了一条时间线,每次提交完,会移动当前分支`master`、`HEAD`的“指针”位置。
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
Sourcetree上的历史记录:
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
> 📢一般情况,每完成一个小功能、一个Bu就可以提交一次,这样会形成比较清晰的历史记录。
|
||||||
|
|
||||||
|
**🔥指令:**
|
||||||
|
|
||||||
|
| **指令** | **描述** |
|
||||||
|
| --- | --- |
|
||||||
|
| git commit -m '说明' | 提交变更,参数`-m`设置提交的描述信息,应该正确提交,不带该参数会进入说明编辑模式 |
|
||||||
|
| git commit -a | 参数`-a`,表示直接从工作区提交到版本库,略过了`git add`步骤,不包括新增的文件 |
|
||||||
|
| git commit \[file\] | 提交暂存区的指定文件到仓库区 |
|
||||||
|
| git commit --amend -m | 使用一次新的`commit`,替代上一次提交,会修改`commit`的`hash`值(id) |
|
||||||
|
| git log -n20 | 查看日志(最近20条),不带参数`-n`则显示所有日志 |
|
||||||
|
| git log -n20 --oneline | 参数“`--oneline`”可以让日志输出更简洁(一行) |
|
||||||
|
| git log -n20 --graph | 参数“`--graph`”可视化显示分支关系 |
|
||||||
|
| git log --follow \[file\] | 显示某个文件的版本历史 |
|
||||||
|
| git blame \[file\] | 以列表形式显示指定文件的修改记录 |
|
||||||
|
| git **reflog** | 查看所有可用的历史版本记录(实际是HEAD变更记录),包含被回退的记录(**重要**) |
|
||||||
|
| git status | 查看本地仓库状态,比较常用的指令,加参数`-s`简洁模式 |
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
通过`git log`指令可以查看提交记录日志,可以很方便的查看每次提交修改了哪些文件,改了哪些内容,从而进行恢复等操作。
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 提交暂存区到仓库区
|
||||||
|
$ git commit -m [message]
|
||||||
|
# 提交所有修改到仓库
|
||||||
|
$ git commit -a -m'修改README的版权信息'
|
||||||
|
|
||||||
|
# 提交暂存区的指定文件到仓库区
|
||||||
|
$ git commit [file1] [file2] ... -m [message]
|
||||||
|
|
||||||
|
# 使用一次新的commit,替代上一次提交
|
||||||
|
# 如果代码没有任何新变化,则用来改写上一次commit的提交信息
|
||||||
|
$ git commit --amend -m [message]
|
||||||
|
|
||||||
|
$ git log -n2
|
||||||
|
commit 412b56448568ff362ef312507e78797befcf2846 (HEAD -> main)
|
||||||
|
Author: Kanding <123anding@163.com>
|
||||||
|
Date: Thu Dec 1 19:02:22 2022 +0800
|
||||||
|
|
||||||
|
commit c0ef58e3738f7d54545d8c13d603cddeee328fcb
|
||||||
|
Author: Kanding <123anding@163.com>
|
||||||
|
Date: Thu Dec 1 16:52:56 2022 +0800
|
||||||
|
|
||||||
|
# 用参数“--oneline”可以让日志输出更简洁(一行)
|
||||||
|
$ git log -n2 --oneline
|
||||||
|
5444126 (HEAD -> main, origin/main, origin/HEAD) Update README.md
|
||||||
|
228362e Merge branch 'main' of github.com:kwonganding/KWebNote
|
||||||
|
```
|
||||||
|
|
||||||
|
### Git的“指针”引用们
|
||||||
|
|
||||||
|
Git中最重要的就是提交记录了,其他如**标签**、**分支**、**HEAD** 都对提交记录的“指针”引用,指向这些提交记录,理解这一点很重要。
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
上图中:
|
||||||
|
|
||||||
|
打开这些文件内容看看,就更容易理解这些“指针”的真面目了。
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# tag
|
||||||
|
$ git tag -a 'v1' -m'v1版本'
|
||||||
|
$ cat .git/refs/tags/v1
|
||||||
|
a2e2c9caea35e176cf61e96ad9d5a929cfb82461
|
||||||
|
|
||||||
|
# main分支指向最新的提交
|
||||||
|
$ cat .git/refs/heads/main
|
||||||
|
8f4244550c2b6c23a543b741c362b13768442090
|
||||||
|
|
||||||
|
# HEAD指向当前活动分支
|
||||||
|
$ cat .git/HEAD
|
||||||
|
ref: refs/heads/main
|
||||||
|
|
||||||
|
# 切换到dev分支,HEAD指向了dev
|
||||||
|
$ git switch dev
|
||||||
|
Switched to branch 'dev'
|
||||||
|
$ cat .git/HEAD
|
||||||
|
ref: refs/heads/dev
|
||||||
|
```
|
||||||
|
|
||||||
|
这里的主分支名字为“`main`”,是因为该仓库是从Github上克隆的,Github上创建的仓库默认主分支名字就是“`main`”,本地创建的仓库默认主分支名字为“`master`”。
|
||||||
|
|
||||||
|
> **📢“指针”引用**:之所以用引号的“指针”,是为了便于统一和理解。和指针原理类似,都是一个指向,只是实际上可能更复杂一点,且不同的“指针”引用会有区别。
|
||||||
|
|
||||||
|
### 提交的唯一标识id,HEAD~n是什么意思?
|
||||||
|
|
||||||
|
每一个提交都有一个唯一标识,主要就是提交的`hash`值`commit id`,在很多指令中会用到,如版本回退、拣选提交等,需要指定一个提交。那标识唯一提交有两种方式:
|
||||||
|
|
||||||
|
通过`git log`、`git reflog`可以查看历史日志,可以看每次提交的唯一编号(hash)。区别是`git reflog`可以查看所有操作的记录(实际是HEAD变更记录),包括被撤销回退的提交记录。
|
||||||
|
|
||||||
|
```bash
|
||||||
|
$ git reflog -n10
|
||||||
|
5acc914 (HEAD -> main) HEAD@{0}: reset: moving to HEAD~
|
||||||
|
738748b (dev) HEAD@{1}: reset: moving to HEAD~
|
||||||
|
9312c3e HEAD@{2}: reset: moving to HEAD~
|
||||||
|
db03fcb HEAD@{3}: reset: moving to HEAD~
|
||||||
|
1b81fb3 HEAD@{4}: reset: moving to HEAD~
|
||||||
|
41ea423 HEAD@{5}: reset: moving to HEAD~
|
||||||
|
d3e15f9 HEAD@{6}: reset: moving to d3e15f9
|
||||||
|
1b81fb3 HEAD@{7}: reset: moving to HEAD~1
|
||||||
|
41ea423 HEAD@{8}: reset: moving to HEAD~
|
||||||
|
d3e15f9 HEAD@{9}: reset: moving to HEAD~
|
||||||
|
```
|
||||||
|
|
||||||
|
### 比较diff
|
||||||
|
|
||||||
|
`git diff`用来比较不同文件版本之间的差异。
|
||||||
|
|
||||||
|
| **指令** | **描述** |
|
||||||
|
| --- | --- |
|
||||||
|
| **git diff** | 查看暂存区和工作区的差异 |
|
||||||
|
| git diff \[file\] | 同上,指定文件 |
|
||||||
|
| git diff --cached | 查看已暂存的改动,就是暂存区与新版本`HEAD`进行比较 |
|
||||||
|
| git diff --staged | 同上 |
|
||||||
|
| git diff --cached \[file\] | 同上,指定文件 |
|
||||||
|
| git diff HEAD | 查看已暂存的+未暂存的所有改动,就是与最新版本`HEAD`进行比较 |
|
||||||
|
| git diff HEAD~ | 同上,与上一个版本比较。`HEAD~`表示上一个版本,`HEAD~10`为最近第10个版本 |
|
||||||
|
| git diff \[id\] \[id\] | 查看两次提交之间的差异 |
|
||||||
|
| git diff \[branch\] | 查看工作区和分支直接的差异 |
|
||||||
|
|
||||||
|
☘️画个图更清晰些:
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 查看文件的修改
|
||||||
|
$ git diff README.md
|
||||||
|
|
||||||
|
# 查看两次提交的差异
|
||||||
|
$ git diff 8f4244 1da22
|
||||||
|
|
||||||
|
# 显示今天你写了多少行代码:工作区+暂存区
|
||||||
|
$ git diff --shortstat "@{0 day ago}"
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 远程仓库
|
||||||
|
|
||||||
|
Git作为分布式的版本管理系统,每个终端都有自己的Git仓库。但团队协作还需一个中间仓库,作为中心,同步各个仓库。于是服务端(远程)仓库就来承担这个职责,服务端不仅有仓库,还配套相关管理功能。
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
可以用公共的Git服务器,也可以自己搭建一套Git服务器。
|
||||||
|
|
||||||
|
### 远程用户登录
|
||||||
|
|
||||||
|
Git服务器一般提供两种登录验证方式:
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
```bash
|
||||||
|
#查看当前远程仓库使用的那种协议连接:
|
||||||
|
$ git remote -v
|
||||||
|
origin git@github.com:kwonganding/KWebNote.git (fetch)
|
||||||
|
origin https://github.com/kwonganding/KWebNote.git (push)
|
||||||
|
|
||||||
|
# 更改为https地址,即可切换连接模式。还需要禁用掉SSL, 才能正常使用https管理git
|
||||||
|
git config --global http.sslVerify false
|
||||||
|
```
|
||||||
|
|
||||||
|
### 🔑远程用户登录:HTTS
|
||||||
|
|
||||||
|
基于HTTPS的地址连接远程仓库,Github的共有仓库克隆、拉取(pull)是不需要验证的。
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
```bash
|
||||||
|
$ git clone 'https://github.com/kwonganding/KWebNote.git'
|
||||||
|
Cloning into 'KWebNote'...
|
||||||
|
|
||||||
|
# 仓库配置文件“.git/config”
|
||||||
|
[remote "origin"]
|
||||||
|
url = https://github.com/kwonganding/KWebNote.git
|
||||||
|
fetch = +refs/heads/*:refs/remotes/origin/*
|
||||||
|
pushurl = https://github.com/kwonganding/KWebNote.git
|
||||||
|
```
|
||||||
|
|
||||||
|
推送(push)代码的时候就会提示输入用户名、密码了,否则无法提交。记住用户密码的方式有两种:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 直接修改仓库的配置文件“.git/config”
|
||||||
|
[remote "origin"]
|
||||||
|
url = https://用户名:密码@github.com/kwonganding/KWebNote.git
|
||||||
|
fetch = +refs/heads/*:refs/remotes/origin/*
|
||||||
|
pushurl = https://github.com/kwonganding/KWebNote.git
|
||||||
|
```
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 参数“--global”全局有效,也可以针对仓库设置“--local”
|
||||||
|
# store 表示永久存储,也可以设置临时存储
|
||||||
|
git config --global credential.helper store
|
||||||
|
|
||||||
|
# 存储内容如下,打开文件“仓库\.git\.git-credentials”
|
||||||
|
https://kwonganding:[加密内容付费可见]@github.com
|
||||||
|
```
|
||||||
|
|
||||||
|
### 🔑远程用户登录:SSH
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
SSH(Secure Shell,安全外壳)是一种网络安全协议,通过加密和认证机制实现安全的访问和文件传输等业务,多用来进行远程登录、数据传输。SSH通过公钥、私钥非对称加密数据,所以SSH需要生成一个公私钥对,公钥放服务器上,私有自己留着进行认证。
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
**① 生成公私钥**:通过Git指令`ssh-keygen -t rsa`生成公私钥,一路回车即可完成。生成在“`C:\Users\用户名\.ssh`”目录下,文件`id_rsa.pub`的内容就是公钥。
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
**② 配置公钥**:打开`id_rsa.pub`文件,复制内容。Github上,打开`Setting`➤ `SSH and GPG keys` ➤ `SSH keys` ➤ 按钮`New SSH key`,标题(Title)随意,秘钥内容粘贴进去即可。
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
SSH配置完后,可用`ssh -T git@github.com`来检测是否连接成功。
|
||||||
|
|
||||||
|
```bash
|
||||||
|
$ ssh -T git@github.com
|
||||||
|
Hi kwonganding! You've successfully authenticated, but GitHub does not provide shell access.
|
||||||
|
```
|
||||||
|
|
||||||
|
### 远程仓库指令🔥
|
||||||
|
|
||||||
|
| **指令** | **描述** |
|
||||||
|
| --- | --- |
|
||||||
|
| git clone \[git地址\] | 从远程仓库克隆到本地(当前目录) |
|
||||||
|
| git remote -v | 查看所有远程仓库,不带参数`-v`只显示名称 |
|
||||||
|
| git remote show \[remote\] | 显示某个远程仓库的信息 |
|
||||||
|
| git remote add \[name\] \[url\] | 增加一个新的远程仓库,并命名 |
|
||||||
|
| git remote rename \[old\] \[new\] | 修改远程仓库名称 |
|
||||||
|
| **git pull \[remote\] \[branch\]** | 取回远程仓库的变化,并与本地版本合并 |
|
||||||
|
| **git pull** | 同上,针对当前分支 |
|
||||||
|
| git fetch \[remote\] | 获取远程仓库的所有变动到本地仓库,不会自动合并!需要手动合并 |
|
||||||
|
| **git push** | 推送当前分支到远程仓库 |
|
||||||
|
| git push \[remote\] \[branch\] | 推送本地当前分支到远程仓库的指定分支 |
|
||||||
|
| git push \[remote\] --force/-f | 强行推送当前分支到远程仓库,即使有冲突,⚠️很危险! |
|
||||||
|
| git push \[remote\] --all | 推送所有分支到远程仓库 |
|
||||||
|
| git push –u | 参数`–u`表示与远程分支建立关联,第一次执行的时候用,后面就不需要了 |
|
||||||
|
| git remote rm \[remote-name\] | 删除远程仓库 |
|
||||||
|
| git pull --rebase | 使用rebase的模式进行合并 |
|
||||||
|
|
||||||
|
### 推送push/拉取pull
|
||||||
|
|
||||||
|
`git push`、`git pull`是团队协作中最常用的指令,用于同步本地、服务端的更新,与他人协作。
|
||||||
|
|
||||||
|
**🔸推送**(push):推送本地仓库到远程仓库。
|
||||||
|
|
||||||
|
**🔸拉取**(pull):从服务端(远程)仓库更新到本地仓库。
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
### fetch与pull有什么不同?
|
||||||
|
|
||||||
|
两者都是从服务端获取更新,主要区别是`fetch`不会自动合并,不会影响当前工作区内容。
|
||||||
|
|
||||||
|
> `git pull` = `git fetch` + `git merge`
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
```bash
|
||||||
|
# fetch只更新版本库
|
||||||
|
$ git fetch
|
||||||
|
remote: Enumerating objects: 5, done.
|
||||||
|
remote: Counting objects: 100% (5/5), done.
|
||||||
|
remote: Compressing objects: 100% (3/3), done.
|
||||||
|
remote: Total 3 (delta 2), reused 0 (delta 0), pack-reused 0
|
||||||
|
Unpacking objects: 100% (3/3), 663 bytes | 44.00 KiB/s, done.
|
||||||
|
From github.com:kwonganding/KWebNote
|
||||||
|
2ba12ca..c64f5b5 main -> origin/main
|
||||||
|
|
||||||
|
# 执行合并,合并自己
|
||||||
|
$ git merge
|
||||||
|
Updating 2ba12ca..c64f5b5
|
||||||
|
Fast-forward
|
||||||
|
README.md | 2 +-
|
||||||
|
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Git利器-分支
|
||||||
|
|
||||||
|
分支是从主线分离出去的“副本”,分支就像是平行宇宙,可独立发展,独立编辑、提交,也可以和其他分支合并。分支是Git的核心必杀利器之一,分支创建、切换、删除都非常快,他非常的轻量。所以,早建分支!多用分支!
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
### 分支Branch
|
||||||
|
|
||||||
|
比如有一个项目团队,准备10月份发布新版本,要新开发一堆黑科技功能,占领市场。你和小伙伴“小美”一起负责开发一个新功能A,开发周期2周,在这两周你们的代码不能影响其他人,不影响主分支。这个时候就可以为这个新功能创建一个分支,你们两在这个分支上干活,2周后代码开发完了、测试通过,就可以合并进要发版的开发分支了。安全、高效,不影响其他人工作,完美!
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
在实际项目中,一般会建几个主线分支。
|
||||||
|
|
||||||
|
**分支**就是指向某一个提交记录的“指针”引用,因此创建分支是非常快的,不管仓库多大。当我们运行`git branch dev`创建了一个名字为`dev`的分支,Git实际上是在`.git\refs\heads`下创建一个`dev`的引用文件(没有扩展名)。
|
||||||
|
|
||||||
|
```bash
|
||||||
|
$ git branch dev
|
||||||
|
$ cat .git/refs/heads/dev
|
||||||
|
ca88989e7c286fb4ba56785c2cd8727ea1a07b97
|
||||||
|
```
|
||||||
|
|
||||||
|
### 分支指令🔥
|
||||||
|
|
||||||
|
| **指令** | **描述** |
|
||||||
|
| --- | --- |
|
||||||
|
| git branch | 列出所有本地分支,加参数`-v`显示详细列表,下同 |
|
||||||
|
| git branch -r | 列出所有远程分支 |
|
||||||
|
| git branch -a | 列出所有本地分支和远程分支,用不同颜色区分 |
|
||||||
|
| git branch \[branch-name\] | 新建一个分支,但依然停留在当前分支 |
|
||||||
|
| git branch -d dev | 删除`dev`分支,-D(大写)强制删除 |
|
||||||
|
| **git checkout -b** dev | 从当前分支创建并切换到`dev`分支 |
|
||||||
|
| git checkout **\-b** feature1 dev | 从本地`dev`分支代码创建一个 `feature1`分支,并切换到新分支 |
|
||||||
|
| git branch \[branch\] \[commit\] | 新建一个分支,指向指定`commit id` |
|
||||||
|
| git branch --track \[branch\] \[remote-branch\] | 新建一个分支,与指定的远程分支建立关联 |
|
||||||
|
| git checkout -b hotfix remote hotfix | 从远端`remote`的`hotfix`分支创建本地`hotfix`分支 |
|
||||||
|
| git branch --set-upstream \[branch\] \[remote-branch\] | 在现有分支与指定的远程分支之间建立跟踪关联:
|
||||||
|
`git branch --set-upstream hotfix remote/hotfix` |
|
||||||
|
| **git checkout** \[branch-name\] | 切换到指定分支,并更新工作区 |
|
||||||
|
| git checkout . | 撤销工作区的(未暂存)修改,把暂存区恢复到工作区。 |
|
||||||
|
| git checkout HEAD . | 撤销工作区、暂存区的修改,用`HEAD`指向的当前分支最新版本替换 |
|
||||||
|
| git merge \[branch\] | 合并指定分支到当前分支 |
|
||||||
|
| **git merge --no-ff** dev | 合并`dev`分支到当前分支,参数`--no-ff`禁用快速合并模式 |
|
||||||
|
| git push origin --delete \[branch-name\] | 删除远程分支 |
|
||||||
|
| git rebase master | 将当前分支变基合并到`master`分支 |
|
||||||
|
| ✅switch:新的分支切换指令 | 切换功能和`checkout`一样,`switch`只单纯的用于切换 |
|
||||||
|
| git switch master | 切换到已有的`master`分支 |
|
||||||
|
| git switch -c dev | 创建并切换到新的`dev`分支 |
|
||||||
|
|
||||||
|
> 📢**关于 `checkout` 指令**:`checkout`是Git的底层指令,比较常用,也比较危险,他会重写工作区。支持的功能比较多,能撤销修改,能切换分支,这也导致了这个指令比较复杂。在Git 2.23版本以后,增加了`git switch`、`git reset`指令。
|
||||||
|
|
||||||
|
```bash
|
||||||
|
$ git branch
|
||||||
|
dev
|
||||||
|
* main
|
||||||
|
# 列出了当前的所有分支,星号“*”开头的“main”为当前活动分支。
|
||||||
|
```
|
||||||
|
|
||||||
|
### 分支的切换checkout
|
||||||
|
|
||||||
|
代码仓库可以有多个分支,`master`为默认的主分支,但只有一个分支在工作状态。所以要操作不同分支,需要切换到该分支,`HEAD`就是指向当前正在活动的分支。
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 切换到dev分支,HEAD指向了dev
|
||||||
|
# 此处 switch 作用同 checkout,switch只用于切换,不像checkout功能很多
|
||||||
|
$ git switch dev
|
||||||
|
Switched to branch 'dev'
|
||||||
|
$ cat .git/HEAD
|
||||||
|
ref: refs/heads/dev
|
||||||
|
```
|
||||||
|
|
||||||
|
使用 `git checkout dev`切换分支时,干了两件事:
|
||||||
|
|
||||||
|
此时的活动分支就是`dev`了,后续的提交就会更新到`dev`分支了。
|
||||||
|
|
||||||
|
**❓切换时还没提交的代码怎么办?**
|
||||||
|
|
||||||
|
### 合并merge&冲突
|
||||||
|
|
||||||
|
把两个分支的修改内容合并到一起,常用的合并指令`git merge [branch]`,将分支`[branch]`合并到当前分支。根据要合并的内容的不同,具体合并过程就会有多种情况。
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
### 🔸快速合并(Fast forward)
|
||||||
|
|
||||||
|
如下图,`master`分支么有任何提交,“`git merge dev`”合并分支`dev`到`master`,此时合并速度就非常快,直接移动`master`的“指针”引用到`dev`即可。这就是快速合并(Fast forward),不会产生新的提交。
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
> **📢强制不用快速合并**:`git merge --no-ff -m "merge with no-ff" dev`,参数`--no-ff`不启用快速合并,会产生一个新的合并提交记录。
|
||||||
|
|
||||||
|
### 🔸普通合并
|
||||||
|
|
||||||
|
如果`master`有变更,存在分支交叉,则会把两边的变更合并成一个提交。
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
上图中,创建`dev`分支后,两个分支都有修改提交,因此两个分支就不在一条顺序线上了,此时合并`dev`到`master`就得把他们的修改进行合并操作了。
|
||||||
|
|
||||||
|
### 🔸处理冲突<<<<<<< HEAD
|
||||||
|
|
||||||
|
在有冲突的文件中,`<<<<<<< HEAD`开头的内容就表示是有冲突的部分,需要人工处理,可以借助一些第三方的对比工具。人工处理完毕后,完成合并提交,才最终完成此次合并。`=======`分割线上方是当前分支的内容,下方是被合并分支的变更内容。
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
### 变基rebase
|
||||||
|
|
||||||
|
把两个分支的修改内容合并到一起的办法有两种:`merge` 和 `rebase`,作用都是一样的,区别是`rebase`的提交历史更简洁,干掉了分叉,merge的提交历史更完整。
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
```bash
|
||||||
|
$ git rebase master
|
||||||
|
$ git checkout master
|
||||||
|
$ git merge dev
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 标签管理
|
||||||
|
|
||||||
|
**标签**(Tags)指的是某个分支某个特定时间点的状态,是对某一个提交记录的的**固定**“指针”引用。一经创建,不可移动,存储在工作区根目录下`.git\refs\tags`。可以理解为某一次提交(编号)的别名,常用来标记版本。所以发布时,一般都会打一个版本标签,作为该版本的快照,指向对应提交`commit`。
|
||||||
|
|
||||||
|
当项目达到一个关键节点,希望永远记住那个特别的提交快照,你可以使用 `git tag` 给它打上标签。比如我们今天终于完成了V1.1版本的开发、测试,并成功上线了,那就可给今天最后这个提交打一个标签“V1.1”,便于版本管理。
|
||||||
|
|
||||||
|
默认标签是打在最新提交的commit上的,如果希望在指定的提交上打标签则带上提交编号(commit id):`git tag v0.9 f52c633`
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
| **指令** | **描述** |
|
||||||
|
| --- | --- |
|
||||||
|
| git tag | 查看标签列表 |
|
||||||
|
| git tag -l 'a\*' | 查看名称是“a”开头的标签列表,带查询参数 |
|
||||||
|
| git show \[tagname\] | 查看标签信息 |
|
||||||
|
| **git tag** \[tagname\] | 创建一个标签,默认标签是打在最新提交的commit上的 |
|
||||||
|
| git tag \[tagname\] \[commit id\] | 新建一个tag在指定commit上 |
|
||||||
|
| git tag -a v5.1 -m'v5.1版本' | 创建标签`v5.1.1039`,`-a`指定标签名,`-m`指定说明文字 |
|
||||||
|
| git tag -d \[tagname\] | 删除本地标签 |
|
||||||
|
| git checkout v5.1.1039 | 切换标签,同切换分支 |
|
||||||
|
| git push \[remote\] v5.1 | 推送标签,标签不会默认随代码推送推送到服务端 |
|
||||||
|
| git push \[remote\] --tags | 提交所有tag |
|
||||||
|
|
||||||
|
如果要推送某个标签到远程,使用命令`git push origin [tagname]`,或者,一次性推送全部到远程:`git push origin --tags`
|
||||||
|
|
||||||
|
> 📢注意:标签总是和某个commit挂钩。如果这个commit既出现在master分支,又出现在dev分支,那么在这两个分支上都可以看到这个标签。
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# tag
|
||||||
|
$ git tag -a 'v1' -m'v1版本'
|
||||||
|
$ cat .git/refs/tags/v1
|
||||||
|
a2e2c9caea35e176cf61e96ad9d5a929cfb82461
|
||||||
|
|
||||||
|
# 查看标签列表
|
||||||
|
$ git tag
|
||||||
|
v1
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 后悔药-怎么撤销变更?
|
||||||
|
|
||||||
|
发现写错了要回退怎么办?看看下面几种后悔指令吧!
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
### 后悔指令🔥
|
||||||
|
|
||||||
|
| **指令** | **描述** |
|
||||||
|
| --- | --- |
|
||||||
|
| git checkout . | 撤销工作区的(未暂存)修改,把暂存区恢复到工作区。不影响暂存区,如果没暂存,则撤销所有工作区修改 |
|
||||||
|
| git checkout \[file\] | 同上,`file`指定文件 |
|
||||||
|
| git checkout HEAD . | 撤销工作区、暂存区的修改,用`HEAD`指向的当前分支最新版本替换工作区、暂存区 |
|
||||||
|
| git checkout HEAD \[file\] | 同上,`file`指定文件 |
|
||||||
|
| | |
|
||||||
|
| git reset | 撤销暂存区状态,同`git reset HEAD`,不影响工作区 |
|
||||||
|
| git reset HEAD \[file\] | 同上,指定文件`file`,`HEAD`可省略 |
|
||||||
|
| git reset \[commit\] | 回退到指定版本,清空暂存区,不影响工作区。工作区需要手动`git checkout`签出 |
|
||||||
|
| git reset --soft \[commit\] | 移动分支`master`、`HEAD`到指定的版本,不影响暂存区、工作区,需手动`git checkout`签出更新 |
|
||||||
|
| git reset --hard HEAD | 撤销工作区、暂存区的修改,用当前最新版 |
|
||||||
|
| git reset --hard HEAD~ | 回退到上一个版本,并重置工作区、暂存区内容。 |
|
||||||
|
| git reset --hard \[commit\] | 回退到指定版本,并重置工作区、暂存区内容。 |
|
||||||
|
| | |
|
||||||
|
| git **revert**\[commit\] | 撤销一个提交,会用一个新的提交(原提交的逆向操作)来完成撤销操作,如果已`push`则重新`push`即可 |
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 只撤销工作区的修改(未暂存)
|
||||||
|
$ git checkout .
|
||||||
|
Updated 1 path from the index
|
||||||
|
|
||||||
|
# 撤销工作区、暂存区的修改
|
||||||
|
$ git checkout HEAD .
|
||||||
|
Updated 1 path from f951a96
|
||||||
|
```
|
||||||
|
|
||||||
|
### 回退版本reset
|
||||||
|
|
||||||
|
`reset`是专门用来撤销修改、回退版本的指令,支持的场景比较多,多种撤销姿势,所以参数组合也比较多。简单理解就是移动`master`分支、`HEAD`的“指针”地址,理解这一点就基本掌握`reset`了。
|
||||||
|
|
||||||
|
如下图:
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
`reset`有三种模式,对应三种参数:`mixed`(默认模式)、`soft`、`hard`。三种参数的主要区别就是对工作区、暂存区的操作不同。
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
| **模式名称\\** | **描述** | **HEAD的位置** | **暂存区** | **工作区** |
|
||||||
|
| --- | --- | --- | --- | --- |
|
||||||
|
| **soft** | 回退到某一个版本,工作区不变,需手动`git checkout` | 修改 | 不修改 | 不修改 |
|
||||||
|
| **mixed**(默认) | 撤销暂存区状态,不影响工作区,需手动`git checkout` | 修改 | 修改 | 不修改 |
|
||||||
|
| **hard** | 重置未提交修改(工作区、暂存区) | 修改 | 修改 | 修改 |
|
||||||
|
|
||||||
|
穿梭前,用`git log`可以查看提交历史,以便确定要回退到哪个版本。要重返未来,用`git reflog`查看命令历史,以便确定要回到未来的哪个版本。
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git reset [--soft | --mixed | --hard] [HEAD]
|
||||||
|
|
||||||
|
# 撤销暂存区
|
||||||
|
$ git reset
|
||||||
|
Unstaged changes after reset:
|
||||||
|
M R.md
|
||||||
|
|
||||||
|
# 撤销工作区、暂存区修改
|
||||||
|
$ git reset --hard HEAD
|
||||||
|
|
||||||
|
# 回退版本库到上一个版本,并重置工作区、暂存
|
||||||
|
$ git reset --hard HEAD~
|
||||||
|
|
||||||
|
# 回到原来的版本(恢复上一步的撤销操作),并重置工作区、暂存
|
||||||
|
$ git reset --hard 5f8b961
|
||||||
|
|
||||||
|
# 查看所有历史提交记录
|
||||||
|
$ git reflog
|
||||||
|
ccb9937 (HEAD -> main, origin/main, origin/HEAD) HEAD@{0}: commit: 报表新增导入功能
|
||||||
|
8f61a60 HEAD@{1}: commit: bug:修复报表导出bug
|
||||||
|
4869ff7 HEAD@{2}: commit: 用户报表模块开发
|
||||||
|
4b1028c HEAD@{3}: commit: 财务报表模块开发完成
|
||||||
|
```
|
||||||
|
|
||||||
|
### 撤销提交revert
|
||||||
|
|
||||||
|
安全的撤销某一个提交记录,基本原理就是生产一个新的提交,用原提交的逆向操作来完成撤销操作。注意,这不同于`reset`,`reset`是回退版本,revert只是用于撤销某一次历史提交,操作是比较安全的。
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
如上图:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# revert撤销指定的提交,“-m”附加说明
|
||||||
|
$ git revert 41ea42 -m'撤销对***的修改'
|
||||||
|
[main 967560f] Revert "123"
|
||||||
|
1 file changed, 1 deletion(-)
|
||||||
|
```
|
||||||
|
|
||||||
|
### checkout/reset/revert总结
|
||||||
|
|
||||||
|
| **标题 \\ 指令** | **checkout** | **reset** | **revert** |
|
||||||
|
| --- | --- | --- | --- |
|
||||||
|
| **主要作用(撤销)** | 撤销工作区、暂存区未提交修改 | 回退版本,重置工作区、暂存区 | 撤销某一次提交 |
|
||||||
|
| **撤销工作区** | git checkout \[file\] | git reset HEAD \[file\] | |
|
||||||
|
| **撤销工作区、暂存区** | git checkout HEAD \[file\] | git reset --hard HEAD \[file\] | |
|
||||||
|
| **回退版本** | | git reset --hard \[commit\] | |
|
||||||
|
| **安全性** | 只针对未提交修改,**安全** | 如回退了已`push`提交,**不安全** | **安全** |
|
||||||
|
|
||||||
|
可看出`reset`完全可以替代`checkout`来执行撤销、回退操作,`reset`本来也是专门用来干这个事情的,可以抛弃`checkout`了(撤销的时候)。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 工作中的Git实践
|
||||||
|
|
||||||
|
### Git flow
|
||||||
|
|
||||||
|
Git flow(Git工作流程)是指软件项目中的一种Git分支管理模型,经过了大量的实践和优化,被认为是现代敏捷软件开发和DevOps(开发、技术运营和质量保障三者的交集)的最佳实践。Git flow主要流程及关键分支:[原图地址-processon](https://www.processon.com/view/59ec836de4b0c86d400e99f1?fromnew=1 "https://www.processon.com/view/59ec836de4b0c86d400e99f1?fromnew=1")
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
**✅主分支:master**,稳定版本代码分支,对外可以随时编译发布的分支,不允许直接Push代码,只能请求合并(pull request),且只接受`hotfix`、`release`分支的代码合并。
|
||||||
|
|
||||||
|
**✅热修复分支:hotfix**,针对线上紧急问题、bug修复的代码分支,修复完后合并到主分支、开发分支。
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
**✅发版分支:release**,版本发布分支,用于迭代版本发布。迭代开发完成后,合并`dev`代码到`release`,在`release`分支上编译发布版本,以及修改bug(定时同步bug修改到`dev`分支)。测试完成后此版本可以作为发版使用,然后把稳定的代码push到`master`分支,并打上版本标签。
|
||||||
|
|
||||||
|
**✅开发分支:dev**,开发版本分支,针对迭代任务开发的分支,日常开发原则上都在此分支上面,迭代完成后合并到release分支,开发、发版两不误。
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
**✅其他开发分支:dev-xxx**,开发人员可以针对模块自己创建本地分支,开发完成后合并到dev开发分支,然后删除本地分支。
|
||||||
|
|
||||||
|
### 10.2、金屋藏娇stash
|
||||||
|
|
||||||
|
当你正在`dev`分支开发一个功能时,代码写了一半,突然有一个线上的bug急需要马上修改。`dev`分支Bug没写完,不方便提交,就不能切换到主分支去修复线上bug。Git提供一个`stash`功能,可以把当前**工作区、暂存区** 未提交的内容“隐藏”起来,就像什么都没发生一样。
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 有未提交修改,切换分支时报错
|
||||||
|
$ git checkout dev
|
||||||
|
error: Your local changes to the following files would be overwritten by checkout:
|
||||||
|
README.md
|
||||||
|
Please commit your changes or stash them before you switch branches.
|
||||||
|
Aborting
|
||||||
|
|
||||||
|
# 隐藏
|
||||||
|
$ git stash
|
||||||
|
Saved working directory and index state WIP on main: 2bc012c s
|
||||||
|
|
||||||
|
# 查看被隐藏的内容
|
||||||
|
$ git stash list
|
||||||
|
stash@{0}: WIP on main: 2bc012c s
|
||||||
|
|
||||||
|
# 比较一下,什么都没有,一切都没有发生过!
|
||||||
|
$ git diff
|
||||||
|
|
||||||
|
# 去其他分支修改bug,修复完成回到当前分支,恢复工作区
|
||||||
|
$ git stash pop
|
||||||
|
```
|
||||||
|
|
||||||
|
在上面示例中,有未提交修改,切换分支时报错。错误提示信息很明确了,`commit`提交或`stash`隐藏:`Please commit your changes or stash them before you switch branches.`
|
||||||
|
|
||||||
|
> 📢 如果切换分支时,未提交修改的内容没有冲突,是可以成功切换的,未提交修改会被带过去。
|
||||||
|
|
||||||
|
| **指令** | **描述** |
|
||||||
|
| --- | --- |
|
||||||
|
| git stash | 把未提交内容隐藏起来,包括未暂存、已暂存。 等以后恢复现场后继续工作 |
|
||||||
|
| git stash list | 查看所有被隐藏的内容列表 |
|
||||||
|
| git stash pop | 恢复被隐藏的内容,同时删除隐藏记录 |
|
||||||
|
| git stash save "message" | 同`git stash`,可以备注说明`message` |
|
||||||
|
| git stash apply | 恢复被隐藏的文件,但是隐藏记录不删除 |
|
||||||
|
| git stash drop | 删除隐藏记录 |
|
||||||
|
|
||||||
|
> 🪧当然这里先提交到本地也是可以的,只是提交不是一个完整的功能代码,而是残缺的一部分,影响也不大。
|
||||||
|
|
||||||
|
### 拣选提交cherry-pick
|
||||||
|
|
||||||
|
当有一个紧急bug,在`dev`上修复完,我们需要把`dev`上的这个bug修复所做的修改“复制”到`master`分支,但不想把整个dev合并过去。为了方便操作,Git专门提供了一个`cherry-pick`命令,让我们能复制一个特定的提交到当前分支,而不管这个提交在哪个分支。
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
如上图,操作过程相当于将该提交导出为补丁文件,然后在当前`HEAD`上重放,形成无论内容还是提交说明都一致的提交。
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 选择一个commit,合并进当前分支
|
||||||
|
$ git cherry-pick [commit]
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
原文链接 :https://juejin.cn/post/7195030726096453690
|
||||||
@@ -0,0 +1,249 @@
|
|||||||
|
---
|
||||||
|
title: Markdown 使用指南
|
||||||
|
date: 2026-07-08 22:00:00
|
||||||
|
tags: [Markdown, 写作, 教程]
|
||||||
|
categories: 教程
|
||||||
|
cover: /images/Markdown使用指南/markdown.webp
|
||||||
|
description: 从零掌握 Markdown 常用语法。每条语法都先给「写法」再给「效果」,照抄即可。
|
||||||
|
---
|
||||||
|
|
||||||
|
## 一、什么是 Markdown
|
||||||
|
|
||||||
|
Markdown 是一种**轻量级标记语言**,用纯文本编写,通过简单符号控制排版。优点:
|
||||||
|
|
||||||
|
- 语法简单,几分钟上手;
|
||||||
|
- 专注内容,不被格式打扰;
|
||||||
|
- 通用性强,几乎所有博客、笔记、代码托管平台都支持。
|
||||||
|
|
||||||
|
下面每一条都先给**写法**(源码),紧接着给出**效果**(实际渲染结果),方便对照学习。
|
||||||
|
|
||||||
|
## 二、标题
|
||||||
|
|
||||||
|
用 `#` 的数量表示标题层级,`#` 越多级别越低(建议全文只有一个 `#` 一级标题)。
|
||||||
|
|
||||||
|
**写法**
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
# 一级标题
|
||||||
|
## 二级标题
|
||||||
|
### 三级标题
|
||||||
|
#### 四级标题
|
||||||
|
```
|
||||||
|
|
||||||
|
**效果**(演示三级与四级,一、二级即本文各章节样式)
|
||||||
|
|
||||||
|
### 这是三级标题的效果
|
||||||
|
|
||||||
|
#### 这是四级标题的效果
|
||||||
|
|
||||||
|
## 三、文本样式
|
||||||
|
|
||||||
|
### 加粗、斜体、删除线
|
||||||
|
|
||||||
|
**写法**
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
**加粗文字**
|
||||||
|
*斜体文字*
|
||||||
|
***加粗斜体***
|
||||||
|
~~删除线~~
|
||||||
|
```
|
||||||
|
|
||||||
|
**效果**
|
||||||
|
|
||||||
|
**加粗文字**
|
||||||
|
*斜体文字*
|
||||||
|
***加粗斜体***
|
||||||
|
~~删除线~~
|
||||||
|
|
||||||
|
### 高亮与上下标
|
||||||
|
|
||||||
|
> 以下为扩展语法,**标准 Markdown 不渲染**,仅在 Typora、部分平台支持,本站点同样不会渲染,这里如实展示原样。
|
||||||
|
|
||||||
|
**写法**
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
==高亮文字==
|
||||||
|
上标:x^2^
|
||||||
|
下标:H~2~O
|
||||||
|
```
|
||||||
|
|
||||||
|
**效果(原样,因本站点不支持)**
|
||||||
|
|
||||||
|
==高亮文字==
|
||||||
|
上标:x^2^
|
||||||
|
下标:H~2~O
|
||||||
|
|
||||||
|
## 四、列表
|
||||||
|
|
||||||
|
### 无序列表
|
||||||
|
|
||||||
|
**写法**
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
- 项目一
|
||||||
|
- 项目二
|
||||||
|
- 子项目(前面加两个空格缩进)
|
||||||
|
```
|
||||||
|
|
||||||
|
**效果**
|
||||||
|
|
||||||
|
- 项目一
|
||||||
|
- 项目二
|
||||||
|
- 子项目(前面加两个空格缩进)
|
||||||
|
|
||||||
|
### 有序列表
|
||||||
|
|
||||||
|
**写法**
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
1. 第一步
|
||||||
|
2. 第二步
|
||||||
|
3. 第三步
|
||||||
|
```
|
||||||
|
|
||||||
|
**效果**
|
||||||
|
|
||||||
|
1. 第一步
|
||||||
|
2. 第二步
|
||||||
|
3. 第三步
|
||||||
|
|
||||||
|
### 任务列表
|
||||||
|
|
||||||
|
> 任务列表为 GitHub 扩展语法,本站点不渲染复选框,这里展示原样写法。
|
||||||
|
|
||||||
|
**写法**
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
- [x] 已完成的任务
|
||||||
|
- [ ] 待完成的任务
|
||||||
|
```
|
||||||
|
|
||||||
|
**效果(原样)**
|
||||||
|
|
||||||
|
- [x] 已完成的任务
|
||||||
|
- [ ] 待完成的任务
|
||||||
|
|
||||||
|
## 五、链接与图片
|
||||||
|
|
||||||
|
### 链接
|
||||||
|
|
||||||
|
**写法**
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
[显示文字](https://example.com "可选标题")
|
||||||
|
```
|
||||||
|
|
||||||
|
**效果**
|
||||||
|
|
||||||
|
[显示文字](https://example.com "可选标题")
|
||||||
|
|
||||||
|
### 图片
|
||||||
|
|
||||||
|
**写法**
|
||||||
|
|
||||||
|
```markdown
|
||||||
|

|
||||||
|
```
|
||||||
|
|
||||||
|
**效果**
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
> 提示:图片语法与链接几乎一样,区别仅在于最前面多一个 `!`。本地图片可写成 `/images/文章名/图片.webp`。
|
||||||
|
|
||||||
|
## 六、代码
|
||||||
|
|
||||||
|
### 行内代码
|
||||||
|
|
||||||
|
**写法**
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
使用 `npm install` 安装依赖
|
||||||
|
```
|
||||||
|
|
||||||
|
**效果**
|
||||||
|
|
||||||
|
使用 `npm install` 安装依赖
|
||||||
|
|
||||||
|
### 代码块与语法高亮
|
||||||
|
|
||||||
|
**写法**(用四个反引号包裹,内部的三反引号才能原样显示)
|
||||||
|
|
||||||
|
````markdown
|
||||||
|
```python
|
||||||
|
def hello():
|
||||||
|
print("Hello, Markdown!")
|
||||||
|
```
|
||||||
|
````
|
||||||
|
|
||||||
|
**效果**
|
||||||
|
|
||||||
|
```python
|
||||||
|
def hello():
|
||||||
|
print("Hello, Markdown!")
|
||||||
|
```
|
||||||
|
|
||||||
|
## 七、引用
|
||||||
|
|
||||||
|
**写法**
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
> 引用内容
|
||||||
|
>
|
||||||
|
> > 嵌套的二级引用
|
||||||
|
```
|
||||||
|
|
||||||
|
**效果**
|
||||||
|
|
||||||
|
> 引用内容
|
||||||
|
>
|
||||||
|
> > 嵌套的二级引用
|
||||||
|
|
||||||
|
## 八、表格
|
||||||
|
|
||||||
|
**写法**
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
| 语法 | 含义 | 示例 |
|
||||||
|
| ------- | ------ | ------- |
|
||||||
|
| `**x**` | 加粗 | **x** |
|
||||||
|
| `*x*` | 斜体 | *x* |
|
||||||
|
| `` `x` `` | 行内代码 | `x` |
|
||||||
|
```
|
||||||
|
|
||||||
|
**效果**
|
||||||
|
|
||||||
|
| 语法 | 含义 | 示例 |
|
||||||
|
| ------- | ------ | ------- |
|
||||||
|
| `**x**` | 加粗 | **x** |
|
||||||
|
| `*x*` | 斜体 | *x* |
|
||||||
|
| `` `x` `` | 行内代码 | `x` |
|
||||||
|
|
||||||
|
## 九、分隔线
|
||||||
|
|
||||||
|
连续三个以上的 `-`、`*` 或 `_`(独占一行)即为分隔线。
|
||||||
|
|
||||||
|
**写法**
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
---
|
||||||
|
```
|
||||||
|
|
||||||
|
**效果**
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 十、实用扩展(平台相关)
|
||||||
|
|
||||||
|
以下语法并非所有平台都支持,按平台能力选用:
|
||||||
|
|
||||||
|
- **脚注**:`正文[^1]` 配合文末 `[^1]: 注释内容`;
|
||||||
|
- **自动目录**:部分编辑器支持 `[TOC]`;
|
||||||
|
- **emoji**:`:smile:` 显示 😄(依赖平台);
|
||||||
|
- **数学公式**:`$E=mc^2$` 行内,`$$...$$` 独立公式块;
|
||||||
|
- **流程图**:GitHub 等支持 Mermaid 语法。
|
||||||
|
|
||||||
|
## 总结
|
||||||
|
|
||||||
|
掌握标题、文本样式、列表、链接图片、代码、引用、表格、分隔线,已能应付 90% 写作场景。核心心法:**先写内容,再管格式**,其余交给 Markdown。把本文收藏,写文章时对照查阅即可。
|
||||||
@@ -1,38 +0,0 @@
|
|||||||
---
|
|
||||||
title: Hello World
|
|
||||||
---
|
|
||||||
Welcome to [Hexo](https://hexo.io/)! This is your very first post. Check [documentation](https://hexo.io/docs/) for more info. If you get any problems when using Hexo, you can find the answer in [troubleshooting](https://hexo.io/docs/troubleshooting.html) or you can ask me on [GitHub](https://github.com/hexojs/hexo/issues).
|
|
||||||
|
|
||||||
## Quick Start
|
|
||||||
|
|
||||||
### Create a new post
|
|
||||||
|
|
||||||
``` bash
|
|
||||||
$ hexo new "My New Post"
|
|
||||||
```
|
|
||||||
|
|
||||||
More info: [Writing](https://hexo.io/docs/writing.html)
|
|
||||||
|
|
||||||
### Run server
|
|
||||||
|
|
||||||
``` bash
|
|
||||||
$ hexo server
|
|
||||||
```
|
|
||||||
|
|
||||||
More info: [Server](https://hexo.io/docs/server.html)
|
|
||||||
|
|
||||||
### Generate static files
|
|
||||||
|
|
||||||
``` bash
|
|
||||||
$ hexo generate
|
|
||||||
```
|
|
||||||
|
|
||||||
More info: [Generating](https://hexo.io/docs/generating.html)
|
|
||||||
|
|
||||||
### Deploy to remote sites
|
|
||||||
|
|
||||||
``` bash
|
|
||||||
$ hexo deploy
|
|
||||||
```
|
|
||||||
|
|
||||||
More info: [Deployment](https://hexo.io/docs/one-command-deployment.html)
|
|
||||||
@@ -92,10 +92,6 @@ html[data-theme="dark"] #article-container table:not(.gist table) tbody tr:nth-c
|
|||||||
padding-bottom: 0.3rem;
|
padding-bottom: 0.3rem;
|
||||||
border-bottom: 2px solid var(--border-color);
|
border-bottom: 2px solid var(--border-color);
|
||||||
}
|
}
|
||||||
#article-container h1::before, #article-container h2::before, #article-container h3::before {
|
|
||||||
content: "# ";
|
|
||||||
color: var(--btn-bg);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ==================== 文章标题栏字体颜色(明亮模式) ==================== */
|
/* ==================== 文章标题栏字体颜色(明亮模式) ==================== */
|
||||||
html:not([data-theme="dark"]) #post-info .post-title {
|
html:not([data-theme="dark"]) #post-info .post-title {
|
||||||
|
|||||||
|
After Width: | Height: | Size: 9.0 KiB |
|
After Width: | Height: | Size: 7.0 KiB |
|
After Width: | Height: | Size: 18 KiB |
|
After Width: | Height: | Size: 13 KiB |
|
After Width: | Height: | Size: 26 KiB |
|
After Width: | Height: | Size: 14 KiB |
|
After Width: | Height: | Size: 47 KiB |
|
After Width: | Height: | Size: 21 KiB |
|
After Width: | Height: | Size: 36 KiB |
|
After Width: | Height: | Size: 2.6 KiB |
|
After Width: | Height: | Size: 10 KiB |
|
After Width: | Height: | Size: 15 KiB |
|
After Width: | Height: | Size: 4.3 KiB |
|
After Width: | Height: | Size: 10 KiB |
|
After Width: | Height: | Size: 29 KiB |
|
After Width: | Height: | Size: 21 KiB |
|
After Width: | Height: | Size: 14 KiB |
|
After Width: | Height: | Size: 14 KiB |
|
After Width: | Height: | Size: 8.5 KiB |
|
After Width: | Height: | Size: 13 KiB |
|
After Width: | Height: | Size: 33 KiB |
|
After Width: | Height: | Size: 6.0 KiB |
|
After Width: | Height: | Size: 24 KiB |
|
After Width: | Height: | Size: 9.4 KiB |
|
After Width: | Height: | Size: 30 KiB |
|
After Width: | Height: | Size: 46 KiB |
|
After Width: | Height: | Size: 26 KiB |
|
After Width: | Height: | Size: 16 KiB |
|
After Width: | Height: | Size: 3.6 KiB |
|
After Width: | Height: | Size: 13 KiB |
|
After Width: | Height: | Size: 54 KiB |
|
After Width: | Height: | Size: 15 KiB |
|
After Width: | Height: | Size: 6.2 KiB |
|
After Width: | Height: | Size: 12 KiB |
|
After Width: | Height: | Size: 31 KiB |
|
After Width: | Height: | Size: 12 KiB |
|
After Width: | Height: | Size: 4.2 KiB |
|
After Width: | Height: | Size: 6.9 KiB |
|
After Width: | Height: | Size: 11 KiB |
|
After Width: | Height: | Size: 21 KiB |
|
After Width: | Height: | Size: 6.1 KiB |
|
After Width: | Height: | Size: 20 KiB |
|
After Width: | Height: | Size: 4.6 KiB |
|
After Width: | Height: | Size: 16 KiB |
|
After Width: | Height: | Size: 17 KiB |
|
After Width: | Height: | Size: 16 KiB |
|
After Width: | Height: | Size: 8.5 KiB |
|
After Width: | Height: | Size: 10 KiB |
|
After Width: | Height: | Size: 9.4 KiB |
|
After Width: | Height: | Size: 22 KiB |
|
After Width: | Height: | Size: 12 KiB |
|
After Width: | Height: | Size: 5.2 KiB |
|
After Width: | Height: | Size: 6.2 KiB |
|
After Width: | Height: | Size: 445 KiB |
|
After Width: | Height: | Size: 82 KiB |
@@ -0,0 +1,122 @@
|
|||||||
|
param(
|
||||||
|
# 要执行的命令:help / clean / build / server / preview / deploy
|
||||||
|
[Parameter(Position=0)]
|
||||||
|
[ValidateSet('help','clean','build','server','preview','deploy')]
|
||||||
|
[string]$Command = 'help'
|
||||||
|
)
|
||||||
|
|
||||||
|
# 只要出现错误就立即停止,避免后续命令继续执行
|
||||||
|
$ErrorActionPreference = 'Stop'
|
||||||
|
|
||||||
|
# 以脚本所在目录为基准,切回博客根目录
|
||||||
|
$root = Split-Path -Parent $PSScriptRoot
|
||||||
|
Set-Location $root
|
||||||
|
|
||||||
|
# 环境变量可覆盖默认值
|
||||||
|
$port = if ($env:PORT) { $env:PORT } else { '4000' }
|
||||||
|
$hostName = if ($env:HOST) { $env:HOST } else { '127.0.0.1' }
|
||||||
|
$branch = if ($env:BRANCH) { $env:BRANCH } else { 'main' }
|
||||||
|
|
||||||
|
function Show-Usage {
|
||||||
|
@"
|
||||||
|
博客脚本用法:
|
||||||
|
./tools/blog.ps1 clean # 清理缓存和 public 目录
|
||||||
|
./tools/blog.ps1 build # 生成静态文件
|
||||||
|
./tools/blog.ps1 server # 启动本地服务
|
||||||
|
./tools/blog.ps1 preview # 清理 + 生成 + 启动预览
|
||||||
|
./tools/blog.ps1 deploy # 清理 + 生成 + git 提交 + 推送
|
||||||
|
|
||||||
|
可选环境变量:
|
||||||
|
PORT=4000 预览端口
|
||||||
|
HOST=127.0.0.1 监听地址
|
||||||
|
BRANCH=main 推送分支
|
||||||
|
"@
|
||||||
|
}
|
||||||
|
|
||||||
|
function Invoke-Hexo {
|
||||||
|
# 把后续参数原样转发给 hexo
|
||||||
|
param([Parameter(ValueFromRemainingArguments = $true)][string[]]$HexoArgs)
|
||||||
|
|
||||||
|
& npx hexo @HexoArgs
|
||||||
|
if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE }
|
||||||
|
}
|
||||||
|
|
||||||
|
function Add-BlogFiles {
|
||||||
|
# 只暂存博客相关文件,避免误把 node_modules、public 或其他杂项提交进去
|
||||||
|
$paths = @(
|
||||||
|
'_config.yml',
|
||||||
|
'_config.butterfly.yml',
|
||||||
|
'_config.landscape.yml',
|
||||||
|
'package.json',
|
||||||
|
'package-lock.json',
|
||||||
|
'scaffolds',
|
||||||
|
'source',
|
||||||
|
'themes',
|
||||||
|
'tools'
|
||||||
|
)
|
||||||
|
|
||||||
|
$existingPaths = @()
|
||||||
|
foreach ($path in $paths) {
|
||||||
|
if (Test-Path $path) {
|
||||||
|
$existingPaths += $path
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($existingPaths.Count -eq 0) {
|
||||||
|
Write-Host '[deploy] 没有找到可暂存的博客文件'
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
git add -- @existingPaths
|
||||||
|
if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE }
|
||||||
|
}
|
||||||
|
|
||||||
|
switch ($Command) {
|
||||||
|
'clean' {
|
||||||
|
Write-Host '[clean] 清理生成缓存'
|
||||||
|
Invoke-Hexo clean
|
||||||
|
}
|
||||||
|
'build' {
|
||||||
|
Write-Host '[build] 生成静态文件'
|
||||||
|
Invoke-Hexo generate
|
||||||
|
}
|
||||||
|
'server' {
|
||||||
|
Write-Host "[server] 启动预览服务:http://${hostName}:${port}"
|
||||||
|
Invoke-Hexo server -i $hostName -p $port
|
||||||
|
}
|
||||||
|
'preview' {
|
||||||
|
Write-Host '[preview] 清理并生成静态文件'
|
||||||
|
Invoke-Hexo clean
|
||||||
|
Invoke-Hexo generate
|
||||||
|
|
||||||
|
Write-Host "[preview] 启动预览服务:http://${hostName}:${port}"
|
||||||
|
Invoke-Hexo server -i $hostName -p $port
|
||||||
|
}
|
||||||
|
'deploy' {
|
||||||
|
Write-Host '[deploy] 清理并生成静态文件'
|
||||||
|
Invoke-Hexo clean
|
||||||
|
Invoke-Hexo generate
|
||||||
|
|
||||||
|
Write-Host '[deploy] 只暂存博客相关改动'
|
||||||
|
Add-BlogFiles
|
||||||
|
|
||||||
|
# 没有变更就不提交也不推送
|
||||||
|
git diff --cached --quiet
|
||||||
|
if ($LASTEXITCODE -eq 0) {
|
||||||
|
Write-Host '[deploy] 没有可提交的改动,跳过 commit/push'
|
||||||
|
exit 0
|
||||||
|
}
|
||||||
|
|
||||||
|
$timestamp = Get-Date -Format 'yyyy-MM-dd HH:mm:ss'
|
||||||
|
Write-Host "[deploy] 提交改动:chore: deploy blog $timestamp"
|
||||||
|
git commit -m "chore: deploy blog $timestamp"
|
||||||
|
if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE }
|
||||||
|
|
||||||
|
Write-Host "[deploy] 推送到 origin/$branch"
|
||||||
|
git push origin $branch
|
||||||
|
if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE }
|
||||||
|
}
|
||||||
|
default {
|
||||||
|
Show-Usage
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,114 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
# 切换到博客根目录,确保从任何位置执行都能正常工作
|
||||||
|
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||||
|
cd "$ROOT_DIR"
|
||||||
|
|
||||||
|
# 允许用环境变量覆盖默认值
|
||||||
|
PORT="${PORT:-4000}"
|
||||||
|
HOST="${HOST:-127.0.0.1}"
|
||||||
|
BRANCH="${BRANCH:-main}"
|
||||||
|
|
||||||
|
usage() {
|
||||||
|
cat <<'EOF'
|
||||||
|
博客脚本用法:
|
||||||
|
./tools/blog.sh clean # 清理缓存和 public 目录
|
||||||
|
./tools/blog.sh build # 生成静态文件
|
||||||
|
./tools/blog.sh server # 启动本地服务
|
||||||
|
./tools/blog.sh preview # 清理 + 生成 + 启动预览
|
||||||
|
./tools/blog.sh deploy # 清理 + 生成 + git 提交 + 推送
|
||||||
|
|
||||||
|
可选环境变量:
|
||||||
|
PORT=4000 预览端口
|
||||||
|
HOST=127.0.0.1 监听地址
|
||||||
|
BRANCH=main 推送分支
|
||||||
|
EOF
|
||||||
|
}
|
||||||
|
|
||||||
|
hexo_run() {
|
||||||
|
# 把参数原样传给 hexo
|
||||||
|
npx hexo "$@"
|
||||||
|
}
|
||||||
|
|
||||||
|
add_blog_files() {
|
||||||
|
# 只暂存博客相关文件,避免误把 node_modules、public 或其他杂项提交进去
|
||||||
|
local paths=(
|
||||||
|
"_config.yml"
|
||||||
|
"_config.butterfly.yml"
|
||||||
|
"_config.landscape.yml"
|
||||||
|
"package.json"
|
||||||
|
"package-lock.json"
|
||||||
|
"scaffolds"
|
||||||
|
"source"
|
||||||
|
"themes"
|
||||||
|
"tools"
|
||||||
|
)
|
||||||
|
|
||||||
|
local existing=()
|
||||||
|
local path
|
||||||
|
for path in "${paths[@]}"; do
|
||||||
|
if [[ -e "$path" ]]; then
|
||||||
|
existing+=("$path")
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
if [[ ${#existing[@]} -eq 0 ]]; then
|
||||||
|
echo '[deploy] 没有找到可暂存的博客文件' >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
git add -- "${existing[@]}"
|
||||||
|
}
|
||||||
|
|
||||||
|
case "${1:-help}" in
|
||||||
|
clean)
|
||||||
|
echo '[clean] 清理生成缓存'
|
||||||
|
hexo_run clean
|
||||||
|
;;
|
||||||
|
build)
|
||||||
|
echo '[build] 生成静态文件'
|
||||||
|
hexo_run generate
|
||||||
|
;;
|
||||||
|
server)
|
||||||
|
echo "[server] 启动预览服务:http://${HOST}:${PORT}"
|
||||||
|
hexo_run server -i "$HOST" -p "$PORT"
|
||||||
|
;;
|
||||||
|
preview)
|
||||||
|
echo '[preview] 清理并生成静态文件'
|
||||||
|
hexo_run clean
|
||||||
|
hexo_run generate
|
||||||
|
|
||||||
|
echo "[preview] 启动预览服务:http://${HOST}:${PORT}"
|
||||||
|
hexo_run server -i "$HOST" -p "$PORT"
|
||||||
|
;;
|
||||||
|
deploy)
|
||||||
|
echo '[deploy] 清理并生成静态文件'
|
||||||
|
hexo_run clean
|
||||||
|
hexo_run generate
|
||||||
|
|
||||||
|
echo '[deploy] 只暂存博客相关改动'
|
||||||
|
add_blog_files
|
||||||
|
|
||||||
|
# 没有变更就不提交也不推送
|
||||||
|
if git diff --cached --quiet; then
|
||||||
|
echo '[deploy] 没有可提交的改动,跳过 commit/push'
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
COMMIT_MSG="chore: deploy blog $(date '+%F %T')"
|
||||||
|
echo "[deploy] 提交改动:${COMMIT_MSG}"
|
||||||
|
git commit -m "$COMMIT_MSG"
|
||||||
|
|
||||||
|
echo "[deploy] 推送到 origin/${BRANCH}"
|
||||||
|
git push origin "$BRANCH"
|
||||||
|
;;
|
||||||
|
help|-h|--help)
|
||||||
|
usage
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "未知命令: $1" >&2
|
||||||
|
usage
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
@@ -0,0 +1,76 @@
|
|||||||
|
// 下载 Markdown 中的掘金外链图片,按文章归类到 source/images/<文章名>/,并替换链接为站内路径
|
||||||
|
const fs = require('fs');
|
||||||
|
const path = require('path');
|
||||||
|
const https = require('https');
|
||||||
|
const http = require('http');
|
||||||
|
|
||||||
|
const ROOT = 'c:/Users/Administrator/Desktop/新建文件夹/blog';
|
||||||
|
const MD = path.join(ROOT, 'source/_posts/Git使用教学.md');
|
||||||
|
// 以文章文件名(去掉扩展名)作为图片子文件夹名,便于按文章管理
|
||||||
|
const POST = path.basename(MD, path.extname(MD));
|
||||||
|
const OUT = path.join(ROOT, 'source/images', POST);
|
||||||
|
|
||||||
|
function download(url) {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
const lib = url.startsWith('https') ? https : http;
|
||||||
|
const req = lib.get(url, { headers: { 'User-Agent': 'Mozilla/5.0' } }, (res) => {
|
||||||
|
// 跟随重定向
|
||||||
|
if (res.statusCode >= 300 && res.statusCode < 400 && res.headers.location) {
|
||||||
|
res.resume();
|
||||||
|
return download(new URL(res.headers.location, url).href).then(resolve, reject);
|
||||||
|
}
|
||||||
|
if (res.statusCode !== 200) {
|
||||||
|
res.resume();
|
||||||
|
return reject(new Error('HTTP ' + res.statusCode));
|
||||||
|
}
|
||||||
|
const chunks = [];
|
||||||
|
res.on('data', (c) => chunks.push(c));
|
||||||
|
res.on('end', () => resolve(Buffer.concat(chunks)));
|
||||||
|
});
|
||||||
|
req.on('error', reject);
|
||||||
|
req.setTimeout(30000, () => req.destroy(new Error('timeout')));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
(async () => {
|
||||||
|
fs.mkdirSync(OUT, { recursive: true });
|
||||||
|
let content = fs.readFileSync(MD, 'utf8');
|
||||||
|
|
||||||
|
const re = /!\[[^\]]*\]\((https:\/\/p3-juejin\.byteimg\.com\/[^)\s]+)\)/g;
|
||||||
|
const map = {}; // url -> /images/<POST>/xxx.webp
|
||||||
|
let m;
|
||||||
|
const tasks = [];
|
||||||
|
|
||||||
|
while ((m = re.exec(content)) !== null) {
|
||||||
|
const url = m[1];
|
||||||
|
if (map[url]) continue;
|
||||||
|
const seg = url.split('/').pop();
|
||||||
|
const hash = seg.split('~')[0];
|
||||||
|
if (!hash) {
|
||||||
|
console.log('跳过(无法解析文件名): ' + url);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
const file = hash + '.webp';
|
||||||
|
map[url] = '/images/' + POST + '/' + file;
|
||||||
|
tasks.push(
|
||||||
|
download(url)
|
||||||
|
.then((buf) => {
|
||||||
|
fs.writeFileSync(path.join(OUT, file), buf);
|
||||||
|
console.log('[OK] ' + file + ' <- ' + url);
|
||||||
|
})
|
||||||
|
.catch((e) => {
|
||||||
|
console.log('[FAIL] ' + url + ' -> ' + e.message);
|
||||||
|
delete map[url];
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
await Promise.all(tasks);
|
||||||
|
|
||||||
|
for (const url in map) {
|
||||||
|
content = content.split(url).join(map[url]);
|
||||||
|
}
|
||||||
|
fs.writeFileSync(MD, content); // UTF-8 无 BOM
|
||||||
|
|
||||||
|
console.log('\n完成:处理 ' + Object.keys(map).length + ' 张图片');
|
||||||
|
})();
|
||||||
@@ -0,0 +1,61 @@
|
|||||||
|
# 下载 Markdown 中的掘金外链图片到 source/images/,并替换链接为站内路径
|
||||||
|
param(
|
||||||
|
[string]$MdPath = "c:/Users/Administrator/Desktop/新建文件夹/blog/source/_posts/Git使用教学.md",
|
||||||
|
[string]$OutDir = "c:/Users/Administrator/Desktop/新建文件夹/blog/source/images"
|
||||||
|
)
|
||||||
|
|
||||||
|
$ErrorActionPreference = "Stop"
|
||||||
|
New-Item -ItemType Directory -Force -Path $OutDir | Out-Null
|
||||||
|
|
||||||
|
$content = Get-Content -Path $MdPath -Raw -Encoding UTF8
|
||||||
|
|
||||||
|
# 匹配  中的掘金图片地址
|
||||||
|
$pattern = '!\[[^\]]*\]\((https://p3-juejin\.byteimg\.com/[^)\s]+)\)'
|
||||||
|
$imgMatches = [regex]::Matches($content, $pattern)
|
||||||
|
|
||||||
|
$map = @{} # url -> /images/xxx.webp
|
||||||
|
$count = 0
|
||||||
|
$failed = @()
|
||||||
|
|
||||||
|
foreach ($m in $imgMatches) {
|
||||||
|
$url = $m.Groups[1].Value
|
||||||
|
if ($map.ContainsKey($url)) { continue }
|
||||||
|
|
||||||
|
# 用 URL 路径最后一段中 "~" 之前的部分作为文件名(即图片 hash)
|
||||||
|
$seg = ($url -split '/')[-1]
|
||||||
|
$hash = ($seg -split '~')[0]
|
||||||
|
if ([string]::IsNullOrEmpty($hash)) {
|
||||||
|
$failed += "无法解析文件名: $url"
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
$file = $hash + '.webp'
|
||||||
|
$dest = Join-Path $OutDir $file
|
||||||
|
|
||||||
|
try {
|
||||||
|
curl.exe -s -L --max-time 30 -o $dest $url
|
||||||
|
if ((Test-Path $dest) -and ((Get-Item $dest).Length -gt 0)) {
|
||||||
|
$map[$url] = '/images/' + $file
|
||||||
|
$count++
|
||||||
|
Write-Host "[OK] $file <- $url"
|
||||||
|
} else {
|
||||||
|
$failed += "下载为空: $url"
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
$failed += "下载异常: $url -> $_"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# 替换 Markdown 中的外链
|
||||||
|
foreach ($kv in $map.GetEnumerator()) {
|
||||||
|
$content = $content.Replace($kv.Key, $kv.Value)
|
||||||
|
}
|
||||||
|
|
||||||
|
# 写回(UTF-8 无 BOM)
|
||||||
|
[System.IO.File]::WriteAllText($MdPath, $content, [System.Text.UTF8Encoding]::new($false))
|
||||||
|
|
||||||
|
Write-Host ""
|
||||||
|
Write-Host "完成:成功下载 $count 张,失败 $($failed.Count) 张"
|
||||||
|
if ($failed.Count -gt 0) {
|
||||||
|
Write-Host "失败列表:"
|
||||||
|
$failed | ForEach-Object { Write-Host " - $_" }
|
||||||
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
// 将文章中的子节标题(X.Y 形式、拣选提交)从 ## 提升为 ###,使目录正确嵌套
|
||||||
|
const fs = require('fs');
|
||||||
|
const p = 'c:/Users/Administrator/Desktop/新建文件夹/blog/source/_posts/Git使用教学.md';
|
||||||
|
let s = fs.readFileSync(p, 'utf8');
|
||||||
|
|
||||||
|
const n1 = (s.match(/^## \d+\.\d+、/gm) || []).length;
|
||||||
|
s = s.replace(/^## (\d+\.\d+、)/gm, '### $1');
|
||||||
|
|
||||||
|
const n2 = (s.match(/^## 拣选提交/gm) || []).length;
|
||||||
|
s = s.replace(/^## (拣选提交)/gm, '### $1');
|
||||||
|
|
||||||
|
fs.writeFileSync(p, s);
|
||||||
|
console.log('提升 X.Y 子节: ' + n1 + ' 处');
|
||||||
|
console.log('提升 拣选提交: ' + n2 + ' 处');
|
||||||