树莓派连接硬件

Speaker

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# play audio
$ sudo apt-get install sox libsox-fmt-all
$ play file-name.mp3

# turn volume
$ amixer set Master 50%
$ amixer set Master 10%+

# slelect speaker
$ alsamixer
## F6 to select device

# set volume over 100%
$ sudo apt install pulseaudio
$ pulseaudio --start -D
$ pulseaudio --check -v # check
$ sudo apt-get install pulseaudio-utils
$ pactl set-sink-volume 0 300%

Camera

Web Stream

1
2
# install
$ sudo apt-get install libjpeg8-dev imagemagick

Reference

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# setup and test
https://www.raspberrypi.org/documentation/configuration/camera.md

# official documents
https://www.raspberrypi.org/documentation/raspbian/applications/camera.md

# web stream
https://blog.miguelgrinberg.com/post/stream-video-from-the-raspberry-pi-camera-to-web-browsers-even-on-ios-and-android
https://blog.miguelgrinberg.com/post/how-to-build-and-run-mjpg-streamer-on-the-raspberry-pi
## 注释 mjpg-streamer/util.c stats.h
# // #include <linux/stat.h>
# // #include <sys/stat.h>

# generate stream
$ raspistill --nopreview -w 640 -h 480 -q 5 -o /home/pi/test.jpg -tl 100 -t 9999999 -th 0:0:0

# serve stream
$ LD_LIBRARY_PATH=/usr/local/lib mjpg_streamer -i "input_file.so -f /home/pi -n test.jpg" -o "output_http.so -w /usr/local/www"

# watch
http://rpi-ip:8080

L298N

参考

Linux之查看设备

CPU

1
$ lscpu

PCI 设备

1
$ lspci

块设备信息

1
2
3
4
5
6
7
$ lsblk

# 查看挂载的节点和对应的分区 UUID
$ ls -lha /dev/disk/by-uuid

# 查看块设备的信息,包含 UUID
$ blkid /dev/sda1

参数

  • -f 显示文件系统信息
  • -a 显示所有设备

硬盘

初始化步骤

  • 创建分区表
  • 创建分区
  • 格式化分区
  • 挂载分区
  • 配置启动时挂载

列出设备及分区信息

1
2
3
$ parted -l
#
$ fdisk -l

初始化设备

格式化

1
$ mkfs [options] [-t type fs-options] device [size]

示例

1
$ sudo mkfs -t ext4 /dev/sda

类型

  • ext4
  • FAT32
  • NTFS

使用中无法格式化

1
2
3
$ dmsetup status
$ dmsetup remove <>
$ dmsetup remove_all # 清楚所有, 谨慎使用, 最好挨个删除

创建主分区

打开存储盘

1
2
3
4
5
6
$ sudo parted -a optimal /dev/sda
GNU Parted 3.1
Using /dev/sda
Welcome to GNU Parted! Type 'help' to view a list of commands.
(parted) select /dev/sdb # 切换至 /dev/sdb
Using /dev/sdb

创建分区表

1
(parted) mklabel [partition_table_type]

分区表类型

  • aix
  • amiga
  • bsd
  • dvh
  • gpt
  • mac
  • ms-dos
  • pc98
  • sun
  • loop

示例

1
(parted) mklabel gpt

检查

1
(parted) print

创建分区

1
2
3
4
5
6
7
# 主分区
(parted) print free
(parted) mkpart primary [start] [end] # 主分区模式

# lvm 分区
(parted) unit s
(parted) mkpart LVM ext4 0% 100%

示例

1
2
(parted) mkpart primary 0.00B 100GB   # 按容量 
(parted) mkpart primary 0 100% # 按比例

格式化分区

1
$ sudo mkfs.ext4 /dev/sda1

自动挂载分区

1
2
$ sudo mkdir data
$ sudo mount -t auto /dev/sda1 /data

