新增文档
This commit is contained in:
128
docs/学习笔记/gerrit分支规范.md
Normal file
128
docs/学习笔记/gerrit分支规范.md
Normal file
@@ -0,0 +1,128 @@
|
||||
推荐标准分支模型: master/main主干分支 永远保持可编译、可运行 release-* 发布分支 只合并经过验证的Change hotfix-* 紧急修复
|
||||
|
||||
|
||||
您总结的Gerrit分支创建流程非常准确和实用!以下是对您提供内容的梳理和补充,使其更加清晰系统化。
|
||||
|
||||
## Gerrit 分支管理全流程
|
||||
|
||||
### 一、权限说明(重要前提)
|
||||
- **Owner/Maintainer**:有权限创建新分支
|
||||
- **Developer**:默认只能推送提交到现有分支,不能创建新分支
|
||||
- **权限配置路径**:Project → Access → Reference: refs/heads/*
|
||||
|
||||
### 二、分支创建详细步骤
|
||||
|
||||
#### 1. master/main分支(主干分支)
|
||||
```bash
|
||||
# 如果仓库为空,需要初始化master分支
|
||||
git clone ssh://user@gerrit-ip:29418/project-name
|
||||
cd project-name
|
||||
git checkout -b master
|
||||
# 首次推送master分支(不走Review流程)
|
||||
git push origin master
|
||||
```
|
||||
|
||||
#### 2. release-*分支(发布分支)
|
||||
```bash
|
||||
# 1. 更新master分支
|
||||
git checkout master
|
||||
git pull
|
||||
|
||||
# 2. 创建本地release分支
|
||||
git checkout -b release-1.0
|
||||
|
||||
# 3. 推送到Gerrit创建远程分支
|
||||
git push origin release-1.0
|
||||
# 注意:这里直接push,不是refs/for/
|
||||
```
|
||||
|
||||
#### 3. hotfix-*分支(紧急修复分支)
|
||||
```bash
|
||||
# 从release分支创建
|
||||
git checkout release-1.0
|
||||
git pull
|
||||
git checkout -b hotfix-crash-123
|
||||
git push origin hotfix-crash-123
|
||||
|
||||
# 从master分支创建(如果未建立release分支)
|
||||
git checkout master
|
||||
git pull
|
||||
git checkout -b hotfix-issue-456
|
||||
git push origin hotfix-issue-456
|
||||
```
|
||||
|
||||
### 三、不同分支的提交方式差异
|
||||
|
||||
| 分支类型 | 推送命令 | 是否走Review | 说明 |
|
||||
|---------|---------|-------------|------|
|
||||
| 创建新分支 | `git push origin 分支名` | ❌ 否 | 直接创建分支 |
|
||||
| master分支提交 | `git push origin HEAD:refs/for/master` | ✅ 是 | 常规开发流程 |
|
||||
| release分支提交 | `git push origin HEAD:refs/for/release-1.0` | ✅ 是 | 修复bug流程 |
|
||||
| hotfix分支提交 | `git push origin HEAD:refs/for/hotfix-*` | ✅ 是 | 紧急修复流程 |
|
||||
|
||||
### 四、分支合并策略
|
||||
|
||||
#### hotfix修复后的合并流程:
|
||||
```bash
|
||||
# 1. 修复完成后,合并到release分支
|
||||
git checkout release-1.0
|
||||
git merge --no-ff hotfix-crash-123
|
||||
git push origin HEAD:refs/for/release-1.0
|
||||
|
||||
# 2. cherry-pick到master
|
||||
git checkout master
|
||||
git cherry-pick <hotfix-commit-id>
|
||||
git push origin HEAD:refs/for/master
|
||||
```
|
||||
|
||||
### 五、最佳实践建议
|
||||
|
||||
1. **分支命名规范**:
|
||||
- feature/xxx(功能分支,从master创建)
|
||||
- release/x.y.z(发布分支)
|
||||
- hotfix/xxx(紧急修复)
|
||||
- bugfix/xxx(普通bug修复)
|
||||
|
||||
2. **权限管理**:
|
||||
```bash
|
||||
# 为开发者授予特定分支创建权限(Gerrit Web界面)
|
||||
# Access → Reference: refs/heads/feature/*
|
||||
# 添加 Push + Create Reference 权限给特定用户组
|
||||
```
|
||||
|
||||
3. **CI/CD集成**:
|
||||
- release-* 分支:触发正式环境构建
|
||||
- hotfix-* 分支:紧急修复通道,快速验证
|
||||
- master分支:每日/持续集成
|
||||
|
||||
4. **分支保护**:
|
||||
- 保护master分支:必须通过Code Review
|
||||
- 保护release分支:限制直接push,需通过Review
|
||||
- 定期清理过期分支
|
||||
|
||||
### 六、常见问题排查
|
||||
|
||||
1. **权限拒绝错误**:
|
||||
```
|
||||
! [remote rejected] release-1.0 -> release-1.0 (prohibited by Gerrit)
|
||||
```
|
||||
解决方法:联系Owner/Maintainer授予分支创建权限
|
||||
|
||||
2. **分支已存在错误**:
|
||||
```bash
|
||||
# 先拉取远程分支列表
|
||||
git fetch origin
|
||||
git branch -r # 查看远程分支
|
||||
```
|
||||
|
||||
3. **使用Gerrit插件创建分支**(可选):
|
||||
```bash
|
||||
# 安装git-review插件
|
||||
pip install git-review
|
||||
|
||||
# 创建分支并推送到Gerrit
|
||||
git review -c -b release-1.0
|
||||
```
|
||||
|
||||
您的总结已经非常全面,这些补充主要是为了让操作流程更加清晰,便于团队协作和标准化操作。
|
||||
|
||||
276
docs/学习笔记/git同步远程分支总结.md
Normal file
276
docs/学习笔记/git同步远程分支总结.md
Normal file
@@ -0,0 +1,276 @@
|
||||
非常全面的同步远程分支指南!我来帮你整理几个最实用的方案,并提供更清晰的分类:
|
||||
|
||||
## 📋 **最常用的分支同步方案**
|
||||
|
||||
### **方案一:基础同步(最常用)**
|
||||
```bash
|
||||
# 1. 获取所有远程更新并清理已删除分支
|
||||
git fetch --all --prune
|
||||
|
||||
# 2. 查看所有分支
|
||||
git branch -a
|
||||
|
||||
# 3. 切换到特定分支并同步
|
||||
git checkout 分支名
|
||||
git pull origin 分支名
|
||||
```
|
||||
|
||||
### **方案二:一键同步所有分支到本地**
|
||||
```bash
|
||||
# 推荐的安全版本
|
||||
git fetch --all --prune
|
||||
for branch in $(git branch -r | grep -v '\->' | grep -v 'HEAD'); do
|
||||
local_branch=${branch#origin/}
|
||||
if ! git show-ref --quiet refs/heads/"$local_branch"; then
|
||||
echo "📦 创建分支: $local_branch"
|
||||
git branch --track "$local_branch" "$branch"
|
||||
fi
|
||||
done
|
||||
```
|
||||
|
||||
## 🔧 **实用脚本整理**
|
||||
|
||||
### **脚本1:智能同步脚本 (sync-branches.sh)**
|
||||
```bash
|
||||
#!/bin/bash
|
||||
# 智能同步所有远程分支
|
||||
|
||||
echo "🔄 开始同步分支..."
|
||||
|
||||
# 1. 获取所有远程更新
|
||||
git fetch --all --prune
|
||||
|
||||
# 2. 同步主要分支
|
||||
main_branch=""
|
||||
if git show-ref --verify --quiet refs/remotes/origin/main; then
|
||||
main_branch="main"
|
||||
elif git show-ref --verify --quiet refs/remotes/origin/master; then
|
||||
main_branch="master"
|
||||
fi
|
||||
|
||||
if [ -n "$main_branch" ]; then
|
||||
echo "📌 更新主分支: $main_branch"
|
||||
git checkout $main_branch 2>/dev/null || git checkout -b $main_branch origin/$main_branch
|
||||
git pull origin $main_branch
|
||||
fi
|
||||
|
||||
# 3. 创建本地不存在的远程分支
|
||||
echo "📦 同步其他分支..."
|
||||
git branch -r | grep -v '\->' | grep -v 'HEAD' | while read remote; do
|
||||
local_branch=${remote#origin/}
|
||||
|
||||
# 跳过已经存在的分支
|
||||
if git show-ref --verify --quiet refs/heads/"$local_branch"; then
|
||||
echo " ✓ 已存在: $local_branch"
|
||||
continue
|
||||
fi
|
||||
|
||||
# 创建跟踪分支
|
||||
echo " ➕ 创建: $local_branch"
|
||||
git branch --track "$local_branch" "$remote" 2>/dev/null
|
||||
done
|
||||
|
||||
# 4. 检查是否需要更新现有分支
|
||||
echo "🔄 检查本地分支更新..."
|
||||
current_branch=$(git branch --show-current)
|
||||
git branch --format='%(refname:short)' | while read branch; do
|
||||
if [ "$branch" != "$current_branch" ]; then
|
||||
git checkout "$branch" >/dev/null 2>&1
|
||||
if [ $? -eq 0 ]; then
|
||||
git pull origin "$branch" --ff-only >/dev/null 2>&1
|
||||
echo " ⬆️ 已更新: $branch"
|
||||
fi
|
||||
fi
|
||||
done
|
||||
|
||||
# 5. 返回原分支
|
||||
git checkout "$current_branch" >/dev/null 2>&1
|
||||
|
||||
echo "✅ 同步完成!"
|
||||
echo "📊 分支统计:"
|
||||
git branch -a | grep -c "remotes/origin" | xargs echo "远程分支数: "
|
||||
git branch | wc -l | xargs echo "本地分支数: "
|
||||
```
|
||||
|
||||
### **脚本2:快速切换和同步 (git-sync)**
|
||||
```bash
|
||||
#!/bin/bash
|
||||
# 快速切换到指定分支并同步
|
||||
if [ $# -eq 0 ]; then
|
||||
echo "用法: git-sync 分支名"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
BRANCH=$1
|
||||
|
||||
echo "🔄 切换到分支: $BRANCH"
|
||||
|
||||
# 检查分支是否存在
|
||||
if git show-ref --verify --quiet refs/heads/"$BRANCH"; then
|
||||
# 本地分支存在
|
||||
git checkout "$BRANCH"
|
||||
git pull origin "$BRANCH"
|
||||
elif git show-ref --verify --quiet refs/remotes/origin/"$BRANCH"; then
|
||||
# 远程分支存在,创建本地跟踪分支
|
||||
git checkout -b "$BRANCH" origin/"$BRANCH"
|
||||
else
|
||||
echo "❌ 错误: 分支 $BRANCH 不存在"
|
||||
echo "可用的远程分支:"
|
||||
git branch -r | grep -v '\->' | sed 's/origin\///' | sort | uniq
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "✅ 完成!当前分支: $(git branch --show-current)"
|
||||
```
|
||||
|
||||
## ⚙️ **Git 配置别名(推荐)**
|
||||
|
||||
添加到 `~/.gitconfig` 的 `[alias]` 部分:
|
||||
|
||||
```ini
|
||||
[alias]
|
||||
# 同步所有分支
|
||||
sync-all = "!f() { \
|
||||
echo '🔄 获取远程更新...'; \
|
||||
git fetch --all --prune; \
|
||||
echo '📦 创建本地分支...'; \
|
||||
git branch -r | grep -v '\\->' | grep -v 'HEAD' | while read remote; do \
|
||||
local=${remote#origin/}; \
|
||||
if ! git show-ref --quiet refs/heads/\"$local\"; then \
|
||||
echo \" ➕ $local\"; \
|
||||
git branch --track \"$local\" \"$remote\" 2>/dev/null; \
|
||||
fi; \
|
||||
done; \
|
||||
echo '✅ 同步完成!'; \
|
||||
}; f"
|
||||
|
||||
# 更新当前仓库所有分支
|
||||
update-all = "!f() { \
|
||||
current=$(git branch --show-current); \
|
||||
for branch in $(git branch --format='%(refname:short)'); do \
|
||||
if [ \"$branch\" != \"$current\" ]; then \
|
||||
git checkout \"$branch\" 2>/dev/null && git pull origin \"$branch\" 2>/dev/null; \
|
||||
fi; \
|
||||
done; \
|
||||
git checkout \"$current\"; \
|
||||
echo '✅ 所有分支已更新!'; \
|
||||
}; f"
|
||||
|
||||
# 查看分支树状图
|
||||
tree = log --graph --abbrev-commit --decorate --format=format:'%C(bold blue)%h%C(reset) - %C(bold green)(%ar)%C(reset) %C(white)%s%C(reset) %C(dim white)- %an%C(reset)%C(bold yellow)%d%C(reset)' --all
|
||||
|
||||
# 清理已合并的分支
|
||||
clean-branches = "!f() { \
|
||||
git fetch --all --prune; \
|
||||
git branch --merged main | grep -v '^\\* main$' | xargs -n 1 git branch -d; \
|
||||
echo '🧹 已清理合并到main的分支'; \
|
||||
}; f"
|
||||
```
|
||||
|
||||
使用别名:
|
||||
```bash
|
||||
git sync-all # 同步所有远程分支到本地
|
||||
git update-all # 更新所有本地分支
|
||||
git tree # 查看分支树状图
|
||||
git clean-branches # 清理已合并的分支
|
||||
```
|
||||
|
||||
## 🎯 **针对不同场景的推荐方案**
|
||||
|
||||
### **场景1:新电脑初次同步**
|
||||
```bash
|
||||
# 1. 克隆仓库
|
||||
git clone ssh://renjianbo@101.43.95.130:29418/zhini_im
|
||||
|
||||
# 2. 进入目录并同步所有分支
|
||||
cd zhini_im
|
||||
git sync-all # 使用上面配置的别名
|
||||
```
|
||||
|
||||
### **场景2:日常更新**
|
||||
```bash
|
||||
# 推荐的工作流程
|
||||
git status # 1. 查看状态
|
||||
git stash # 2. 暂存未提交的修改(可选)
|
||||
git fetch --all --prune # 3. 获取最新状态
|
||||
git checkout main # 4. 切换到主分支
|
||||
git pull --rebase origin main # 5. 更新主分支
|
||||
git checkout 你的分支 # 6. 切回你的分支
|
||||
git rebase main # 7. 基于最新main重定基
|
||||
git stash pop # 8. 恢复暂存的修改
|
||||
```
|
||||
|
||||
### **场景3:清理分支**
|
||||
```bash
|
||||
# 查看哪些分支已经合并到main
|
||||
git branch --merged main
|
||||
|
||||
# 删除已合并的分支(除了当前分支和main)
|
||||
git branch --merged main | grep -v "main" | xargs git branch -d
|
||||
|
||||
# 强制删除未合并的分支
|
||||
git branch -D 分支名
|
||||
|
||||
# 删除远程分支(谨慎操作)
|
||||
git push origin --delete 分支名
|
||||
```
|
||||
|
||||
## 📊 **分支管理最佳实践**
|
||||
|
||||
### **分支命名规范**
|
||||
```
|
||||
feature/ # 新功能
|
||||
bugfix/ # 修复bug
|
||||
hotfix/ # 紧急修复
|
||||
release/ # 发布分支
|
||||
```
|
||||
|
||||
### **常用命令速查**
|
||||
```bash
|
||||
# 查看分支关系
|
||||
git log --graph --oneline --all
|
||||
|
||||
# 查看远程分支的最后提交
|
||||
git for-each-ref --sort=-committerdate refs/remotes/origin/ --format='%(refname:short) - %(committerdate:short)'
|
||||
|
||||
# 查看分支差异
|
||||
git diff main..你的分支 # 比较差异
|
||||
git log main..你的分支 # 查看提交记录差异
|
||||
|
||||
# 重命名分支
|
||||
git branch -m 旧名字 新名字 # 本地重命名
|
||||
git push origin :旧名字 # 删除远程旧分支
|
||||
git push origin 新名字 # 推送新分支
|
||||
git push origin -u 新名字 # 设置上游分支
|
||||
```
|
||||
|
||||
## 🚨 **注意事项**
|
||||
|
||||
1. **备份重要修改**:同步前先提交或暂存工作
|
||||
2. **小心 force push**:避免使用 `--force`,用 `--force-with-lease` 更安全
|
||||
3. **定期清理**:删除已合并的本地分支,保持仓库整洁
|
||||
4. **沟通协调**:多人协作时,删除远程分支前要确认
|
||||
|
||||
## 🎪 **一个命令完成所有同步**
|
||||
|
||||
终极简化版:
|
||||
```bash
|
||||
# 创建 ~/bin/git-full-sync 文件
|
||||
#!/bin/bash
|
||||
cd /path/to/your/project
|
||||
git stash
|
||||
git fetch --all --prune
|
||||
git checkout main && git pull origin main
|
||||
git sync-all # 使用别名
|
||||
git stash pop
|
||||
echo "✅ 全量同步完成!"
|
||||
|
||||
# 添加执行权限
|
||||
chmod +x ~/bin/git-full-sync
|
||||
|
||||
# 使用
|
||||
cd 你的项目
|
||||
git-full-sync
|
||||
```
|
||||
|
||||
这些方案覆盖了大部分使用场景,根据你的具体需求选择合适的方法即可。最常用的是方案一的基础同步,配合别名可以极大提高效率。
|
||||
14
docs/学习笔记/git设置用户名和邮箱.md
Normal file
14
docs/学习笔记/git设置用户名和邮箱.md
Normal file
@@ -0,0 +1,14 @@
|
||||
配置用户名和邮箱(如果还没配置)
|
||||
git config --global user.name "Your Name" git config --global user.email "your.email@example.com"
|
||||
|
||||
查看用户名
|
||||
git config user.name
|
||||
|
||||
查看邮箱
|
||||
git config user.email
|
||||
|
||||
查看远程仓库地址
|
||||
git config remote.origin.url
|
||||
|
||||
设置远程仓库地址
|
||||
git remote set-url origin ssh://renjianbo@101.43.95.130:29419/zhini_im_android
|
||||
133
docs/学习笔记/生成并配置SSH密钥、克隆仓库.md
Normal file
133
docs/学习笔记/生成并配置SSH密钥、克隆仓库.md
Normal file
@@ -0,0 +1,133 @@
|
||||
你的操作指南非常详细和准确!我帮你重新整理了一个更清晰的流程,并修复了流程图的语法:
|
||||
|
||||
## 完整操作流程
|
||||
|
||||
### **第一步:生成SSH密钥(在新电脑上)**
|
||||
|
||||
```bash
|
||||
# 1. 生成SSH密钥(使用ed25519算法,更安全)
|
||||
ssh-keygen -t ed25519 -C "renjianbo@example.com"
|
||||
|
||||
# 按提示操作:
|
||||
# - 直接回车使用默认路径 (~/.ssh/id_ed25519)
|
||||
# - 可以设置密码(可选)
|
||||
# - 再次确认密码
|
||||
|
||||
# 2. 查看公钥并复制
|
||||
cat ~/.ssh/id_ed25519.pub
|
||||
```
|
||||
**输出示例:**
|
||||
```
|
||||
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIJL...你的公钥内容... renjianbo@example.com
|
||||
```
|
||||
|
||||
### **第二步:添加公钥到Gerrit账户**
|
||||
|
||||
1. 登录 Gerrit:`http://101.43.95.130:8080/`
|
||||
2. 点击右上角 **renjianbo** → **Settings** → **SSH Keys**
|
||||
3. 点击 **Add Key** 按钮
|
||||
4. 粘贴复制的公钥内容,保存
|
||||
|
||||
### **第三步:克隆项目**
|
||||
|
||||
#### **方式A:SSH协议(推荐)**
|
||||
```bash
|
||||
# 使用你的用户名 renjianbo
|
||||
git clone ssh://renjianbo@101.43.95.130:29418/zhini_im
|
||||
```
|
||||
|
||||
#### **方式B:HTTP协议(备用)**
|
||||
```bash
|
||||
git clone http://101.43.95.130:8080/zhini_im
|
||||
# 可能需要输入用户名密码
|
||||
```
|
||||
|
||||
### **第四步:验证和配置**
|
||||
|
||||
```bash
|
||||
# 1. 进入项目目录
|
||||
cd zhini_im
|
||||
|
||||
# 2. 查看远程仓库地址
|
||||
git remote -v
|
||||
# 应该显示类似:origin ssh://renjianbo@101.43.95.130:29418/zhini_im
|
||||
|
||||
# 3. 配置用户信息(重要!)
|
||||
git config user.name "renjianbo"
|
||||
git config user.email "renjianbo@example.com" # 使用你的Gerrit注册邮箱
|
||||
|
||||
# 4. 可选:验证SSH连接
|
||||
ssh -p 29418 renjianbo@101.43.95.130
|
||||
# 如果看到 Gerrit 欢迎信息,说明连接成功
|
||||
```
|
||||
|
||||
## **操作流程图**
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
Start[开始] --> GenKey[生成SSH密钥<br>ssh-keygen]
|
||||
GenKey --> CopyKey[复制公钥<br>cat ~/.ssh/id_ed25519.pub]
|
||||
CopyKey --> LoginGerrit[登录Gerrit网页]
|
||||
LoginGerrit --> AddKey[添加公钥到SSH Keys]
|
||||
|
||||
AddKey --> ChooseMethod{选择克隆方式}
|
||||
ChooseMethod --> SSH[SSH协议<br>git clone ssh://renjianbo@...]
|
||||
ChooseMethod --> HTTP[HTTP协议<br>git clone http://...]
|
||||
|
||||
SSH --> Verify[进入目录验证]
|
||||
HTTP --> Verify
|
||||
Verify --> Config[配置用户信息]
|
||||
Config --> Done[完成]
|
||||
```
|
||||
|
||||
## **常见问题解决**
|
||||
|
||||
### **1. SSH连接被拒绝**
|
||||
```bash
|
||||
# 测试SSH连接
|
||||
ssh -p 29418 -T renjianbo@101.43.95.130
|
||||
|
||||
# 如果提示"Permission denied",检查:
|
||||
# - 公钥是否正确添加到Gerrit
|
||||
# - 用户名是否正确(不是admin,是renjianbo)
|
||||
# - 是否有仓库访问权限
|
||||
```
|
||||
|
||||
### **2. 首次连接需要确认主机**
|
||||
```
|
||||
The authenticity of host '[101.43.95.130]:29418' can't be established.
|
||||
ECDSA key fingerprint is SHA256:xxx...
|
||||
Are you sure you want to continue connecting (yes/no/[fingerprint])?
|
||||
```
|
||||
**输入:** `yes`
|
||||
|
||||
### **3. 端口被阻挡**
|
||||
- 检查防火墙是否允许29418端口
|
||||
- 在公司网络可能需要配置代理
|
||||
|
||||
### **4. 克隆速度慢**
|
||||
```bash
|
||||
# 可以尝试浅克隆(只获取最新版本)
|
||||
git clone --depth 1 ssh://renjianbo@101.43.95.130:29418/zhini_im
|
||||
```
|
||||
|
||||
## **快捷脚本**
|
||||
创建一键克隆脚本 `clone_zhini_im.sh`:
|
||||
```bash
|
||||
#!/bin/bash
|
||||
# 克隆智拟IM项目
|
||||
echo "正在克隆智拟IM项目..."
|
||||
git clone ssh://renjianbo@101.43.95.130:29418/zhini_im
|
||||
cd zhini_im
|
||||
git config user.name "renjianbo"
|
||||
git config user.email "renjianbo@example.com"
|
||||
echo "克隆完成!"
|
||||
```
|
||||
|
||||
执行:
|
||||
```bash
|
||||
chmod +x clone_zhini_im.sh
|
||||
./clone_zhini_im.sh
|
||||
```
|
||||
|
||||
按照这个流程操作,你应该能成功将项目拉到新电脑。如果遇到具体错误,可以把错误信息发给我,我会帮你诊断解决。
|
||||
@@ -61,6 +61,10 @@ nav:
|
||||
- 学习笔记/前端学习.md
|
||||
- 学习笔记/DevOps学习.md
|
||||
- 学习笔记/gerrit上传代码详细指南.md
|
||||
- 学习笔记/gerrit分支规范.md
|
||||
- 学习笔记/生成并配置SSH密钥、克隆仓库.md
|
||||
- 学习笔记/git设置用户名和邮箱.md
|
||||
- 学习笔记/git同步远程分支总结.md
|
||||
- 学习笔记/MkDocs 是什么.md
|
||||
|
||||
# Markdown扩展
|
||||
@@ -85,4 +89,3 @@ markdown_extensions:
|
||||
|
||||
# 版权信息
|
||||
copyright: Copyright © 2024 renjianbo
|
||||
|
||||
|
||||
Reference in New Issue
Block a user