来源:AI开发日志公众号专辑「Build Your Own X With AI」
原文链接:https://mp.weixin.qq.com/s?__biz=MzUxMjg3MjE2OA==&mid=2247486201&idx=1&sn=5cc4a8934da3dcb081f2fd0fb60a3df3&chksm=f95c917ece2b186884d50a04518981a2878cc7e96b186dcd23afd06fb3b18ab3868a62eab0a7#rd
⏺
Git Client - 支持 SSH 的简易 Git 客户端
| English | 简体中文 |
一个功能完整、用户友好的 Git 客户端,使用 Python 构建,提供完整的 SSH 支持用于 GitHub。适合学习 Git 内部原理或作为标准 Git CLI 的轻量级替代品。
功能特性
核心功能
基础 Git 操作
:init、clone、add、commit、push、pull
分支管理
:创建、切换、删除、合并分支
历史查看
:log、diff、status、show commits
远程管理
:添加和列出远程仓库
SSH 密钥管理
:生成、管理和测试 SSH 密钥
配置管理
:持久化用户设置
特色亮点
美观的终端 UI,带彩色输出
自动 SSH 密钥检测和设置
GitHub SSH 连接测试
全面的错误处理
Rich 格式化的详细提交历史
支持所有标准 Git 工作流
安装
前置要求
Python 3.8 或更高版本
pip(Python 包管理器)
OpenSSH(用于 SSH 操作)
从源码安装
克隆仓库
git clone git@github.com:build-your-own-x-with-ai/AI_Git.git
cd AI_Git
安装依赖
pip install -r requirements.txt
安装包
pip install -e .
安装后,您可以在任何地方使用 gitc 命令。
快速开始
- 生成 SSH 密钥(首次设置)
生成新的 SSH 密钥
gitc ssh keygen –email your-email@example.com
公钥将被显示,复制并添加到 GitHub:
https://github.com/settings/ssh/new
测试 GitHub SSH 连接
gitc ssh test
- 初始化仓库
创建新仓库
gitc init
或克隆现有仓库
gitc clone git@github.com:username/repo.git
- 基础工作流
查看仓库状态
gitc status
添加文件到暂存区
gitc add –all
提交更改
gitc commit -m ”Your commit message”
推送到 GitHub
gitc push -u origin main
命令参考
SSH 管理
生成 SSH 密钥
gitc ssh keygen –email your@email.com
显示公钥
gitc ssh show
添加 SSH 密钥到 agent
gitc ssh add
测试 GitHub 连接
gitc ssh test
仓库操作
初始化新仓库
gitc init [path]
克隆仓库
gitc clone
查看仓库状态
gitc status
添加文件到暂存区
gitc add
gitc add –all # 添加所有文件
提交更改
gitc commit -m ”message” [–author-name ”Name”] [–author-email ”email”]
推送到远程
gitc push [–remote origin] [–branch main] [-u]
从远程拉取
gitc pull [–remote origin] [–branch main]
分支管理
列出分支
gitc branch list # 仅本地分支
gitc branch list –all # 包括远程分支
创建新分支
gitc branch create
切换分支
gitc branch switch
gitc branch switch -c
删除分支
gitc branch delete
gitc branch delete -f
合并分支
gitc branch merge
历史和检查
查看提交历史
gitc log [-n count] [–branch name] [–author name] [–since date]
显示差异
gitc diff # 未暂存的更改
gitc diff –cached # 已暂存的更改
gitc diff
gitc diff –file
显示提交详情
gitc show
远程管理
添加远程
gitc remote add
列出远程
gitc remote list
实现原理
架构设计
Git Client 采用模块化的分层架构,将功能明确分离到不同的层次:
┌─────────────────────────────────────────┐
│ CLI Layer (cli/) │
│ 命令行界面、参数解析、输出格式化 │
└────────────────┬────────────────────────┘
│
┌────────────────▼────────────────────────┐
│ Core Layer (core/) │
│ Git 操作、分支管理、历史查看 │
└────────────────┬────────────────────────┘
│
┌────────────────▼────────────────────────┐
│ Utils Layer (utils/) │
│ SSH 管理、配置、日志、错误处理 │
└────────────────┬────────────────────────┘
│
┌────────────────▼────────────────────────┐
│ External Libraries │
│ GitPython、Paramiko、Cryptography │
└─────────────────────────────────────────┘
核心模块详解
- Git 操作模块 (git_operations.py)
设计思路:
封装 GitPython 库,提供统一的接口
所有方法返回 Tuple[bool, str/dict] 格式,便于错误处理
自动检测 Git 仓库,提供友好的错误提示
核心实现:
classGitOperations:
def__init__(self, repo_path: str = ”.”):
self.repo_path = Path(repo_path).resolve()
self.repo: Optional[Repo] = None
if self._is_git_repo():
self.repo = Repo(self.repo_path)
关键技术点:
仓库检测
:使用 InvalidGitRepositoryError 异常判断
状态管理
:通过 repo.index.diff() 获取暂存和未暂存的更改
推送检测
:检查 PushInfo 标志位(ERROR、REJECTED、REMOTE_FAILURE 等)
defpush(self, remote: str = ”origin”, branch: Optional[str] = None,
set_upstream: bool = False) -> Tuple[bool, str]:
检查推送结果的各种状态标志
if push_info.flags & push_info.ERROR:
returnFalse, f”Push failed: {error_msg}”
elif push_info.flags & push_info.REJECTED:
returnFalse, f”Push rejected (non-fast-forward)”
… 更多状态检查
- 分支管理模块 (branch_manager.py)
设计思路:
独立的分支操作类,职责单一
支持本地和远程分支的统一管理
安全的分支删除(检查是否已合并)
核心实现:
defswitch_branch(self, branch_name: str, create: bool = False):
检查分支是否存在
branch_exists = branch_name in [b.name for b in self.repo.branches]
ifnot branch_exists and create:
self.repo.create_head(branch_name)
切换分支
self.repo.heads[branch_name].checkout()
关键技术点:
分支列表
:遍历 repo.branches 和 repo.remotes[].refs
合并操作
:使用 merge_base() 查找共同祖先,merge_tree() 执行合并
冲突检测
:捕获 GitCommandError,检查是否包含 “conflict”
- 历史查看模块 (history_viewer.py)
设计思路:
提供丰富的历史查询功能
支持过滤(作者、时间、分支)
格式化输出,便于阅读
核心实现:
deflog(self, max_count: int = 10, branch: Optional[str] = None,
author: Optional[str] = None, since: Optional[str] = None):
kwargs = {‘max_count’: max_count}
if author:
kwargs[‘author’] = author
commits = []
for commit in self.repo.iter_commits(**kwargs):
commits.append({
“hash”: commit.hexsha[:7],
“author”: f”{commit.author.name}”,
“date”: datetime.fromtimestamp(commit.committed_date),
“message”: commit.message.strip()
})
关键技术点:
差异计算
:使用 diff() 方法比较提交、暂存区、工作目录
语法高亮
:集成 Rich 的 Syntax 类显示彩色 diff
Blame 功能
:使用 repo.blame() 追踪每行代码的修改者
- SSH 密钥管理模块 (ssh_manager.py)
设计思路:
完整的 SSH 密钥生命周期管理
使用 cryptography 库生成高强度密钥
自动配置 SSH 环境
核心实现:
defgenerate_ssh_key(self, email: str, overwrite: bool = False):
生成 4096 位 RSA 密钥
key = rsa.generate_private_key(
backend=default_backend(),
public_exponent=65537,
key_size=4096
)
保存私钥(PEM 格式)
private_pem = key.private_bytes(
encoding=serialization.Encoding.PEM,
format=serialization.PrivateFormat.OpenSSH,
encryption_algorithm=serialization.NoEncryption()
)
设置正确的权限
os.chmod(self.private_key_path, 0o600)
关键技术点:
密钥格式:
私钥:OpenSSH PEM 格式,无加密
公钥:OpenSSH 格式,附带邮箱标识
权限设置:
私钥:0o600(仅所有者可读写)
公钥:0o644(所有者可读写,其他人可读)
SSH 目录:0o700(仅所有者访问)
连接测试:
deftest_github_connection(self):
result = subprocess.run(
[“ssh”, ”-T”, ”git@github.com”,
“-o”, ”StrictHostKeyChecking=no”],
capture_output=True, text=True, timeout=10
)
GitHub 认证成功返回 exit code 1
if”successfully authenticated”in output.lower():
returnTrue, ”Connection successful”
SSH Config 配置:
Host github.com
HostName github.com
User git
IdentityFile ~/.ssh/id_rsa
IdentitiesOnly yes
- CLI 界面模块 (main.py)
设计思路:
使用 Click 框架构建命令行界面
使用 Rich 库美化输出
分离正常输出和错误输出
核心实现:
创建两个控制台实例
console = Console() # 标准输出
error_console = Console(stderr=True) # 错误输出
@cli.command()
@click.option(‘–message’, ’-m’, required=True)
defcommit(message, author_name, author_email, path):
git_ops = GitOperations(path)
success, msg = git_ops.commit(message, author_name, author_email)
if success:
console.print(f”[green]✓[/green] {msg}”)
else:
error_console.print(f”[red]✗[/red] {msg}”)
sys.exit(1)
关键技术点:
命令组织:使用 Click 的 @group 装饰器组织子命令
@cli.group()
defbranch():
”"”Branch management commands”””
pass
@branch.command(‘list’)
deflist_branches():
实现
表格输出:使用 Rich 的 Table 类
table = Table(title=”Branches”)
table.add_column(“Name”, style=”magenta”)
table.add_column(“Commit”, style=”yellow”)
for br in branches:
table.add_row(br[‘name’], br[‘commit’])
console.print(table)
语法高亮:使用 Rich 的 Syntax 类
syntax = Syntax(diff_text, ”diff”,
theme=”monokai”,
line_numbers=False)
console.print(syntax)
- 配置管理模块 (config_manager.py)
设计思路:
JSON 格式存储配置
支持点号分隔的键名(如 user.name)
提供配置验证功能
核心实现:
classConfigManager:
def__init__(self):
self.config_dir = Path.home() / ”.gitc”
self.config_file = self.config_dir / ”config.json”
self.config = self._load_config()
defset(self, key: str, value: Any):
keys = key.split(‘.’)
config = self.config
导航到目标键的父级
for k in keys[:-1]:
if k notin config:
config[k] = {}
config = config[k]
设置值
config[keys[-1]] = value
return self.save_config()
配置结构:
{
“user”:{
“name”:”Your Name”,
“email”:”your@email.com”
},
“ssh”:{
“key_path”:”/Users/xxx/.ssh/id_rsa”
},
“defaults”:{
“remote”:”origin”,
“branch”:”main”
},
“preferences”:{
“auto_add_ssh_key”:true,
“verbose”:false,
“color”:true
}
}
技术实现细节
错误处理策略
三层错误处理机制:
异常捕获:
try:
Git 操作
except GitCommandError as e:
returnFalse, f”Git error: {e.stderr}”
except Exception as e:
returnFalse, f”Error: {str(e)}”
返回值检查:
success, message = git_ops.commit(msg)
ifnot success:
error_console.print(f”[red]✗[/red] {message}”)
sys.exit(1)
用户友好提示:
提供具体的错误原因
建议可能的解决方案
错误输出到 stderr,便于脚本处理
推送状态检测
PushInfo 标志位系统:
GitPython 返回的 PushInfo 对象包含多个标志位,需要正确检测:
错误标志(优先级最高)
ERROR = 1 « 0# 推送错误
REJECTED = 1 « 1# 被拒绝(非快进)
REMOTE_REJECTED = 1 « 2# 远程拒绝
REMOTE_FAILURE = 1 « 3# 远程失败
成功标志
UP_TO_DATE = 1 « 4# 已是最新
NEW_TAG = 1 « 5# 新标签
NEW_HEAD = 1 « 6# 新分支
FAST_FORWARD = 1 « 7# 快进合并
FORCED_UPDATE = 1 « 8# 强制更新
检测顺序:
先检查错误标志
再检查成功标志
提取具体的错误信息
SSH 密钥生成算法
RSA 密钥参数选择:
参数说明
public_exponent=65537# 标准的公钥指数(F4)
key_size=4096# 密钥长度(4096 位更安全)
为什么选择这些参数:
公钥指数 65537:
是一个质数(第 4 个费马数)
二进制表示简单:10000000000000001
加密运算快速
是 RSA 标准推荐值
密钥长度 4096:
GitHub 推荐最小 2048 位
4096 位提供更高安全性
适合长期使用
性能开销可接受
并发和性能优化
优化策略:
懒加载:
def__init__(self, repo_path: str = ”.”):
self.repo: Optional[Repo] = None
if self._is_git_repo():
self.repo = Repo(self.repo_path) # 仅在需要时加载
缓存配置:
classConfigManager:
def__init__(self):
self.config = self._load_config() # 加载一次,重复使用
批量操作:
defadd(self, files: List[str], all_files: bool = False):
if all_files:
self.repo.git.add(A=True) # 一次性添加所有文件
else:
self.repo.index.add(files) # 批量添加指定文件
关键技术挑战及解决方案
挑战 1:Rich Console 的 stderr 输出
问题:Rich 的 Console.print() 不支持 err=True 参数
解决方案:
console = Console() # 正常输出
error_console = Console(stderr=True) # 错误输出
使用不同的控制台
console.print(“[green]Success”)
error_console.print(“[red]Error”)
挑战 2:路径管理
问题:开发模式和安装模式的导入路径不一致
解决方案:
移除 sys.path.insert()
使用标准的包导入:from git_client.core import GitOperations
通过 setup.py 正确安装包
挑战 3:推送失败检测
问题:GitPython 即使推送失败也返回结果对象
解决方案:
result = origin.push(branch)
push_info = result[0]
检查所有可能的错误标志
| if push_info.flags & (push_info.ERROR |
| push_info.REJECTED |
| push_info.REMOTE_REJECTED |
push_info.REMOTE_FAILURE):
returnFalse, ”Push failed”
挑战 4:SSH 密钥权限
问题:不正确的文件权限导致 SSH 拒绝使用密钥
解决方案:
SSH 要求严格的权限设置
os.chmod(private_key_path, 0o600) # 私钥:仅所有者读写
os.chmod(public_key_path, 0o644) # 公钥:所有者读写,其他人只读
os.chmod(ssh_dir, 0o700) # SSH 目录:仅所有者访问
测试策略
虽然当前版本主要进行了手动测试,但设计时已考虑可测试性:
单元测试设计:
deftest_init_repository():
git_ops = GitOperations(“/tmp/test_repo”)
success, message = git_ops.init()
assert success == True
assert”Initialized”in message
deftest_commit_without_changes():
git_ops = GitOperations(“/tmp/test_repo”)
success, message = git_ops.commit(“test”)
assert success == False
assert”nothing to commit”in message.lower()
集成测试设计:
deftest_complete_workflow():
初始化 -> 添加 -> 提交 -> 推送
git_ops = GitOperations(“/tmp/test_repo”)
git_ops.init()
git_ops.add(all_files=True)
git_ops.commit(“Initial commit”)
success, _ = git_ops.push()
assert success == True
扩展性设计
插件系统(未来):
可通过继承扩展功能
classCustomGitOps(GitOperations):
defcustom_operation(self):
自定义操作
pass
或通过装饰器添加功能
@git_operation
defmy_custom_command(repo):
自定义命令
pass
钩子系统(未来):
classGitHooks:
defpre_commit(self):
提交前检查
pass
defpost_commit(self):
提交后操作
pass
项目统计
代码行数
:~1,857 行 Python
模块数量
:7 个核心模块
CLI 命令
:20+ 个命令
文档文件
:5 份完整指南
依赖库
核心依赖
GitPython (3.1.40+):Git 操作的 Python 接口
提供完整的 Git 功能封装
支持所有标准 Git 命令
Click (8.1.7+):命令行界面框架
简洁的装饰器语法
自动生成帮助文档
类型验证和转换
Rich (13.7.0+):终端美化输出
彩色输出
表格和面板
语法高亮
进度条
Paramiko (3.4.0+):SSH 协议实现
SSH 连接管理
密钥认证
Cryptography (41.0.7+):加密和密钥生成
RSA 密钥生成
各种加密算法
X.509 证书支持
Colorama (0.4.6+):跨平台彩色输出
Windows 控制台颜色支持
ANSI 转义序列处理
使用示例
示例 1:创建并推送新项目
创建新目录并初始化
mkdir my-project
cd my-project
gitc init
创建文件
echo”# My Project” > README.md
添加并提交
gitc add –all
gitc commit -m ”Initial commit”
添加 GitHub 远程并推送
gitc remote add origin git@github.com:username/my-project.git
gitc push -u origin main
示例 2:使用分支
创建并切换到特性分支
gitc branch switch -c feature/amazing-feature
进行更改并提交
gitc add –all
gitc commit -m ”Add amazing feature”
推送特性分支
gitc push -u origin feature/amazing-feature
切换回 main 并合并
gitc branch switch main
gitc branch merge feature/amazing-feature
删除特性分支
gitc branch delete feature/amazing-feature
示例 3:查看项目历史
查看最近 5 次提交
gitc log -n 5
查看暂存区的更改
gitc diff –cached
查看两次提交之间的差异
gitc show abc123
检查当前状态
gitc status
故障排除
SSH 连接问题
如果遇到 SSH 连接问题:
验证 SSH 密钥存在
gitc ssh show
测试 GitHub 连接
gitc ssh test
添加密钥到 SSH agent
gitc ssh add
检查 SSH agent 是否运行
eval”$(ssh-agent -s)”
推送被拒绝
确保:
SSH 密钥已添加到 GitHub 账户
SSH agent 已加载您的密钥(gitc ssh add)
使用 SSH URL(git@github.com:…)而非 HTTPS
命令未找到
安装后,重启终端或运行:
source ~/.bashrc # 或 ~/.zshrc
性能特点
快速初始化
高效的文件操作
相比标准 Git 开销最小
小内存占用
快速命令执行
兼容性
操作系统
:macOS、Linux、Windows
Python 版本
:3.8、3.9、3.10、3.11、3.12、3.13
Git 平台
:GitHub、GitLab、Bitbucket(通过 SSH)
贡献
欢迎贡献!请随时提交问题或拉取请求。
详细信息请参阅 CONTRIBUTING.md。
许可证
MIT License - 详见 LICENSE 文件
鸣谢
构建使用:
GitPython - Git 接口
Click - CLI 框架
Rich - 终端美化
Paramiko - SSH 实现
支持
如有问题、疑问或贡献,请访问 GitHub 仓库。
仓库地址:https://github.com/build-your-own-x-with-ai/AI_Git
相关文档
English Documentation - 英文文档
Quick Start Guide - 快速入门指南
Contributing Guide - 贡献指南
Changelog - 版本历史
Deployment Guide - 部署说明
🎉 项目成功部署到 GitHub!
仓库地址
https://github.com/build-your-own-x-with-ai/AI_Git
已修复的问题
1. Rich Console 错误输出 ✅
-
创建了专用的 error_console 用于 stderr 输出
-
所有错误消息现在正确输出到标准错误流
2. 路径冲突 ✅
-
移除了导致冲突的 sys.path.insert()
-
已安装的包现在使用正确的导入路径
3. Push 状态检测 ✅
-
添加了完整的 PushInfo 标志检查
-
现在能正确检测:ERROR, REJECTED, REMOTE_REJECTED, REMOTE_FAILURE
-
推送失败会立即报告
4. 仓库清理 ✅
-
使用干净的源目录重新初始化
-
正确的 .gitignore 配置
-
成功推送到 GitHub
最终提交
4dc43b7 - Initial commit: Git Client with SSH support
fe24247 - Fix: Improve error handling and push status detection
2964efd - Add deployment guide
功能验证
所有核心功能已测试通过:
-
✅ gitc init - 初始化仓库
-
✅ gitc add - 添加文件
-
✅ gitc commit - 提交更改
-
✅ gitc push - 推送到远程(包含正确的错误检测)
-
✅ gitc pull - 从远程拉取
-
✅ gitc status - 查看状态
-
✅ gitc branch - 分支管理
-
✅ gitc log - 查看历史
-
✅ gitc remote - 远程管理
-
✅ gitc ssh - SSH 密钥管理
项目文档
-
✅ README.md - 完整使用文档
-
✅ QUICKSTART.md - 快速入门指南
-
✅ CONTRIBUTING.md - 贡献指南
-
✅ CHANGELOG.md - 版本历史
-
✅ DEPLOYMENT.md - 部署说明
-
✅ PROJECT_SUMMARY.md - 项目总结
-
✅ examples.py - 代码示例
现在可以使用了!
克隆项目
git clone git@github.com:build-your-own-x-with-ai/AI_Git.git
cd AI_Git
安装
pip install -e .
开始使用
gitc –help
项目已完全就绪,所有功能正常工作!🚀