示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
$ sudo parted /dev/sda
GNU Parted 3.1
Using /dev/sda
Welcome to GNU Parted! Type 'help' to view a list of commands.
(parted) print
Model: ATA Hitachi HUS72404 (scsi)
Disk /dev/sda: 4001GB
Sector size (logical/physical): 512B/4096B
Partition Table: loop
Disk Flags:

Number Start End Size File system Flags
1 0.00B 4001GB 4001GB ext4

(parted) mklabel gpt
Warning: The existing disk label on /dev/sda will be destroyed and all data on this disk will be lost. Do you want to continue?
Yes/No? yes
(parted) print
Model: ATA Hitachi HUS72404 (scsi)
Disk /dev/sda: 4001GB
Sector size (logical/physical): 512B/4096B
Partition Table: gpt
Disk Flags:

Number Start End Size File system Name Flags
(parted) mkpart primary 4096s 100% # 创建分区表
(parted) print
Model: ATA Hitachi HUS72404 (scsi)
Disk /dev/sda: 4001GB
Sector size (logical/physical): 512B/4096B
Partition Table: gpt
Disk Flags:

Number Start End Size File system Name Flags
1 2097kB 4001GB 4001GB primary
$ sudo mkfs.ext4 /dev/sda1
...
$ sudo mount -t auto /dev/sda1 /data
$ df -h
Filesystem Size Used Avail Use% Mounted on
devtmpfs 32G 0 32G 0% /dev
tmpfs 32G 0 32G 0% /dev/shm
tmpfs 32G 2.0G 30G 7% /run
tmpfs 32G 0 32G 0% /sys/fs/cgroup
/dev/mapper/centos-root 50G 4.2G 46G 9% /
/dev/nvme0n1p2 1014M 233M 782M 23% /boot
/dev/nvme0n1p1 200M 12M 189M 6% /boot/efi
/dev/mapper/centos-home 395G 332M 394G 1% /home
tmpfs 6.3G 12K 6.3G 1% /run/user/42
tmpfs 6.3G 0 6.3G 0% /run/user/1000
/dev/sda1 3.6T 89M 3.4T 1% /data

创建分区表时 4096s 的取值,可以参考 这里这里

脚本创建分区 & 格式化

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 分区
parted --script /dev/vdb \
mklabel gpt \
mkpart primary 4096s 100%

# 格式化
mkfs.ext4 /dev/vdb1

# 挂载
mount -t auto /dev/vdb1 /data

# 写入 /etc/fstab, root 用户运行
echo -e "UUID=$(blkid -o value -s UUID /dev/vdb1)\t/data\text4\tdefaults\t0 0" >> /etc/fstab


echo -e "UUID=$(blkid -o value -s UUID /dev/sdb1)\t/downloads\text4\tdefaults\t0 0" >> /etc/fstab

创建 LVM 分区

概念

  • 物理卷(Physical Volumes)
  • 卷组(Volume Groups)
  • 逻辑卷(Logical Volumes)

查看信息

查看所有 LVM 可以管理的块设备

1
sudo lvmdiskscan

查看物理卷信息

1
2
3
4
5
6
7
8
9
sudo lvmdiskscan -l
#
sudo pvscan

# 如果需要展示更多信息
sudo pvs
#
sudo pvdisplay
sudo pvdisplay -m # 查看映射到每个卷的逻辑扩展名

查看 Volumn Group 的信息

1
sudo vgscan

查看 Logical Volumn 信息

1
2
3
sudo lvscan
#
sudo lvs

创建 LVM 卷

从 Raw Storage Device 创建 Physical Volumes

1
2
# 列出所有可用的设备
sudo lvmdiskscan

如果没有列出目标设备,可能是设备使用了不支持的分区表。重新设置设备的分区表为兼容的 BIOS 表。

1
2
3
sudo parted /dev/sda
(parted) mktable msdos
(parted) quit

标记存储设备为 LVM 物理卷。

1
2
3
sudo pvcreate /dev/sda
# 多个设备
sudo pvcreate /dev/sda /dev/sdb

从 Physical Volumes 创建 Volume Group

1
2
3
sudo vgcreate lvm-storage /dev/sda
# 多个设备
sudo vgcreate lvm-storage /dev/sda /dev/sdb

从 Volume Group 创建 Logical Volume

1
2
3
4
5
# 创建指定 size
sudo lvcreate -L 500G -n lvm-storage-hadoop lvm-storage

# 使用所有剩余空间
sudo lvcreate -l 100%FREE -n lvm-storage-hadoop lvm-storage

格式化分区

1
sudo mkfs.ext4 /dev/<lvm-vg-name>/<lvm-lv-name> 

挂载 LV

1
sudo mount /dev/<lvm-vg-name>/<lvm-lv-name> /path/to/destination

自动挂载

1
2
3
4
5
6
7
# 查看 logical volume 的 uuid
sudo blkid
/dev/mapper/<lvm-lv-name>: UUID="0192e4be-db57-4dc9-9f07-cb7bd673811b" BLOCK_SIZE="4096" TYPE="ext4"
# 添加自动挂载
sudo vim /etc/fstab
# 新增如下内容
UUID=0192e4be-db57-4dc9-9f07-cb7bd673811b /storage/hadoop ext4 defaults 0 2

更多操作

向 Volume Group 添加 Physical Volume

1
sudo vgextend <volume-group-name> /dev/sdb

增加 Logical Volume 的空间

Solution 1

1
2
3
4
sudo lvresize -L +5G --resizefs <lvm-vg-name>/<lvm-lv-name>  # 调整 lvm size
sudo lvresize -l +100%FREE /dev/<lvm-vg-name>/<lvm-lv-name> # 使用所有剩余空间
# sudo lvdisplay; 找到 Logical Volume 的 LV Path
sudo resize2fs <lv-path> # 生效

注意: lvresize 之后通过 df -h 查看空间,并不会生效,需要再运行 resize2fs

Solution 2

为 Ubuntu 的 lv 分区扩容

1
2
3
$ sudo vgdisplay  # 查看 vg 信息
$ sudo lvdisplay # 查看 lv 信息
$ sudo lvextend -l +100%FREE -r /dev/ubuntu-vg/ubuntu-lv

删除 Logical Volume

1
2
sudo umount /dev/<lvm-vg-name>/<lvm-lv-name>
sudo lvremove <lvm-vg-name>/<lvm-lv-name>

删除 Volume Group

1
2
sudo umount /dev/<lvm-vg-name>/* # unmount vg 下所有 lv
sudo vgremove <lvm-vg-name>

删除 Physical Volume

1
sudo pvremove /dev/sda

查看接口

1
2
sudo dmidecode --type connector
# 可以查看 USB、SATA、M.2 接口

参考

Linux之网络配置

DNS

Debian+

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# interfaces; configured by dns-nameserver
$ cat /etc/network/interfaces
...
auto wlan0
allow-hotplug wlan0
iface wlan0 inet static
address 192.168.8.160
netmask 255.255.255.0
network 192.168.8.1
gateway 192.168.8.1
broadcast 192.168.8.255
wpa-essid "<wifi-id>"
wpa-psk "<wifi-password>"
dns-nameserver 8.8.8.8
dns-nameserver 8.8.4.4
dns-nameserver 192.168.8.1

Proxy

全局代理

1
2
export http_proxy=socks5://<host>:<port>
export https_proxy=socks5://<host>:<port>

适用

  • cURL

Git 代理

1
2
3
4
5
6
7
# 设置代理
git config --global https.proxy socks5://<host>:<port>
git config --global https.proxy socks5://<host>:<port>

# 取消
git config --global --unset http.proxy
git config --global --unset https.proxy

CMD ip

1
2
via : [FAMILY] ADDRESS, 指定下一跳地址
src : ADDRESS, 发送至目的地时优先使用的源地址

table

1
2
3
4
5
6
7
8
9
10
# show table
ip route show table all
ip route show table 10

# add table
ip route add 192.168.6.0/24 dev br0 table 10
ip route add default via 192.168.6.1 table 10

# 删除 table
ip route delete table 12 192.168.9.0/24

rule

1
2
3
4
5
# show rule
ip rule show

# 添加
ip rule add from 192.168.6.0/24 table 10 priority 1

gateway

1
2
3
4
5
# 添加
ip route add default via 192.168.1.1 dev eth0

# 更新 (所有配置都要添加vc)
ip route replace default via 192.168.1.1 dev eth0

静态路由

1
2
# github ip 走网关 192.168.6.68 
sudo ip route add 20.205.243.166 via 192.168.6.68

CMD route

1
2
# 添加路由
route -q -n add -inet 192.168.6.0/24 -interface utun3

Route Trace

1
2
3
$ traceroute -4 baidu.com
$ traceroute -6 baidu.com # ipv6
$ traceroute -g 192.168.6.1 # 指定 gateway

tcpdump

1
2
# 客户端抓取向服务端发送的数据
$ tcpdump dst host {dst-host} and dst port {dst-port} -w out.pacp

树莓派 - PWM 调速马达

L298N

L298N motor controller board

接口

  • OUT A,接马达 A
  • OUT B ,接马达 B
  • POWER,+5V、GND、+12V
    • 5V 电源,接 +5V + GND
    • 12V 电源,接 +12V + GND
  • 控制端口,ENA、INA1、INA2、INB1、INB2、ENB
    • 接 GPIO
    • ENA、INA1、INA2 控制马达 A
    • ENB、INB1、INB2 控制马达 B

JVM 参数

参数

参数 默认值 说明
-XX:MaxDirectMemorySize 64M 非堆内存大小

GC

G1GC

G1GC是区域化、分代式垃圾回收器。堆内存被划分为大小相同的若干区域(Region),区域大小取值为[1,32]之间2的幂,若不配置Region大小,JVM以数量不超过2048个区域为目标,确定Region大小。这些Region逻辑上组合成传统的Eden、Survivor、Tenured。

概念

  • Region:对内存块,逻辑组合为传统的年轻代、老年代
  • CSet:回收集
  • RSet:记忆集
  • SATB: Snapshot-At-The-Beginning,初始快照
  • IHOP:Initiating Heap Occupancy Percent

分区

阶段

G1GC在两个阶段之间交替,young-only和space-reclamation。young-only 阶段包括垃圾回收,其逐渐将

Young-only 阶段

该阶段开始是一些普通年轻代回收(Normal yount collection),其将对象晋升至老年代。Young-only向Space-reclamatioin阶段过渡始自老年代使用率达到设定阈值。此时,G1执行**并行开始年轻代回收(Concurrent Start young collection)**替代普通年轻代回收。过渡周期包含以下阶段。

  • Concurrent Start:除了执行普通年轻代回收,同时开始标记过程(marking process)。并行标记决定老年代区域中(old generation regions)所有当前可达对象,在接下来的space-reclamation阶段被保留。当回收标记还未完成时,可能会进行普通年轻代回收。标记完成伴随两个STW阶段:Remark和Cleanup。
  • Remark:完成标记本身、执行全局引用处理、类卸载、回收空区域、清理内部数据结构。在Remark和Cleanup之间,G1会计算信息,以便后面能够在选中的老年代区域中并发回收可用空间,该过程在Cleanup阶段完成。
  • Cleanup:决定是否将实际执行space-reclamation阶段。如果随后进行space-reclamation阶段,young-only阶段以单个就绪混合年轻代回收(Prepare Mixed young collection)结束。

Space-reclamation 阶段

该阶段包含多个混合回收,除了年轻代区域外,还会压缩(evacuate)老年代区域集合中的存活对象。当G1确定压缩更多老年代区域不会产生足够值得努力的空间时,space-reclamation阶段结束。

细节

确定初始堆占用率

初始堆占用率(Initiating Heap Occupancy Percent,IHOP)是触发初始标记回收的阈值,定义为老年代大小的百分比。

默认情况下,G1通过观察标记耗时及标记周期内老年代分配内存,自动决定最佳的IHOP。该特性称为Adaptive IHOP,当该特性激活时,参数-XX:InitiatingHeapOccupancyPercent指定的值作为,G1在还没有足够观察值确定该值时的初始值。通过参数-XX:-G1UseAdaptiveIHOP可关闭该特性,此时 -XX:InitiatingHeapOccupancyPercent 参数指定的值总是决定该阈值。

标记

G1标记使用初始快照算法(Snapshot-At-The-Beginning,SATB)。在初始标记暂停时(Initial Mark pause),为堆创建虚拟快照,

参数

参数 默认值 说明
-XX:+UseG1GC - 使用G1回收器
-XX:MaxGCPauseMillis 200 最大GC停顿时间,单位毫秒
-XX:InitiatingHeapOccupancyPercent 45 触发标记周期的堆占用率阈值
-XX:NewRatio 2 新生代与老年代大小比例
-XX:SurvivorRatio 8 eden与suvivor区大小比例
-XX:MaxTenuringThreshold 15 提升年老代的最大临界值
-XX:ParallelGCThreads - STW工作线程数
-XX:ConcGCThreads - 并行标记线程数
-XX:G1ReservePercent 10 空闲空间的预留内存百分比
-XX:G1HeapWastePercent 10 触发混合垃圾回收的可回收堆内存阈值
-XX:G1HeapRegionSize - region分片size,1M~32M,2的幂
-XX:G1MixedGCCountTarget 8
-XX:G1OldCSetRegionThresholdPercent 10
-XX:-G1UseAdaptiveIHOP - 关闭自动设置IHOP特性

实验参数

使用实验参数,需要添加解锁实验参数标记。

参数 默认值 说明
-XX:+UnlockExperimentalVMOptions - 解锁实验参数
-XX:G1NewSizePercent 5 年轻代最小百分比
-XX:G1MaxNewSizePercent=60 60 年轻代最大百分比
-XX:G1MixedGCLiveThresholdPercent 65 混合垃圾回收周期中要包括的老年代region使用率阈值

日志

参数 说明
-verbose:gc -
-XX:+PrintGCDetails -
-XX:+PrintGCDateStamps -
-XX:+PrintGCApplicationStoppedTime 打印应用停留时间
-XX:+PrintTenuringDistribution 老年代分布
-Xloggc:/path/to/gc.log -
-XX:+UseGCLogFileRotation -
-XX:NumberOfGCLogFiles=10 -
-XX:GCLogFileSize=128M -

注意

  • G1触发Full GC,退化使用Serial收集完成垃圾回收,仅适用单线程
  • 避免使用 -Xmn或 -XX:NewRatio 显示设置年轻代大小,会覆盖期望STW时间设置
  • 优先调优项
    • -XX:InitiatingHeapOccupancyPercent
    • -XX:G1MixedGCLiveThresholdPercent
    • -XX:G1HeapWastePercent
    • -XX:G1MixedGCCountTarget
    • -XX:G1OldCSetRegionThresholdPercent

参考

memset & fill

memset

头文件

1
2
3
4
// c
#include <string.h>
// c++
#include <cstring>

使用

1
2
3
4
5
6
void *memset( void *dest, int ch, size_t count );
dest : 需要填充内存指针
ch : 填充内容,被强转成unsigned char使用
count: 需要填充数量

dest指针开始前count个字节的每个字节赋值为ch

示例

1
2
3
4
5
6
char str[] = "hello world";
memset (str, '-', 5);
puts(str);

// output
"----- world"

fill

头文件

1
#include <algorithm>

使用

1
2
3
4
5
template< class ForwardIt, class T >
constexpr void fill( ForwardIt first, ForwardIt last, const T& value );
first : 开始迭代器
last : 中止迭代器
value : 需要填充的值

c++ sizeof

使用

1
2
3
sizeof(type/object)

查询对象/类型实际大小

示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// 定义结构
struct Empty {};
struct Base { int a; };
struct Derived : Base { int b; };
struct Bit { unsigned bit: 1; };

// 实例化
Empty e;
Derived d;
Base& b = d;
[[maybe_unused]] Bit bit;
int a[10];

// 查询大小
sizeof e // 1 Empty类大小
sizeof &e // 8 类指针大小
sizeof(Bit) // 4 Bit类大小
sizeof(int[10]) // 40
sizeof(a) // 40
((sizeof a) / (sizeof *a)) // 计算数组a的长度
((sizeof a) / (sizeof a[0])) // 计算数组a的长度
sizeof d // Derived对象大小
sizeof b // Base对象大小

gitignore

Common

1
.idea/

Python

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class

# C extensions
*.so

# Distribution / packaging
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST

# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec

# Installer logs
pip-log.txt
pip-delete-this-directory.txt

# Unit test / coverage reports
htmlcov/
.tox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
.hypothesis/

# Translations
*.mo
*.pot

# Django stuff:
*.log
.static_storage/
.media/
local_settings.py

# Flask stuff:
instance/
.webassets-cache

# Scrapy stuff:
.scrapy

# Sphinx documentation
docs/_build/

# PyBuilder
target/

# Jupyter Notebook
.ipynb_checkpoints

# pyenv
.python-version

# celery beat schedule file
celerybeat-schedule

# SageMath parsed files
*.sage.py

# Environments
.env
.venv
env/
venv/
ENV/
env.bak/
venv.bak/

# Spyder project settings
.spyderproject
.spyproject

# Rope project settings
.ropeproject

# mkdocs documentation
/site

# mypy
.mypy_cache/

git 使用

basic

生成公钥

1
2
3
4
5
$ ssh-keygen -t ed25519 -C "<your email>"

# 不推荐
$ ssh-keygen -t rsa -C "<your email>" # id_rsa
$ ssh-keygen -t rsa -C "<your another email>" # id_rsa_work

配置全局信息

1
2
$ git config --global user.name "sunzhenkai"
$ git config --global user.email "zhenkai.sun@qq.com"

多公钥

适用

  • 一台机器,同一Git仓库,多账号
  • 一台机器,多Git仓库,多账号
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# 生成公钥
$ ssh-keygen -t rsa -C "<your email>" # id_rsa
$ ssh-keygen -t rsa -C "<your another email>" # id_rsa_work

# 配置 config
$ vim ~/.ssh/config
Host github.com
HostName github.com
User git
IdentityFile ~/.ssh/id_rsa

Host github.com-work
HostName github.com
User git
IdentityFile ~/.ssh/id_rsa_work

# 指定账号添加对应公钥

# 使用, 克隆或添加remote时使用config定义的Host别名(github.com / github.com-work / 其他)
$ git clone git@github.com:<user-name>/<repo-name>.git
$ git remote add origin git@github.com:<user-name>/<repo-name>.git

stash

用于暂存代码。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 暂存
$ git stash save 'message'

# 查看暂存
$ git stash list

# 恢复并删除暂存
$ git stash pop stash@{?}

# 只恢复,不删除暂存
$ git stash apply stash@{?}

# 删除暂存
$ git stash drop stash@{?}

# 删除所有暂存
$ git stash clear

submodule

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 添加子模块
$ git submodule add <git-address> <localpath>

# 初始化/下载子模块代码
git submodule update --init --recursive

# 递归clone
$ git clone ... --recursive
$ git clone --recurse-submodules ...

# pull with submodules
$ git pull --recurse-submodules

# 更新子模块至最新提交
$ git submodule update --remote --merge

# 重置 submodule commit id
git submodule update --init

清理

1
2
3
4
$ rm -rf path/to/submodule
$ rm -rf .git/modules/{module}
$ vim .gitmodules # 移除对应 module
$ vim .git/config # 移除对应 module

tags

1
2
3
4
5
$ git tag -s "tag_name" -m "comments"
# push 到远端
$ git push origin <tag-name> # one
$ git push --tags # all
$ git push origin --tags # all

删除大文件

1
git filter-branch -f --prune-empty --index-filter "git rm -rf --cached --ignore-unmatch recommend/keywords.txt" --tag-name-filter cat -- --all

修改 commit 用户名

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 设置用户名、邮箱
git config user.name "New User"
git config user.email "newuser@gmail.com"

git log
git rebase -i <commit-id> # 这个 commit-id 需要修改的前一个
# 把需要修改的 commit 前的 'pick' 改为 'edit', 保存并退出

# 重复下面两步
git commit --amend --reset-author --no-edit
git rebase --continue

# 强制提交
git push --force-with-lease

参考这里

查看某一行修改人

1
git blame <file> -L <start-line>,<end-line>

branch

1
2
# 删除分支
git push origin --delete <branch>

Git Tree

1
2
# 检出 /path/pattern 下文件在 tree-ish 下的状态
git checkout {tree-ish} /path/pattern # 主要后面的 path, 存放 checkout 出来的文件

检出并保存在其他路径

1
git archive f9ee8bb31f04f4e6a8c0d3e96fbb98deeb448d45 | tar -x -C /tmp/f9ee8bb31f04f4e6a8c0d3e96fbb98deeb448d45

从 remote 检出

1
git archive --remote=https://github.com/user/repo.git <tree-ish> | tar -x -C /path/to/target-dir

配置

1
2
3
4
5
# 打印配置
git config -l
# 打印全局配置
git config --global -l # 当前用户的配置
git config --sysmte -l # 系统配置

作用域

1
2
3
          默认仓库级别
--system 系统
--global 用户目录

配置项

1
2
git config user.name '...'
git config user.email '...'

代理

1
2
3
4
5
6
7
# 设置
git config --global http.proxy http://user:password@domain:port
git config --global https.proxy http://user:password@domain:port

# 取消设置
git config --global --unset http.proxy
git config --global --unset https.proxy

最佳实践

分支名称

分支分类

  • 主分支,main / master
  • 开发分支,dev
  • 功能分支,feature / feat
  • 修复分支,bugfix / fix
  • 发布分支,release
  • 紧急修复分支,hotfix
  • 测试分支,test
  • 文档分支,doc

命名示例

1
feature/JIRA-1929-support-oneid

问题排查

中文乱码

参考

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
git config --global core.quotepath false  		# 显示 status 编码
git config --global gui.encoding utf-8 # 图形界面编码
git config --global i18n.commit.encoding utf-8 # 提交信息编码
git config --global i18n.logoutputencoding utf-8 # 输出 log 编码
export LESSCHARSET=utf-8
# 最后一条命令是因为 git log 默认使用 less 分页,所以需要 bash 对 less 命令进行 utf-8 编码
# 命令

```shell
# init
git init

# add, 添加改动
git add file

# commit
git commit -m 'comment' --author='sample@x.com'
## 修改刚刚 commit 的内容
git commit --amend -m 'comment' ...

git-remote-http libcurl-httpd24.so.4 不存在

错误信息

1
/opt/rh/rh-git218/root/usr/libexec/git-core/git-remote-http: error while loading shared libraries: libcurl-httpd24.so.4: cannot open shared object file: No such file or directory

解决

1
2
3
4
5
6
7
8
find / -name 'libcurl-httpd24.so.4'
/opt/rh/httpd24/root/usr/lib64/libcurl-httpd24.so.4

# 修改 LD_LIBRARY_PATH 环境变量
# vim ~/.bashrc
export LD_LIBRARY_PATH=/opt/rh/httpd24/root/usr/lib64:$LD_LIBRARY_PATH

source ~/.bashrc