Compare commits
10 Commits
e20c435e43
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| 3af0c0dcc8 | |||
| e78e33731b | |||
| e8d607c602 | |||
| e8697e3676 | |||
| d6fbdf16e3 | |||
| 6973a327e4 | |||
| b75dee4536 | |||
| 19384439f2 | |||
| d9485e3c67 | |||
| 19a94c45bb |
360
AGENTS.md
Normal file
360
AGENTS.md
Normal file
@@ -0,0 +1,360 @@
|
|||||||
|
# Agent Guidelines for QuickGit
|
||||||
|
|
||||||
|
This document provides coding agents with essential information about the QuickGit codebase, including build commands, code style, and architectural conventions.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Project Overview
|
||||||
|
|
||||||
|
**QuickGit** is a modular CLI Git management tool written in Python 3.6+. It simplifies Git operations through an interactive menu system with colorful console output.
|
||||||
|
|
||||||
|
**Key Technologies:**
|
||||||
|
- Pure Python 3.6+ (no external dependencies)
|
||||||
|
- Standard library only: `subprocess`, `os`, `datetime`, `sys`
|
||||||
|
- Cross-platform support: Windows, Linux, macOS
|
||||||
|
- ANSI escape codes for colorful console output
|
||||||
|
- **SSH-only Git operations**: Supports GitHub and Gitea via SSH (no HTTPS support)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Build, Run, and Test Commands
|
||||||
|
|
||||||
|
### Running the Application
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Recommended: Run the modular version
|
||||||
|
python quickgit.py # Windows
|
||||||
|
python3 quickgit.py # Linux/macOS
|
||||||
|
|
||||||
|
# Platform-specific launchers:
|
||||||
|
run.bat # Windows (sets UTF-8 encoding)
|
||||||
|
./run.sh # Linux/macOS (first run: chmod +x run.sh)
|
||||||
|
|
||||||
|
# Legacy: Run the single-file version
|
||||||
|
python mengya_git_manager.py
|
||||||
|
```
|
||||||
|
|
||||||
|
### Testing
|
||||||
|
|
||||||
|
**No formal test suite exists yet.** Manual testing workflow:
|
||||||
|
|
||||||
|
1. **Prerequisite: Configure SSH keys**
|
||||||
|
```bash
|
||||||
|
# Generate SSH key if needed
|
||||||
|
ssh-keygen -t ed25519 -C "your_email@example.com"
|
||||||
|
|
||||||
|
# Test SSH connection
|
||||||
|
ssh -T git@github.com
|
||||||
|
ssh -T git@git.shumengya.top -p 8022
|
||||||
|
```
|
||||||
|
|
||||||
|
2. **Test in a clean directory:**
|
||||||
|
```bash
|
||||||
|
cd /path/to/test/directory
|
||||||
|
python E:\SmyProjects\Python\脚本\萌芽一键Git管理\quickgit.py
|
||||||
|
```
|
||||||
|
|
||||||
|
3. **Test each menu option:**
|
||||||
|
- Option 1: Initialize Git repo
|
||||||
|
- Option 2: Commit changes to local (requires changes)
|
||||||
|
- Option 3: Push to remote (requires SSH-configured remote)
|
||||||
|
- Option 4: Pull from remote (requires SSH-configured remote)
|
||||||
|
- Option 5: View status
|
||||||
|
- Option 6: Manage remotes (add GitHub/Gitea via SSH)
|
||||||
|
- Option 7: Exit
|
||||||
|
|
||||||
|
4. **Verify console output:**
|
||||||
|
- Check colors render correctly
|
||||||
|
- Ensure ASCII dividers align (60 chars wide)
|
||||||
|
- No encoding errors with Chinese characters
|
||||||
|
|
||||||
|
### Linting and Code Quality
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# No formal linting configured yet
|
||||||
|
# Recommended tools for future use:
|
||||||
|
# pip install pylint black mypy
|
||||||
|
|
||||||
|
# Type checking (Python 3.10+ syntax used):
|
||||||
|
# mypy quickgit/
|
||||||
|
|
||||||
|
# Formatting:
|
||||||
|
# black quickgit/ --line-length 100
|
||||||
|
|
||||||
|
# Linting:
|
||||||
|
# pylint quickgit/
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Code Style Guidelines
|
||||||
|
|
||||||
|
### File Organization
|
||||||
|
|
||||||
|
**Module Structure:**
|
||||||
|
```
|
||||||
|
quickgit/
|
||||||
|
├── __init__.py # Package init (empty)
|
||||||
|
├── config.py # Configuration constants
|
||||||
|
├── utils.py # Utilities (Colors, CommandExecutor, OutputFormatter, InputValidator, PlatformUtils)
|
||||||
|
├── git_operations.py # Git command wrapper (supports custom work directory)
|
||||||
|
├── remote_manager.py # Remote repository management
|
||||||
|
└── ui.py # User interface and menu system
|
||||||
|
```
|
||||||
|
|
||||||
|
**Principle:** Each module has a single, well-defined responsibility.
|
||||||
|
|
||||||
|
### Key Features
|
||||||
|
|
||||||
|
1. **Flexible Directory Management**: Users can select any directory to manage at startup
|
||||||
|
2. **Cross-platform Path Handling**: Automatic path normalization for Windows/Linux/macOS
|
||||||
|
3. **Directory Validation**: Real-time validation of user-provided paths
|
||||||
|
|
||||||
|
### Import Conventions
|
||||||
|
|
||||||
|
**Order:**
|
||||||
|
1. Standard library imports
|
||||||
|
2. Relative imports from `quickgit` package
|
||||||
|
|
||||||
|
**Style:**
|
||||||
|
```python
|
||||||
|
# Standard library
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
from datetime import datetime
|
||||||
|
|
||||||
|
# Internal modules (relative imports preferred)
|
||||||
|
from .utils import CommandExecutor, OutputFormatter, Colors
|
||||||
|
from .config import Config
|
||||||
|
```
|
||||||
|
|
||||||
|
**Lazy imports for circular dependency avoidance:**
|
||||||
|
```python
|
||||||
|
def some_function():
|
||||||
|
from .utils import Colors # Import inside function if needed
|
||||||
|
print(f"{Colors.CYAN}Message{Colors.ENDC}")
|
||||||
|
```
|
||||||
|
|
||||||
|
### Type Hints
|
||||||
|
|
||||||
|
**Required for all function signatures:**
|
||||||
|
|
||||||
|
```python
|
||||||
|
# Good
|
||||||
|
def run(command: str, show_output: bool = True) -> tuple[bool, str]:
|
||||||
|
"""Execute command and return (success, output)"""
|
||||||
|
pass
|
||||||
|
|
||||||
|
def get_remotes(self) -> list[str]:
|
||||||
|
"""Get all remote repositories"""
|
||||||
|
pass
|
||||||
|
|
||||||
|
def confirm(prompt: str, default: bool = False) -> bool:
|
||||||
|
"""Get user confirmation"""
|
||||||
|
pass
|
||||||
|
```
|
||||||
|
|
||||||
|
**Note:** Uses Python 3.10+ syntax (`list[str]`, `tuple[bool, str]`). For Python 3.6-3.9 compatibility, use:
|
||||||
|
```python
|
||||||
|
from typing import List, Tuple
|
||||||
|
def get_remotes(self) -> List[str]: ...
|
||||||
|
```
|
||||||
|
|
||||||
|
### Naming Conventions
|
||||||
|
|
||||||
|
- **Classes:** `PascalCase` (e.g., `GitOperations`, `RemoteManager`)
|
||||||
|
- **Functions/Methods:** `snake_case` (e.g., `add_github_remote`, `show_main_menu`)
|
||||||
|
- **Constants:** `UPPER_SNAKE_CASE` (e.g., `DEFAULT_BRANCH`, `GITEA_HOST`)
|
||||||
|
- **Private methods:** Prefix with `_` (e.g., `_create_gitignore`, `_add_remote`)
|
||||||
|
- **Module-level:** Avoid global variables; use `Config` class for constants
|
||||||
|
|
||||||
|
### Formatting and Whitespace
|
||||||
|
|
||||||
|
- **Line length:** Aim for 100 characters max (not strictly enforced)
|
||||||
|
- **Indentation:** 4 spaces (no tabs)
|
||||||
|
- **Blank lines:** 2 between top-level definitions, 1 between methods
|
||||||
|
- **Strings:** Use double quotes `"` for user-facing text, either for code strings
|
||||||
|
|
||||||
|
### Error Handling
|
||||||
|
|
||||||
|
**Always provide user-friendly feedback:**
|
||||||
|
|
||||||
|
```python
|
||||||
|
# Good
|
||||||
|
try:
|
||||||
|
with open('.gitignore', 'w', encoding='utf-8') as f:
|
||||||
|
f.write(Config.GITIGNORE_TEMPLATE)
|
||||||
|
OutputFormatter.success(".gitignore文件创建成功")
|
||||||
|
except Exception as e:
|
||||||
|
OutputFormatter.error(f".gitignore文件创建失败: {str(e)}")
|
||||||
|
```
|
||||||
|
|
||||||
|
**Command execution pattern:**
|
||||||
|
|
||||||
|
```python
|
||||||
|
success, output = self.executor.run("git status", show_output=False)
|
||||||
|
if success:
|
||||||
|
OutputFormatter.success("操作成功")
|
||||||
|
else:
|
||||||
|
OutputFormatter.error("操作失败")
|
||||||
|
return False
|
||||||
|
```
|
||||||
|
|
||||||
|
**Never swallow exceptions silently.** Always log errors via `OutputFormatter.error()`.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Console Output Guidelines
|
||||||
|
|
||||||
|
### Critical Rules
|
||||||
|
|
||||||
|
1. **NO EMOJI CHARACTERS** - They cause Windows console encoding errors
|
||||||
|
2. **NO UNICODE BOX-DRAWING** (`┌─┐│└┘╔═╗║╚╝`) - They misalign across terminals
|
||||||
|
3. **Use ASCII only:** `=`, `-`, `·` for dividers
|
||||||
|
4. **Status indicators:** `[√]`, `[×]`, `[i]`, `[!]`, `[>]` instead of Unicode symbols
|
||||||
|
5. **Fixed width:** All dividers are exactly 60 characters wide
|
||||||
|
|
||||||
|
### Color Usage
|
||||||
|
|
||||||
|
**Color scheme:**
|
||||||
|
```python
|
||||||
|
Colors.BRIGHT_GREEN # Success messages
|
||||||
|
Colors.BRIGHT_RED # Errors
|
||||||
|
Colors.BRIGHT_CYAN # Info/prompts
|
||||||
|
Colors.BRIGHT_YELLOW # Warnings/section headers
|
||||||
|
Colors.BRIGHT_MAGENTA # Main headers
|
||||||
|
Colors.WHITE # General text
|
||||||
|
```
|
||||||
|
|
||||||
|
**Always reset colors:**
|
||||||
|
```python
|
||||||
|
print(f"{Colors.BRIGHT_GREEN}Success{Colors.ENDC}") # ENDC resets to default
|
||||||
|
```
|
||||||
|
|
||||||
|
### Output Formatting Functions
|
||||||
|
|
||||||
|
```python
|
||||||
|
OutputFormatter.header("Title") # Top-level header (cyan/magenta)
|
||||||
|
OutputFormatter.section("Section") # Section header (yellow/blue)
|
||||||
|
OutputFormatter.divider() # 60-char line: ----------
|
||||||
|
OutputFormatter.success("Done!") # [√] Green success
|
||||||
|
OutputFormatter.error("Failed!") # [×] Red error
|
||||||
|
OutputFormatter.info("Note...") # [i] Cyan info
|
||||||
|
OutputFormatter.warning("Warning!") # [!] Yellow warning
|
||||||
|
OutputFormatter.tip("Tip...") # [*] Cyan tip/suggestion
|
||||||
|
OutputFormatter.step(1, "Step one") # [1] Step indicator
|
||||||
|
OutputFormatter.menu_item(1, "Option") # [1] Menu item
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Git Operations Patterns
|
||||||
|
|
||||||
|
### SSH Configuration
|
||||||
|
|
||||||
|
**⚠️ IMPORTANT: This tool ONLY supports SSH connections. HTTPS is not supported.**
|
||||||
|
|
||||||
|
- **GitHub:** `git@github.com:shumengya/{repo}.git`
|
||||||
|
- **Gitea:** `ssh://git@git.shumengya.top:8022/{user}/{repo}.git`
|
||||||
|
|
||||||
|
All remote operations (push, pull, fetch) use SSH. Do not use HTTPS URLs like `https://github.com/user/repo.git`.
|
||||||
|
|
||||||
|
**Prerequisites:**
|
||||||
|
1. User must have SSH keys generated (`ssh-keygen`)
|
||||||
|
2. Public key must be added to GitHub/Gitea account
|
||||||
|
3. SSH connection must be tested and working
|
||||||
|
|
||||||
|
### Command Execution
|
||||||
|
|
||||||
|
**Pattern for all Git commands:**
|
||||||
|
|
||||||
|
```python
|
||||||
|
# 1. Show status indicator
|
||||||
|
OutputFormatter.status('running', "Pushing to remote...")
|
||||||
|
|
||||||
|
# 2. Execute command (capture output)
|
||||||
|
success, output = self.executor.run("git push origin main", show_output=True)
|
||||||
|
|
||||||
|
# 3. Provide feedback
|
||||||
|
if success:
|
||||||
|
OutputFormatter.success("Push successful")
|
||||||
|
else:
|
||||||
|
OutputFormatter.error("Push failed")
|
||||||
|
|
||||||
|
return success
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Adding New Features
|
||||||
|
|
||||||
|
### Checklist for New Functionality
|
||||||
|
|
||||||
|
1. **Determine the module:** Where does this feature belong?
|
||||||
|
- Git operations → `git_operations.py`
|
||||||
|
- Remote management → `remote_manager.py`
|
||||||
|
- UI/menus → `ui.py`
|
||||||
|
- Config/constants → `config.py`
|
||||||
|
- Utilities → `utils.py`
|
||||||
|
|
||||||
|
2. **Add type hints** to all functions
|
||||||
|
|
||||||
|
3. **Use OutputFormatter** for all user-facing messages
|
||||||
|
|
||||||
|
4. **Test manually** in a clean directory
|
||||||
|
|
||||||
|
5. **Update README.md** if adding user-facing features
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Common Gotchas
|
||||||
|
|
||||||
|
1. **Windows path handling:** Use `os.path` or `pathlib` for cross-platform paths
|
||||||
|
2. **Encoding:** All file I/O must specify `encoding='utf-8'`
|
||||||
|
3. **Subprocess:** Always use `encoding='utf-8', errors='ignore'` in `subprocess.run()`
|
||||||
|
4. **Git output:** Some commands have localized output; parse carefully
|
||||||
|
5. **Empty commits:** Check `git status --short` before committing
|
||||||
|
6. **Divider width:** Always use exactly 60 characters for consistency
|
||||||
|
7. **Platform differences:**
|
||||||
|
- Use `python3` on Linux/macOS, `python` on Windows
|
||||||
|
- Shell scripts: `.sh` for Unix, `.bat` for Windows
|
||||||
|
- Clear screen: Use `PlatformUtils.clear_screen()` for cross-platform support
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Platform-Specific Notes
|
||||||
|
|
||||||
|
### Windows
|
||||||
|
- Use `run.bat` launcher to set UTF-8 encoding (`chcp 65001`)
|
||||||
|
- ANSI colors supported on Windows 10+ by default
|
||||||
|
- Python command: `python` (not `python3`)
|
||||||
|
|
||||||
|
### Linux/macOS
|
||||||
|
- Use `run.sh` launcher (requires `chmod +x run.sh` first time)
|
||||||
|
- Ensure terminal supports UTF-8 encoding
|
||||||
|
- Python command: `python3` (not `python`)
|
||||||
|
- Shell uses bash (shebang: `#!/bin/bash`)
|
||||||
|
|
||||||
|
### Cross-Platform Code
|
||||||
|
- Use `PlatformUtils.is_windows()`, `is_linux()`, `is_mac()` for platform detection
|
||||||
|
- Use `PlatformUtils.clear_screen()` instead of `os.system('cls')` or `os.system('clear')`
|
||||||
|
- Always use `os.path.join()` or `pathlib.Path` for file paths
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Future Development Notes
|
||||||
|
|
||||||
|
**Planned features (not yet implemented):**
|
||||||
|
- Branch management
|
||||||
|
- Tag management
|
||||||
|
- Conflict resolution assistance
|
||||||
|
- Custom configuration file support
|
||||||
|
- Batch operations for multiple repositories
|
||||||
|
- Formal test suite (pytest recommended)
|
||||||
|
- CI/CD pipeline
|
||||||
|
|
||||||
|
**When implementing these:**
|
||||||
|
- Follow the existing modular architecture
|
||||||
|
- Add to appropriate module (or create new module if needed)
|
||||||
|
- Maintain the colorful, user-friendly console output style
|
||||||
|
- Keep Windows compatibility in mind
|
||||||
122
CLAUDE.md
Normal file
122
CLAUDE.md
Normal file
@@ -0,0 +1,122 @@
|
|||||||
|
# CLAUDE.md
|
||||||
|
|
||||||
|
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
||||||
|
|
||||||
|
## Project Overview
|
||||||
|
|
||||||
|
QuickGit (萌芽一键Git管理工具) is a Python CLI tool that simplifies Git operations through an interactive menu interface. It supports managing multiple Git repositories, handles both GitHub and Gitea remotes, and provides cross-platform compatibility (Windows, Linux, macOS).
|
||||||
|
|
||||||
|
## Running the Application
|
||||||
|
|
||||||
|
**Windows:**
|
||||||
|
```bash
|
||||||
|
run.bat # Recommended - sets UTF-8 encoding
|
||||||
|
python quickgit.py # Direct execution
|
||||||
|
```
|
||||||
|
|
||||||
|
**Linux/macOS:**
|
||||||
|
```bash
|
||||||
|
./run.sh # Recommended (requires chmod +x run.sh first time)
|
||||||
|
python3 quickgit.py # Direct execution
|
||||||
|
```
|
||||||
|
|
||||||
|
The tool is interactive - no command-line arguments needed. On startup, it prompts for a Git repository directory to manage.
|
||||||
|
|
||||||
|
## Architecture
|
||||||
|
|
||||||
|
The codebase follows a modular design with clear separation of concerns:
|
||||||
|
|
||||||
|
### Module Hierarchy
|
||||||
|
|
||||||
|
```
|
||||||
|
quickgit.py (entry point)
|
||||||
|
└── ui.py (GitManagerUI)
|
||||||
|
├── git_operations.py (GitOperations)
|
||||||
|
├── remote_manager.py (RemoteManager)
|
||||||
|
├── utils.py (CommandExecutor, OutputFormatter, InputValidator, PlatformUtils)
|
||||||
|
└── config.py (Config)
|
||||||
|
```
|
||||||
|
|
||||||
|
### Key Design Patterns
|
||||||
|
|
||||||
|
**1. Utility Classes Pattern** (`utils.py`)
|
||||||
|
- `CommandExecutor`: Centralized subprocess execution with UTF-8 handling
|
||||||
|
- `OutputFormatter`: Consistent colored console output (success/error/info/warning/step)
|
||||||
|
- `InputValidator`: User input validation and directory path handling
|
||||||
|
- `PlatformUtils`: Cross-platform operations (clear screen, path normalization, platform detection)
|
||||||
|
- `Colors`: ANSI color code definitions
|
||||||
|
|
||||||
|
**2. Operations Layer** (`git_operations.py`)
|
||||||
|
- `GitOperations` class manages all Git commands
|
||||||
|
- Maintains working directory state (`self.current_dir`)
|
||||||
|
- All Git operations use `CommandExecutor` for consistency
|
||||||
|
- Methods return `tuple[bool, str]` for success status and output
|
||||||
|
|
||||||
|
**3. Remote Management** (`remote_manager.py`)
|
||||||
|
- Handles GitHub and Gitea remote repository configuration
|
||||||
|
- GitHub format: `git@github.com:shumengya/{repo}.git`
|
||||||
|
- Gitea format: `ssh://git@git.shumengya.top:8022/{user}/{repo}.git`
|
||||||
|
- Manages multiple remotes per repository
|
||||||
|
|
||||||
|
**4. Configuration** (`config.py`)
|
||||||
|
- Centralized configuration in `Config` class
|
||||||
|
- Gitea server: `git.shumengya.top:8022`
|
||||||
|
- GitHub user: `shumengya`
|
||||||
|
- Default branch: `main`
|
||||||
|
- Includes comprehensive `.gitignore` template for Node.js, Go, Python projects
|
||||||
|
|
||||||
|
### Cross-Platform Considerations
|
||||||
|
|
||||||
|
The codebase handles platform differences through `PlatformUtils`:
|
||||||
|
- Path normalization with `os.path.expanduser()` and `os.path.normpath()`
|
||||||
|
- Platform detection: `is_windows()`, `is_linux()`, `is_mac()`
|
||||||
|
- Clear screen: `cls` (Windows) vs `clear` (Unix)
|
||||||
|
- Python command: `python` (Windows) vs `python3` (Unix)
|
||||||
|
- UTF-8 encoding explicitly set in subprocess calls
|
||||||
|
|
||||||
|
### State Management
|
||||||
|
|
||||||
|
- `GitOperations` maintains `self.current_dir` for the working directory
|
||||||
|
- Directory can be changed via `change_directory()` method
|
||||||
|
- All Git commands execute in the context of `self.current_dir`
|
||||||
|
- UI layer (`ui.py`) orchestrates state between operations and remote management
|
||||||
|
|
||||||
|
## Important Implementation Details
|
||||||
|
|
||||||
|
**Commit Message Format:**
|
||||||
|
- Default format: `update: YYYY-MM-DD HH:MM:SS` (see `git_operations.py:145`)
|
||||||
|
- Generated using `datetime.now().strftime('%Y-%m-%d %H:%M:%S')`
|
||||||
|
|
||||||
|
**Git Initialization Workflow:**
|
||||||
|
1. Run `git init`
|
||||||
|
2. Create `main` branch with `git checkout -b main`
|
||||||
|
3. Create `.gitignore` from template
|
||||||
|
4. Initial commit with message "first commit"
|
||||||
|
|
||||||
|
**Push Strategy:**
|
||||||
|
- First attempts direct push: `git push {remote} {branch}`
|
||||||
|
- If fails, retries with upstream: `git push -u {remote} {branch}`
|
||||||
|
- This handles first-time pushes to new remotes
|
||||||
|
|
||||||
|
**Subprocess Execution:**
|
||||||
|
- All commands use `shell=True` for compatibility
|
||||||
|
- UTF-8 encoding with `errors='ignore'` for robustness
|
||||||
|
- Captures both stdout and stderr combined
|
||||||
|
- Returns `(success: bool, output: str)` tuple
|
||||||
|
|
||||||
|
## Configuration Customization
|
||||||
|
|
||||||
|
To modify default settings, edit `quickgit/config.py`:
|
||||||
|
- `GITEA_HOST` and `GITEA_PORT`: Gitea server details
|
||||||
|
- `GITHUB_USER`: Default GitHub username
|
||||||
|
- `DEFAULT_BRANCH`: Default branch name (currently "main")
|
||||||
|
- `GITIGNORE_TEMPLATE`: Template for auto-generated .gitignore files
|
||||||
|
|
||||||
|
## Testing Considerations
|
||||||
|
|
||||||
|
When testing or modifying Git operations:
|
||||||
|
- Test with both existing and non-existing repositories
|
||||||
|
- Verify cross-platform path handling (Windows backslashes vs Unix forward slashes)
|
||||||
|
- Test with repositories that have/don't have remotes configured
|
||||||
|
- Verify UTF-8 handling for commit messages with non-ASCII characters
|
||||||
|
- Test the push retry logic (direct push → upstream push fallback)
|
||||||
357
GitHub_SSH_故障排查.md
Normal file
357
GitHub_SSH_故障排查.md
Normal file
@@ -0,0 +1,357 @@
|
|||||||
|
# GitHub SSH 连接问题诊断与解决方案
|
||||||
|
|
||||||
|
**⚠️ QuickGit 工具说明:** 本工具目前仅支持 SSH 方式连接远程仓库,不支持 HTTPS。本文档中提到的 HTTPS 方案仅适用于手动使用 `git` 命令行操作,不适用于 QuickGit 工具本身。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 问题现象
|
||||||
|
|
||||||
|
```
|
||||||
|
Connection closed by 198.18.0.66 port 22
|
||||||
|
fatal: Could not read from remote repository.
|
||||||
|
```
|
||||||
|
|
||||||
|
这个错误表明 SSH 连接被关闭,可能的原因包括:
|
||||||
|
1. SSH 密钥未正确配置
|
||||||
|
2. SSH 密钥未添加到 GitHub
|
||||||
|
3. 网络问题或代理设置
|
||||||
|
4. SSH 配置文件问题
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 诊断步骤
|
||||||
|
|
||||||
|
### 第 1 步:检查 SSH 密钥是否存在
|
||||||
|
|
||||||
|
**Windows:**
|
||||||
|
```bash
|
||||||
|
dir %USERPROFILE%\.ssh
|
||||||
|
```
|
||||||
|
|
||||||
|
**Linux/macOS:**
|
||||||
|
```bash
|
||||||
|
ls -la ~/.ssh
|
||||||
|
```
|
||||||
|
|
||||||
|
**应该看到:**
|
||||||
|
- `id_rsa` 和 `id_rsa.pub` (RSA 密钥)
|
||||||
|
- 或 `id_ed25519` 和 `id_ed25519.pub` (Ed25519 密钥,推荐)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 第 2 步:如果没有 SSH 密钥,生成新密钥
|
||||||
|
|
||||||
|
**推荐方式 (Ed25519):**
|
||||||
|
```bash
|
||||||
|
ssh-keygen -t ed25519 -C "your_email@example.com"
|
||||||
|
```
|
||||||
|
|
||||||
|
**传统方式 (RSA):**
|
||||||
|
```bash
|
||||||
|
ssh-keygen -t rsa -b 4096 -C "your_email@example.com"
|
||||||
|
```
|
||||||
|
|
||||||
|
**执行过程:**
|
||||||
|
```
|
||||||
|
Generating public/private ed25519 key pair.
|
||||||
|
Enter file in which to save the key (/home/user/.ssh/id_ed25519): [直接回车]
|
||||||
|
Enter passphrase (empty for no passphrase): [可以直接回车或输入密码]
|
||||||
|
Enter same passphrase again: [重复密码]
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 第 3 步:查看公钥内容
|
||||||
|
|
||||||
|
**Windows:**
|
||||||
|
```bash
|
||||||
|
type %USERPROFILE%\.ssh\id_ed25519.pub
|
||||||
|
# 或
|
||||||
|
type %USERPROFILE%\.ssh\id_rsa.pub
|
||||||
|
```
|
||||||
|
|
||||||
|
**Linux/macOS:**
|
||||||
|
```bash
|
||||||
|
cat ~/.ssh/id_ed25519.pub
|
||||||
|
# 或
|
||||||
|
cat ~/.ssh/id_rsa.pub
|
||||||
|
```
|
||||||
|
|
||||||
|
**复制输出的完整内容**,类似:
|
||||||
|
```
|
||||||
|
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIM... your_email@example.com
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 第 4 步:添加公钥到 GitHub
|
||||||
|
|
||||||
|
1. **登录 GitHub**: https://github.com
|
||||||
|
2. **打开设置**: 点击右上角头像 → Settings
|
||||||
|
3. **SSH 和 GPG 密钥**: 左侧菜单 → SSH and GPG keys
|
||||||
|
4. **添加新密钥**: 点击 "New SSH key" 按钮
|
||||||
|
5. **填写信息:**
|
||||||
|
- Title: 给密钥起个名字(如:My Windows PC)
|
||||||
|
- Key: 粘贴第3步复制的公钥内容
|
||||||
|
6. **保存**: 点击 "Add SSH key"
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 第 5 步:测试 SSH 连接
|
||||||
|
|
||||||
|
```bash
|
||||||
|
ssh -T git@github.com
|
||||||
|
```
|
||||||
|
|
||||||
|
**成功的输出:**
|
||||||
|
```
|
||||||
|
Hi username! You've successfully authenticated, but GitHub does not provide shell access.
|
||||||
|
```
|
||||||
|
|
||||||
|
**如果仍然失败,继续下一步...**
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 常见问题与解决方案
|
||||||
|
|
||||||
|
### 问题 1: Connection closed by 198.18.0.66
|
||||||
|
|
||||||
|
这个 IP 地址 `198.18.0.66` 不是 GitHub 的官方 IP,可能是:
|
||||||
|
- 代理服务器
|
||||||
|
- VPN
|
||||||
|
- 公司网络的网关
|
||||||
|
|
||||||
|
**解决方案:检查代理设置**
|
||||||
|
|
||||||
|
#### 方案 A: 配置 Git 使用代理
|
||||||
|
|
||||||
|
如果您在使用代理,需要配置:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# HTTP 代理
|
||||||
|
git config --global http.proxy http://proxy_server:port
|
||||||
|
git config --global https.proxy https://proxy_server:port
|
||||||
|
|
||||||
|
# SOCKS5 代理
|
||||||
|
git config --global http.proxy socks5://proxy_server:port
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 方案 B: 取消代理设置
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git config --global --unset http.proxy
|
||||||
|
git config --global --unset https.proxy
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 方案 C: 为 SSH 配置代理
|
||||||
|
|
||||||
|
创建或编辑 `~/.ssh/config` 文件:
|
||||||
|
|
||||||
|
**Windows:** `C:\Users\YourName\.ssh\config`
|
||||||
|
**Linux/macOS:** `~/.ssh/config`
|
||||||
|
|
||||||
|
```
|
||||||
|
Host github.com
|
||||||
|
HostName github.com
|
||||||
|
User git
|
||||||
|
# 如果使用 HTTP 代理
|
||||||
|
ProxyCommand connect -H proxy_server:port %h %p
|
||||||
|
# 如果使用 SOCKS5 代理
|
||||||
|
# ProxyCommand connect -S proxy_server:port %h %p
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 问题 2: Permission denied (publickey)
|
||||||
|
|
||||||
|
**原因:** SSH 密钥未被识别
|
||||||
|
|
||||||
|
**解决方案:**
|
||||||
|
|
||||||
|
1. **启动 SSH Agent:**
|
||||||
|
```bash
|
||||||
|
# Windows (Git Bash)
|
||||||
|
eval "$(ssh-agent -s)"
|
||||||
|
|
||||||
|
# Linux/macOS
|
||||||
|
eval "$(ssh-agent -s)"
|
||||||
|
```
|
||||||
|
|
||||||
|
2. **添加私钥到 SSH Agent:**
|
||||||
|
```bash
|
||||||
|
ssh-add ~/.ssh/id_ed25519
|
||||||
|
# 或
|
||||||
|
ssh-add ~/.ssh/id_rsa
|
||||||
|
```
|
||||||
|
|
||||||
|
3. **再次测试连接:**
|
||||||
|
```bash
|
||||||
|
ssh -T git@github.com
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 问题 3: 防火墙阻止 SSH 端口 22
|
||||||
|
|
||||||
|
**解决方案 A: 使用 HTTPS 代替 SSH**
|
||||||
|
|
||||||
|
修改远程仓库 URL:
|
||||||
|
```bash
|
||||||
|
# 查看当前 URL
|
||||||
|
git remote -v
|
||||||
|
|
||||||
|
# 修改为 HTTPS
|
||||||
|
git remote set-url origin https://github.com/shumengya/QuickGit.git
|
||||||
|
```
|
||||||
|
|
||||||
|
**缺点:** 每次推送需要输入用户名和密码(或 Token)
|
||||||
|
|
||||||
|
**解决方案 B: 使用 SSH over HTTPS (端口 443)**
|
||||||
|
|
||||||
|
编辑 `~/.ssh/config`:
|
||||||
|
```
|
||||||
|
Host github.com
|
||||||
|
HostName ssh.github.com
|
||||||
|
Port 443
|
||||||
|
User git
|
||||||
|
```
|
||||||
|
|
||||||
|
测试:
|
||||||
|
```bash
|
||||||
|
ssh -T -p 443 git@ssh.github.com
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 问题 4: SSH 密钥格式错误
|
||||||
|
|
||||||
|
**原因:** Windows 换行符问题或复制时引入了额外字符
|
||||||
|
|
||||||
|
**解决方案:**
|
||||||
|
|
||||||
|
1. **重新生成密钥**(推荐)
|
||||||
|
2. **或确保公钥完整且格式正确**
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## QuickGit 用户的完整解决流程
|
||||||
|
|
||||||
|
### 步骤 1: 生成 SSH 密钥
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Windows (Git Bash 或 PowerShell)
|
||||||
|
ssh-keygen -t ed25519 -C "shumengya@example.com"
|
||||||
|
|
||||||
|
# 一路回车即可
|
||||||
|
```
|
||||||
|
|
||||||
|
### 步骤 2: 复制公钥
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Windows
|
||||||
|
type %USERPROFILE%\.ssh\id_ed25519.pub
|
||||||
|
|
||||||
|
# Linux/macOS
|
||||||
|
cat ~/.ssh/id_ed25519.pub
|
||||||
|
```
|
||||||
|
|
||||||
|
### 步骤 3: 添加到 GitHub
|
||||||
|
|
||||||
|
1. 访问 https://github.com/settings/keys
|
||||||
|
2. 点击 "New SSH key"
|
||||||
|
3. 粘贴公钥,保存
|
||||||
|
|
||||||
|
### 步骤 4: 测试连接
|
||||||
|
|
||||||
|
```bash
|
||||||
|
ssh -T git@github.com
|
||||||
|
```
|
||||||
|
|
||||||
|
**期望输出:**
|
||||||
|
```
|
||||||
|
Hi shumengya! You've successfully authenticated...
|
||||||
|
```
|
||||||
|
|
||||||
|
### 步骤 5: 在 QuickGit 中重新配置远程仓库
|
||||||
|
|
||||||
|
如果之前的远程仓库配置有问题:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 删除旧的 github 远程仓库
|
||||||
|
git remote remove github
|
||||||
|
|
||||||
|
# 重新添加
|
||||||
|
git remote add github git@github.com:shumengya/QuickGit.git
|
||||||
|
|
||||||
|
# 验证
|
||||||
|
git remote -v
|
||||||
|
```
|
||||||
|
|
||||||
|
### 步骤 6: 使用 QuickGit 推送
|
||||||
|
|
||||||
|
1. 启动 QuickGit
|
||||||
|
2. 选择 `[2] 提交更改到本地` - 提交到本地仓库
|
||||||
|
3. 选择 `[3] 推送到远程仓库` - 推送到 `github`(通过 SSH)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 调试命令
|
||||||
|
|
||||||
|
如果问题仍然存在,使用以下命令获取详细信息:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 详细模式测试 SSH 连接
|
||||||
|
ssh -vT git@github.com
|
||||||
|
|
||||||
|
# 查看 Git 配置
|
||||||
|
git config --list
|
||||||
|
|
||||||
|
# 查看远程仓库配置
|
||||||
|
git remote -v
|
||||||
|
|
||||||
|
# 手动推送(查看详细错误)
|
||||||
|
git push -v github main
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 快速修复:改用 HTTPS(仅适用于 git 命令行)
|
||||||
|
|
||||||
|
**⚠️ 重要:** 以下 HTTPS 方案仅适用于手动使用 `git` 命令行操作,**QuickGit 工具本身不支持 HTTPS**。
|
||||||
|
|
||||||
|
如果 SSH 问题难以解决,可以临时使用命令行的 HTTPS 方式:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 修改远程仓库 URL
|
||||||
|
git remote set-url github https://github.com/shumengya/QuickGit.git
|
||||||
|
|
||||||
|
# 推送(需要输入用户名和密码/Token)
|
||||||
|
git push github main
|
||||||
|
```
|
||||||
|
|
||||||
|
**注意:** HTTPS 方式需要:
|
||||||
|
- GitHub 用户名
|
||||||
|
- Personal Access Token(不能使用密码)
|
||||||
|
|
||||||
|
**生成 Token:**
|
||||||
|
1. GitHub → Settings → Developer settings → Personal access tokens → Tokens (classic)
|
||||||
|
2. Generate new token
|
||||||
|
3. 勾选 `repo` 权限
|
||||||
|
4. 复制 Token(只显示一次)
|
||||||
|
|
||||||
|
**再次强调:** QuickGit 工具不支持 HTTPS 远程仓库,必须使用 SSH。如果需要使用 HTTPS,请直接使用 `git` 命令行工具。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 总结
|
||||||
|
|
||||||
|
**推荐解决方案顺序(用于 QuickGit):**
|
||||||
|
|
||||||
|
1. ✅ 生成 SSH 密钥
|
||||||
|
2. ✅ 添加公钥到 GitHub
|
||||||
|
3. ✅ 测试 SSH 连接
|
||||||
|
4. ✅ 配置 SSH Agent(如果需要)
|
||||||
|
5. ⚠️ 检查代理设置(如果在公司网络)
|
||||||
|
6. ⚠️ 使用 SSH over HTTPS(端口 443)作为备选
|
||||||
|
|
||||||
|
**注意:** QuickGit 工具不支持 HTTPS 方式,必须解决 SSH 连接问题才能正常使用。如果实在无法配置 SSH,建议直接使用 `git` 命令行工具配合 HTTPS。
|
||||||
314
README.md
314
README.md
@@ -1,173 +1,241 @@
|
|||||||
# QuickGit - 萌芽一键Git管理工具
|
# QuickGit - 萌芽一键Git管理工具
|
||||||
|
|
||||||
一个简单易用的模块化Git命令行管理工具,让Git操作更加便捷高效。
|
一个纯 Python 3.6+、零外部依赖的彩色 CLI 工具,用模块化方式把常用 Git 操作"一键化",支持 Windows / Linux / macOS。
|
||||||
|
|
||||||
## 功能特性
|
**⚠️ 重要说明:** 本工具目前仅支持通过 **SSH 方式**连接 GitHub 和 Gitea 远程仓库,不支持 HTTPS 方式。使用前请确保已配置 SSH 密钥。
|
||||||
|
|
||||||
- **一键初始化Git仓库** - 自动完成Git初始化、分支创建、.gitignore配置
|
## 1) 项目简介与核心卖点
|
||||||
- **一键提交推送** - 快速提交代码并推送到远程仓库
|
- 模块化架构,功能职责清晰,易扩展。
|
||||||
- **多仓库支持** - 同时支持GitHub和Gitea仓库管理
|
- 无三方依赖,直接随 Python 运行。
|
||||||
- **远程仓库管理** - 便捷地添加、删除、查看远程仓库
|
- 跨平台路径与编码适配,默认分支 `main`。
|
||||||
- **状态查看** - 快速查看仓库状态和提交历史
|
- 彩色输出 + ASCII 分隔线,兼顾可读性与兼容性。
|
||||||
- **彩色界面** - 友好的彩色控制台输出
|
- **SSH 优先策略**:仅支持 SSH 连接,更安全、更便捷。
|
||||||
- **模块化设计** - 易于维护和扩展
|
|
||||||
|
|
||||||
## 项目结构
|
## 2) 功能清单
|
||||||
|
- [x] 灵活目录选择(启动时可管理任意仓库)
|
||||||
|
- [x] 初始化仓库(创建分支、生成 `.gitignore`)
|
||||||
|
- [x] 提交更改(提交到本地仓库)
|
||||||
|
- [x] 推送更改(推送到远程仓库,支持多远程选择,**仅支持 SSH**)
|
||||||
|
- [x] 从远程拉取(**仅支持 SSH**)
|
||||||
|
- [x] 远程仓库管理(GitHub / Gitea / 自建 Git 服务器,**仅支持 SSH 方式**)
|
||||||
|
- [x] **可配置 Gitea 服务器**(自定义主机地址和端口)
|
||||||
|
- [x] **自建 Git 仓库支持**(GitLab、自建 Gitea、Gogs 等)
|
||||||
|
- [x] 状态查看(工作区状态 + 最近提交)
|
||||||
|
- [ ] 分支管理
|
||||||
|
- [ ] 标签管理
|
||||||
|
- [ ] 冲突解决辅助
|
||||||
|
- [ ] 批量处理多个仓库
|
||||||
|
- [ ] HTTPS 支持(未来版本)
|
||||||
|
|
||||||
|
## 3) 项目结构
|
||||||
```
|
```
|
||||||
QuickGit/
|
QuickGit/
|
||||||
├── quickgit/ # 核心模块
|
├── quickgit/ # 核心模块
|
||||||
│ ├── __init__.py # 包初始化
|
│ ├── __init__.py
|
||||||
│ ├── config.py # 配置模块
|
│ ├── config.py # 常量与 .gitignore 模板
|
||||||
│ ├── utils.py # 工具类(命令执行、输出格式化、输入验证)
|
│ ├── utils.py # 颜色、输出、命令执行、输入校验、平台工具
|
||||||
│ ├── git_operations.py # Git操作模块
|
│ ├── git_operations.py # init / add / commit / push / pull / status
|
||||||
│ ├── remote_manager.py # 远程仓库管理模块
|
│ ├── remote_manager.py # 远程管理(GitHub/Gitea)
|
||||||
│ └── ui.py # UI交互模块
|
│ └── ui.py # 交互与菜单
|
||||||
├── quickgit.py # 主程序入口
|
├── quickgit.py # 主入口(模块化版本)
|
||||||
├── mengya_git_manager.py # 旧版单文件脚本(兼容保留)
|
├── run.bat # Windows 启动脚本(UTF-8)
|
||||||
└── README.md # 项目文档
|
├── run.sh # Linux/macOS 启动脚本(需 chmod +x)
|
||||||
|
├── mengya_git_manager.py # 旧版单文件脚本(兼容保留)
|
||||||
|
└── README.md
|
||||||
```
|
```
|
||||||
|
|
||||||
## 快速开始
|
## 4) 快速开始
|
||||||
|
|
||||||
### 运行脚本
|
### 前置要求
|
||||||
|
1. **必需**:已安装 Git 和 Python 3.6+
|
||||||
|
2. **必需**:已配置 SSH 密钥并添加到 GitHub/Gitea 账户
|
||||||
|
3. **推荐**:使用支持 ANSI 颜色的终端(Windows Terminal、PowerShell、iTerm2 等)
|
||||||
|
|
||||||
|
### SSH 密钥配置指南
|
||||||
|
如果你还没有配置 SSH 密钥,请按以下步骤操作:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# 使用新版模块化脚本(推荐)
|
# 1. 生成 SSH 密钥(如果还没有)
|
||||||
|
ssh-keygen -t ed25519 -C "your_email@example.com"
|
||||||
|
|
||||||
|
# 2. 查看公钥内容
|
||||||
|
cat ~/.ssh/id_ed25519.pub # Linux/macOS
|
||||||
|
type %USERPROFILE%\.ssh\id_ed25519.pub # Windows
|
||||||
|
|
||||||
|
# 3. 将公钥添加到远程仓库
|
||||||
|
# - GitHub: Settings -> SSH and GPG keys -> New SSH key
|
||||||
|
# - Gitea: 设置 -> SSH/GPG 密钥 -> 添加密钥
|
||||||
|
|
||||||
|
# 4. 测试连接
|
||||||
|
ssh -T git@github.com # 测试 GitHub
|
||||||
|
ssh -T git@git.shumengya.top -p 8022 # 测试 Gitea
|
||||||
|
```
|
||||||
|
|
||||||
|
### 启动程序
|
||||||
|
|
||||||
|
**Windows**
|
||||||
|
```bash
|
||||||
|
run.bat
|
||||||
|
# 或
|
||||||
python quickgit.py
|
python quickgit.py
|
||||||
|
|
||||||
# 或使用旧版单文件脚本
|
|
||||||
python mengya_git_manager.py
|
|
||||||
```
|
```
|
||||||
|
|
||||||
### 主要功能菜单
|
**Linux / macOS**
|
||||||
|
```bash
|
||||||
```
|
chmod +x run.sh
|
||||||
1. 初始化Git仓库
|
./run.sh
|
||||||
2. 提交并推送更改
|
# 或
|
||||||
3. 从远程仓库拉取
|
python3 quickgit.py
|
||||||
4. 查看仓库状态
|
|
||||||
5. 管理远程仓库
|
|
||||||
6. 退出
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## 使用场景
|
## 5) 交互流程
|
||||||
|
- 启动即要求选择工作目录:支持绝对/相对路径,直接回车使用脚本所在目录,自动校验目录存在。
|
||||||
|
- 主菜单(含永久提示):
|
||||||
|
```
|
||||||
|
[1] 初始化Git仓库
|
||||||
|
[2] 提交更改到本地
|
||||||
|
[3] 推送到远程仓库
|
||||||
|
[4] 从远程仓库拉取
|
||||||
|
[5] 查看仓库状态
|
||||||
|
[6] 管理远程仓库
|
||||||
|
[7] 退出程序
|
||||||
|
[*] 提交代码前建议先拉取最新代码,减少代码冲突
|
||||||
|
[*] 使用SSH进行Git提交更方便快捷和安全
|
||||||
|
```
|
||||||
|
|
||||||
### 场景1:初始化新项目
|
## 6) 常用操作示例
|
||||||
|
|
||||||
1. 在项目目录运行脚本
|
### 场景0: 选择工作目录
|
||||||
2. 选择 `1. 初始化Git仓库`
|
- 启动时输入要管理的仓库路径
|
||||||
3. 按提示配置GitHub或Gitea远程仓库
|
- 支持绝对路径、相对路径、`~` 路径
|
||||||
4. 完成首次提交
|
- 直接回车使用当前目录
|
||||||
|
|
||||||
### 场景2:提交代码更改
|
### 场景1: 初始化新仓库
|
||||||
|
1. 选择 [1] 初始化Git仓库
|
||||||
|
2. 自动创建 `.gitignore`(含前端/后端通用规则)
|
||||||
|
3. 自动创建 `main` 分支并进行首次提交
|
||||||
|
4. 选择 [6] 管理远程仓库 → 添加 GitHub 或 Gitea 远程仓库(**仅 SSH**)
|
||||||
|
|
||||||
1. 修改代码后运行脚本
|
### 场景2: 日常提交工作流
|
||||||
2. 选择 `2. 提交并推送更改`
|
1. 选择 [2] 提交更改到本地
|
||||||
3. 输入提交信息(或使用默认信息)
|
- 查看更改的文件
|
||||||
4. 选择推送到哪个远程仓库
|
- 输入提交信息(留空自动填入时间戳)
|
||||||
|
- 代码提交到本地仓库
|
||||||
|
2. 选择 [3] 推送到远程仓库
|
||||||
|
- 选择远程仓库(可多选)
|
||||||
|
- 通过 SSH 推送到远程
|
||||||
|
|
||||||
### 场景3:拉取远程更新
|
### 场景3: 拉取远程更新
|
||||||
|
1. 选择 [4] 从远程仓库拉取
|
||||||
|
2. 选择远程仓库(单选)
|
||||||
|
3. 通过 SSH 拉取当前分支的更新
|
||||||
|
|
||||||
1. 运行脚本
|
### 场景4: 管理远程仓库
|
||||||
2. 选择 `3. 从远程仓库拉取`
|
|
||||||
3. 选择要拉取的远程仓库
|
|
||||||
|
|
||||||
## 远程仓库配置
|
选择 [6] 管理远程仓库,提供以下功能:
|
||||||
|
|
||||||
### GitHub配置
|
#### 4.1 添加 GitHub 远程仓库
|
||||||
|
SSH 格式:`git@github.com:shumengya/{repo}.git`
|
||||||
|
|
||||||
- 使用SSH方式连接
|
#### 4.2 添加 Gitea 远程仓库
|
||||||
- 格式:`git@github.com:shumengya/{仓库名}.git`
|
SSH 格式:`ssh://git@git.shumengya.top:8022/{user}/{repo}.git`
|
||||||
|
|
||||||
### Gitea配置
|
默认使用配置的 Gitea 服务器地址和端口,可通过"配置 Gitea 服务器"修改。
|
||||||
|
|
||||||
- 服务器地址:`repo.shumengya.top:8022`
|
#### 4.3 添加自建 Git 仓库
|
||||||
- 使用SSH方式连接
|
支持添加自定义 Git 服务器(GitLab、自建 Gitea、Gogs 等):
|
||||||
- 格式:`ssh://git@repo.shumengya.top:8022/{用户名}/{仓库名}.git`
|
1. 输入远程仓库名称(如:`gitlab`、`mygit`)
|
||||||
|
2. 输入完整的 SSH URL
|
||||||
|
3. 支持的 URL 格式示例:
|
||||||
|
- `git@gitlab.com:user/repo.git`
|
||||||
|
- `ssh://git@your-server.com:port/user/repo.git`
|
||||||
|
|
||||||
## .gitignore 支持
|
#### 4.4 配置 Gitea 服务器
|
||||||
|
自定义 Gitea 服务器的主机地址和 SSH 端口:
|
||||||
|
- 默认主机:`git.shumengya.top`
|
||||||
|
- 默认端口:`8022`
|
||||||
|
- 配置保存在:`~/.quickgit_config.json`
|
||||||
|
|
||||||
脚本自动创建的 `.gitignore` 文件支持以下项目类型:
|
#### 4.5 其他功能
|
||||||
|
- **查看所有远程仓库** - 显示已配置的远程仓库列表
|
||||||
|
- **删除远程仓库** - 移除不需要的远程仓库
|
||||||
|
|
||||||
- **Node.js/React** - node_modules/, build/, dist/
|
**⚠️ 注意:** 本工具不支持 HTTPS URL 格式(如 `https://github.com/user/repo.git`),仅支持 SSH 格式。
|
||||||
- **Go** - *.exe, *.test, vendor/
|
|
||||||
- **Python** - __pycache__/, venv/, *.pyc
|
|
||||||
- **通用** - 日志文件、临时文件、IDE配置
|
|
||||||
|
|
||||||
## 系统要求
|
### 场景5: 配置文件
|
||||||
|
|
||||||
- Python 3.6+
|
QuickGit 的配置文件保存在:`~/.quickgit_config.json`
|
||||||
- Git 已安装并配置
|
|
||||||
- SSH密钥已配置(用于远程仓库推送)
|
|
||||||
|
|
||||||
## 注意事项
|
**配置内容:**
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"gitea_host": "git.shumengya.top",
|
||||||
|
"gitea_port": "8022",
|
||||||
|
"github_user": "shumengya",
|
||||||
|
"default_branch": "main"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
1. 首次使用前请确保已配置Git用户信息:
|
**修改方式:**
|
||||||
```bash
|
- 通过菜单:[6] 管理远程仓库 → [5] 配置 Gitea 服务器
|
||||||
git config --global user.name "你的名字"
|
- 或手动编辑配置文件(需重启工具生效)
|
||||||
git config --global user.email "你的邮箱"
|
|
||||||
```
|
|
||||||
|
|
||||||
2. 使用SSH方式连接需要提前配置SSH密钥
|
## 7) 跨平台与终端要求
|
||||||
|
- `run.bat` 自动设置 UTF-8;Windows 使用 `python` 命令。
|
||||||
|
- `run.sh` 设置 `LANG/LC_ALL`,首次需 `chmod +x run.sh`;Linux/macOS 使用 `python3`。
|
||||||
|
- 终端需支持 ANSI 颜色;仅使用 ASCII 符号,避免编码错位。
|
||||||
|
|
||||||
3. 推送到Gitea时请确保仓库已在服务器上创建
|
## 8) 控制台输出规范
|
||||||
|
- 分隔线宽度固定 60:`======` / `------` / `·····`。
|
||||||
|
- 禁止使用 emoji 和 Unicode 盒线字符。
|
||||||
|
- 颜色键值:成功绿、错误红、信息青、警告黄、标题青/品红。
|
||||||
|
- 状态/提示图标:`[√] [×] [i] [!] [>] [*]`。
|
||||||
|
|
||||||
## 常见问题
|
## 9) 手动测试清单
|
||||||
|
- 启动脚本:`run.bat`、`run.sh`、直接运行 `python/ python3 quickgit.py`。
|
||||||
|
- 颜色与中文显示正常,分隔线对齐 60 列。
|
||||||
|
- 初始化仓库、提交+推送、拉取、远程管理均可用。
|
||||||
|
- 默认分支 `main`;`.gitignore` 自动写入成功。
|
||||||
|
|
||||||
**Q: 推送失败怎么办?**
|
## 10) 常见问题 / 故障排查
|
||||||
A: 请检查SSH密钥配置和远程仓库地址是否正确
|
|
||||||
|
|
||||||
**Q: 如何切换远程仓库?**
|
### SSH 相关问题
|
||||||
A: 使用 `5. 管理远程仓库` 功能添加或删除远程仓库
|
- **推送/拉取失败 "Permission denied (publickey)"**:
|
||||||
|
- 确认 SSH 密钥已生成:`ls ~/.ssh/id_*.pub` (Linux/macOS) 或 `dir %USERPROFILE%\.ssh\id_*.pub` (Windows)
|
||||||
|
- 确认公钥已添加到 GitHub/Gitea 账户
|
||||||
|
- 测试 SSH 连接:`ssh -T git@github.com` 或 `ssh -T git@git.shumengya.top -p 8022`
|
||||||
|
|
||||||
**Q: 支持哪些Git操作?**
|
- **"Could not resolve hostname"**:
|
||||||
A: 目前支持init、add、commit、push、pull等常用操作
|
- 检查网络连接
|
||||||
|
- 确认远程仓库地址格式正确(SSH 格式,非 HTTPS)
|
||||||
|
|
||||||
## 模块说明
|
- **端口被防火墙拦截**:
|
||||||
|
- GitHub 使用标准 SSH 端口 22
|
||||||
|
- Gitea 使用自定义端口 8022,确保防火墙允许此端口
|
||||||
|
|
||||||
### config.py - 配置模块
|
### 远程仓库相关
|
||||||
存储所有配置信息,包括Gitea服务器地址、GitHub用户名、.gitignore模板等。
|
- **不支持 HTTPS URL**:本工具仅支持 SSH 方式,如果你的远程仓库使用 HTTPS URL(如 `https://github.com/user/repo.git`),请手动改为 SSH 格式或使用 `git remote` 命令修改。
|
||||||
|
|
||||||
### utils.py - 工具类模块
|
### 终端显示问题
|
||||||
- `Colors`: 控制台颜色定义
|
- **终端乱码**:设置 UTF-8(Windows 可 `chcp 65001`;Linux/macOS 确保 `LANG/LC_ALL` 为 UTF-8)。
|
||||||
- `CommandExecutor`: 命令执行器
|
- **颜色不显示**:使用支持 ANSI 的终端(Windows Terminal/PowerShell 等)。
|
||||||
- `OutputFormatter`: 输出格式化器
|
- **找不到 `python3`**:在 Linux/macOS 安装或创建软链接;Windows 使用 `python`。
|
||||||
- `InputValidator`: 输入验证器
|
|
||||||
|
|
||||||
### git_operations.py - Git操作模块
|
|
||||||
提供Git基本操作功能:
|
|
||||||
- 初始化仓库
|
|
||||||
- 检查状态
|
|
||||||
- 添加/提交更改
|
|
||||||
- 推送/拉取代码
|
|
||||||
|
|
||||||
### remote_manager.py - 远程仓库管理模块
|
|
||||||
管理GitHub和Gitea远程仓库:
|
|
||||||
- 添加/删除远程仓库
|
|
||||||
- 查看远程仓库列表
|
|
||||||
- 选择推送/拉取目标
|
|
||||||
|
|
||||||
### ui.py - UI交互模块
|
|
||||||
处理用户界面和交互逻辑,整合所有功能模块。
|
|
||||||
|
|
||||||
## 开发计划
|
|
||||||
|
|
||||||
|
## 11) 路线图
|
||||||
- [x] 模块化架构重构
|
- [x] 模块化架构重构
|
||||||
- [ ] 支持分支管理
|
- [x] SSH 方式支持(GitHub + Gitea)
|
||||||
- [ ] 支持标签管理
|
- [x] 可配置 Gitea 服务器
|
||||||
- [ ] 支持冲突解决辅助
|
- [x] 自建 Git 仓库支持(GitLab、自建 Gitea 等)
|
||||||
- [ ] 支持自定义配置文件
|
- [x] 配置文件持久化
|
||||||
- [ ] 支持批量操作多个仓库
|
- [ ] HTTPS 方式支持
|
||||||
|
- [ ] 分支管理
|
||||||
|
- [ ] 标签管理
|
||||||
|
- [ ] 冲突解决辅助
|
||||||
|
- [ ] 批量操作多个仓库
|
||||||
|
- [ ] 更多 Git 托管平台支持(Bitbucket 等)
|
||||||
|
|
||||||
## 许可证
|
## 12) 许可证与作者
|
||||||
|
- 许可证:MIT
|
||||||
|
- 作者:shumengya
|
||||||
|
|
||||||
MIT License
|
让 Git 操作更简单,让开发更高效!
|
||||||
|
|
||||||
## 作者
|
|
||||||
|
|
||||||
shumengya
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
**让Git操作更简单,让开发更高效!**
|
|
||||||
|
|||||||
@@ -2,16 +2,99 @@
|
|||||||
配置模块 - 存储项目配置信息
|
配置模块 - 存储项目配置信息
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
import os
|
||||||
|
import json
|
||||||
|
|
||||||
|
|
||||||
class Config:
|
class Config:
|
||||||
"""配置类"""
|
"""配置类"""
|
||||||
|
|
||||||
# Gitea服务器配置
|
# 配置文件路径
|
||||||
GITEA_HOST = "repo.shumengya.top"
|
CONFIG_FILE = os.path.join(os.path.expanduser("~"), ".quickgit_config.json")
|
||||||
GITEA_PORT = "8022"
|
|
||||||
|
|
||||||
# GitHub配置
|
# 默认配置
|
||||||
GITHUB_USER = "shumengya"
|
_defaults = {
|
||||||
|
"gitea_host": "git.shumengya.top",
|
||||||
|
"gitea_port": "8022",
|
||||||
|
"github_user": "shumengya",
|
||||||
|
"default_branch": "main"
|
||||||
|
}
|
||||||
|
|
||||||
|
# 运行时配置(从文件加载或使用默认值)
|
||||||
|
_config = None
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def _load_config(cls):
|
||||||
|
"""加载配置文件"""
|
||||||
|
if cls._config is not None:
|
||||||
|
return
|
||||||
|
|
||||||
|
if os.path.exists(cls.CONFIG_FILE):
|
||||||
|
try:
|
||||||
|
with open(cls.CONFIG_FILE, 'r', encoding='utf-8') as f:
|
||||||
|
cls._config = json.load(f)
|
||||||
|
except Exception:
|
||||||
|
cls._config = cls._defaults.copy()
|
||||||
|
else:
|
||||||
|
cls._config = cls._defaults.copy()
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def _save_config(cls):
|
||||||
|
"""保存配置到文件"""
|
||||||
|
cls._load_config()
|
||||||
|
try:
|
||||||
|
with open(cls.CONFIG_FILE, 'w', encoding='utf-8') as f:
|
||||||
|
json.dump(cls._config, f, indent=2, ensure_ascii=False)
|
||||||
|
return True
|
||||||
|
except Exception:
|
||||||
|
return False
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def get(cls, key: str, default=None):
|
||||||
|
"""获取配置项"""
|
||||||
|
cls._load_config()
|
||||||
|
return cls._config.get(key, default)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def set(cls, key: str, value):
|
||||||
|
"""设置配置项"""
|
||||||
|
cls._load_config()
|
||||||
|
cls._config[key] = value
|
||||||
|
cls._save_config()
|
||||||
|
|
||||||
|
# 属性访问器(保持向后兼容)
|
||||||
|
@property
|
||||||
|
def GITEA_HOST(self) -> str:
|
||||||
|
return self.get("gitea_host", self._defaults["gitea_host"])
|
||||||
|
|
||||||
|
@property
|
||||||
|
def GITEA_PORT(self) -> str:
|
||||||
|
return self.get("gitea_port", self._defaults["gitea_port"])
|
||||||
|
|
||||||
|
@property
|
||||||
|
def GITHUB_USER(self) -> str:
|
||||||
|
return self.get("github_user", self._defaults["github_user"])
|
||||||
|
|
||||||
|
@property
|
||||||
|
def DEFAULT_BRANCH(self) -> str:
|
||||||
|
return self.get("default_branch", self._defaults["default_branch"])
|
||||||
|
|
||||||
|
# 类方法访问器(用于类级别访问)
|
||||||
|
@classmethod
|
||||||
|
def get_gitea_host(cls) -> str:
|
||||||
|
return cls.get("gitea_host", cls._defaults["gitea_host"])
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def get_gitea_port(cls) -> str:
|
||||||
|
return cls.get("gitea_port", cls._defaults["gitea_port"])
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def get_github_user(cls) -> str:
|
||||||
|
return cls.get("github_user", cls._defaults["github_user"])
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def get_default_branch(cls) -> str:
|
||||||
|
return cls.get("default_branch", cls._defaults["default_branch"])
|
||||||
|
|
||||||
# Git配置
|
# Git配置
|
||||||
DEFAULT_BRANCH = "main"
|
DEFAULT_BRANCH = "main"
|
||||||
|
|||||||
@@ -11,13 +11,36 @@ from .config import Config
|
|||||||
class GitOperations:
|
class GitOperations:
|
||||||
"""Git操作类"""
|
"""Git操作类"""
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self, work_dir: str = ""):
|
||||||
|
"""
|
||||||
|
初始化Git操作类
|
||||||
|
|
||||||
|
Args:
|
||||||
|
work_dir: 工作目录(默认为当前目录)
|
||||||
|
"""
|
||||||
self.executor = CommandExecutor()
|
self.executor = CommandExecutor()
|
||||||
self.current_dir = os.getcwd()
|
if work_dir:
|
||||||
|
self.current_dir = work_dir
|
||||||
|
else:
|
||||||
|
self.current_dir = os.getcwd()
|
||||||
|
|
||||||
|
def change_directory(self, new_dir: str):
|
||||||
|
"""
|
||||||
|
切换工作目录
|
||||||
|
|
||||||
|
Args:
|
||||||
|
new_dir: 新的工作目录
|
||||||
|
"""
|
||||||
|
if os.path.isdir(new_dir):
|
||||||
|
self.current_dir = os.path.abspath(new_dir)
|
||||||
|
os.chdir(self.current_dir)
|
||||||
|
else:
|
||||||
|
raise ValueError(f"目录不存在: {new_dir}")
|
||||||
|
|
||||||
def is_git_repo(self) -> bool:
|
def is_git_repo(self) -> bool:
|
||||||
"""检查当前目录是否是Git仓库"""
|
"""检查当前目录是否是Git仓库"""
|
||||||
return os.path.isdir('.git')
|
git_dir = os.path.join(self.current_dir, '.git')
|
||||||
|
return os.path.isdir(git_dir)
|
||||||
|
|
||||||
def init_repo(self) -> bool:
|
def init_repo(self) -> bool:
|
||||||
"""
|
"""
|
||||||
|
|||||||
@@ -46,7 +46,8 @@ class RemoteManager:
|
|||||||
from .utils import Colors
|
from .utils import Colors
|
||||||
repo_name = InputValidator.get_input(f"{Colors.BRIGHT_CYAN}>> 请输入GitHub仓库名: {Colors.ENDC}")
|
repo_name = InputValidator.get_input(f"{Colors.BRIGHT_CYAN}>> 请输入GitHub仓库名: {Colors.ENDC}")
|
||||||
|
|
||||||
remote_url = f"git@github.com:{Config.GITHUB_USER}/{repo_name}.git"
|
github_user = Config.get_github_user()
|
||||||
|
remote_url = f"git@github.com:{github_user}/{repo_name}.git"
|
||||||
|
|
||||||
return self._add_remote("github", remote_url)
|
return self._add_remote("github", remote_url)
|
||||||
|
|
||||||
@@ -68,10 +69,97 @@ class RemoteManager:
|
|||||||
if not repo_name:
|
if not repo_name:
|
||||||
repo_name = InputValidator.get_input(f"{Colors.BRIGHT_CYAN}>> 请输入Gitea仓库名: {Colors.ENDC}")
|
repo_name = InputValidator.get_input(f"{Colors.BRIGHT_CYAN}>> 请输入Gitea仓库名: {Colors.ENDC}")
|
||||||
|
|
||||||
remote_url = f"ssh://git@{Config.GITEA_HOST}:{Config.GITEA_PORT}/{user}/{repo_name}.git"
|
gitea_host = Config.get_gitea_host()
|
||||||
|
gitea_port = Config.get_gitea_port()
|
||||||
|
remote_url = f"ssh://git@{gitea_host}:{gitea_port}/{user}/{repo_name}.git"
|
||||||
|
|
||||||
return self._add_remote("gitea", remote_url)
|
return self._add_remote("gitea", remote_url)
|
||||||
|
|
||||||
|
def add_custom_remote(self) -> bool:
|
||||||
|
"""
|
||||||
|
添加自建Git远程仓库
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
是否成功
|
||||||
|
"""
|
||||||
|
from .utils import Colors
|
||||||
|
|
||||||
|
print(f"\n{Colors.BRIGHT_MAGENTA}>> 添加自建Git仓库{Colors.ENDC}")
|
||||||
|
print(f"{Colors.CYAN}{'-' * 60}{Colors.ENDC}")
|
||||||
|
OutputFormatter.tip("支持 GitLab、自建Gitea、Gogs 等 Git 服务器")
|
||||||
|
OutputFormatter.tip("SSH URL 格式示例:")
|
||||||
|
print(f"{Colors.WHITE} - git@gitlab.com:user/repo.git")
|
||||||
|
print(f"{Colors.WHITE} - ssh://git@your-server.com:port/user/repo.git{Colors.ENDC}")
|
||||||
|
print(f"{Colors.CYAN}{'-' * 60}{Colors.ENDC}")
|
||||||
|
|
||||||
|
# 输入远程仓库名称
|
||||||
|
remote_name = InputValidator.get_input(
|
||||||
|
f"{Colors.BRIGHT_CYAN}>> 请输入远程仓库名称 (如: gitlab, mygit): {Colors.ENDC}"
|
||||||
|
)
|
||||||
|
|
||||||
|
# 检查是否已存在
|
||||||
|
remotes = self.get_remotes()
|
||||||
|
if remote_name in remotes:
|
||||||
|
OutputFormatter.warning(f"远程仓库 '{remote_name}' 已存在")
|
||||||
|
if not InputValidator.confirm("是否覆盖?", default=False):
|
||||||
|
return False
|
||||||
|
self.executor.run(f"git remote remove {remote_name}", show_output=False)
|
||||||
|
|
||||||
|
# 输入SSH URL
|
||||||
|
remote_url = InputValidator.get_input(
|
||||||
|
f"{Colors.BRIGHT_CYAN}>> 请输入完整的SSH URL: {Colors.ENDC}"
|
||||||
|
)
|
||||||
|
|
||||||
|
# 验证URL格式
|
||||||
|
if not (remote_url.startswith("git@") or remote_url.startswith("ssh://")):
|
||||||
|
OutputFormatter.error("无效的SSH URL格式,必须以 'git@' 或 'ssh://' 开头")
|
||||||
|
return False
|
||||||
|
|
||||||
|
return self._add_remote(remote_name, remote_url)
|
||||||
|
|
||||||
|
def configure_gitea_settings(self):
|
||||||
|
"""配置Gitea服务器设置"""
|
||||||
|
from .utils import Colors
|
||||||
|
|
||||||
|
print(f"\n{Colors.BRIGHT_MAGENTA}>> 配置Gitea服务器{Colors.ENDC}")
|
||||||
|
print(f"{Colors.CYAN}{'-' * 60}{Colors.ENDC}")
|
||||||
|
|
||||||
|
# 显示当前配置
|
||||||
|
current_host = Config.get_gitea_host()
|
||||||
|
current_port = Config.get_gitea_port()
|
||||||
|
|
||||||
|
OutputFormatter.info(f"当前配置:")
|
||||||
|
print(f"{Colors.WHITE} 主机: {current_host}{Colors.ENDC}")
|
||||||
|
print(f"{Colors.WHITE} 端口: {current_port}{Colors.ENDC}")
|
||||||
|
print(f"{Colors.CYAN}{'-' * 60}{Colors.ENDC}")
|
||||||
|
|
||||||
|
# 询问是否修改
|
||||||
|
if not InputValidator.confirm("是否修改Gitea服务器配置?", default=False):
|
||||||
|
return
|
||||||
|
|
||||||
|
# 输入新的主机地址
|
||||||
|
new_host = InputValidator.get_input(
|
||||||
|
f"{Colors.BRIGHT_CYAN}>> 请输入Gitea主机地址 (回车保持 {current_host}): {Colors.ENDC}",
|
||||||
|
allow_empty=True
|
||||||
|
)
|
||||||
|
|
||||||
|
if new_host:
|
||||||
|
Config.set("gitea_host", new_host)
|
||||||
|
OutputFormatter.success(f"Gitea主机地址已更新为: {new_host}")
|
||||||
|
|
||||||
|
# 输入新的端口
|
||||||
|
new_port = InputValidator.get_input(
|
||||||
|
f"{Colors.BRIGHT_CYAN}>> 请输入SSH端口 (回车保持 {current_port}): {Colors.ENDC}",
|
||||||
|
allow_empty=True
|
||||||
|
)
|
||||||
|
|
||||||
|
if new_port:
|
||||||
|
Config.set("gitea_port", new_port)
|
||||||
|
OutputFormatter.success(f"Gitea SSH端口已更新为: {new_port}")
|
||||||
|
|
||||||
|
print(f"{Colors.CYAN}{'-' * 60}{Colors.ENDC}")
|
||||||
|
OutputFormatter.tip("配置已保存,下次添加Gitea仓库时将使用新配置")
|
||||||
|
|
||||||
def _add_remote(self, name: str, url: str) -> bool:
|
def _add_remote(self, name: str, url: str) -> bool:
|
||||||
"""
|
"""
|
||||||
添加远程仓库
|
添加远程仓库
|
||||||
@@ -150,7 +238,7 @@ class RemoteManager:
|
|||||||
|
|
||||||
OutputFormatter.menu_item(1, "GitHub")
|
OutputFormatter.menu_item(1, "GitHub")
|
||||||
OutputFormatter.menu_item(2, "Gitea")
|
OutputFormatter.menu_item(2, "Gitea")
|
||||||
OutputFormatter.menu_item(3, "两者都配置")
|
OutputFormatter.menu_item(3, "自建Git仓库")
|
||||||
OutputFormatter.menu_item(4, "跳过")
|
OutputFormatter.menu_item(4, "跳过")
|
||||||
print(f"{Colors.CYAN}{'-' * 60}{Colors.ENDC}")
|
print(f"{Colors.CYAN}{'-' * 60}{Colors.ENDC}")
|
||||||
|
|
||||||
@@ -164,8 +252,7 @@ class RemoteManager:
|
|||||||
elif choice == 2:
|
elif choice == 2:
|
||||||
self.add_gitea_remote()
|
self.add_gitea_remote()
|
||||||
elif choice == 3:
|
elif choice == 3:
|
||||||
self.add_github_remote()
|
self.add_custom_remote()
|
||||||
self.add_gitea_remote()
|
|
||||||
else:
|
else:
|
||||||
OutputFormatter.info("跳过远程仓库配置")
|
OutputFormatter.info("跳过远程仓库配置")
|
||||||
|
|
||||||
|
|||||||
133
quickgit/ui.py
133
quickgit/ui.py
@@ -2,18 +2,71 @@
|
|||||||
UI交互模块 - 处理用户界面和交互逻辑
|
UI交互模块 - 处理用户界面和交互逻辑
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
import os
|
||||||
from .git_operations import GitOperations
|
from .git_operations import GitOperations
|
||||||
from .remote_manager import RemoteManager
|
from .remote_manager import RemoteManager
|
||||||
from .utils import OutputFormatter, InputValidator, Colors
|
from .utils import OutputFormatter, InputValidator, Colors, PlatformUtils
|
||||||
|
|
||||||
|
|
||||||
class GitManagerUI:
|
class GitManagerUI:
|
||||||
"""Git管理器UI"""
|
"""Git管理器UI"""
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self, work_dir: str = ""):
|
||||||
self.git_ops = GitOperations()
|
"""
|
||||||
|
初始化UI
|
||||||
|
|
||||||
|
Args:
|
||||||
|
work_dir: 工作目录(默认为当前目录)
|
||||||
|
"""
|
||||||
|
self.git_ops = GitOperations(work_dir)
|
||||||
self.remote_mgr = RemoteManager()
|
self.remote_mgr = RemoteManager()
|
||||||
|
|
||||||
|
def select_work_directory(self):
|
||||||
|
"""让用户选择工作目录"""
|
||||||
|
from .utils import Colors
|
||||||
|
|
||||||
|
print(f"\n{Colors.BRIGHT_CYAN}{'=' * 60}")
|
||||||
|
print(f"{Colors.BRIGHT_MAGENTA}{Colors.BOLD} QuickGit - 萌芽一键Git管理工具 v1.0{Colors.ENDC}")
|
||||||
|
print(f"{Colors.BRIGHT_CYAN}{'=' * 60}{Colors.ENDC}")
|
||||||
|
|
||||||
|
# 获取当前目录
|
||||||
|
current_dir = os.getcwd()
|
||||||
|
|
||||||
|
# 显示平台信息和路径示例
|
||||||
|
platform = PlatformUtils.get_platform_name()
|
||||||
|
print(f"{Colors.BRIGHT_YELLOW}当前平台:{Colors.ENDC} {Colors.WHITE}{platform}{Colors.ENDC}")
|
||||||
|
print(f"{Colors.BRIGHT_YELLOW}脚本目录:{Colors.ENDC} {Colors.WHITE}{current_dir}{Colors.ENDC}")
|
||||||
|
print(f"{Colors.CYAN}{'-' * 60}{Colors.ENDC}")
|
||||||
|
|
||||||
|
# 显示路径输入提示
|
||||||
|
OutputFormatter.info("请输入要管理的Git仓库目录")
|
||||||
|
|
||||||
|
# 根据平台显示不同的示例
|
||||||
|
if PlatformUtils.is_windows():
|
||||||
|
OutputFormatter.tip("Windows路径示例: C:\\Users\\YourName\\project")
|
||||||
|
OutputFormatter.tip("或使用相对路径: .\\myproject")
|
||||||
|
else:
|
||||||
|
OutputFormatter.tip("Linux/macOS路径示例: /home/yourname/project")
|
||||||
|
OutputFormatter.tip("或使用相对路径: ./myproject 或 ~/project")
|
||||||
|
|
||||||
|
print(f"{Colors.CYAN}{'-' * 60}{Colors.ENDC}")
|
||||||
|
|
||||||
|
# 获取用户输入的目录
|
||||||
|
work_dir = InputValidator.get_directory(
|
||||||
|
f"{Colors.BRIGHT_CYAN}>> 请输入目录路径{Colors.ENDC}",
|
||||||
|
default=current_dir
|
||||||
|
)
|
||||||
|
|
||||||
|
# 切换到工作目录
|
||||||
|
try:
|
||||||
|
self.git_ops.change_directory(work_dir)
|
||||||
|
OutputFormatter.success(f"已切换到工作目录: {work_dir}")
|
||||||
|
except Exception as e:
|
||||||
|
OutputFormatter.error(f"切换目录失败: {str(e)}")
|
||||||
|
return False
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
def show_welcome(self):
|
def show_welcome(self):
|
||||||
"""显示欢迎信息"""
|
"""显示欢迎信息"""
|
||||||
from .utils import Colors
|
from .utils import Colors
|
||||||
@@ -37,11 +90,17 @@ class GitManagerUI:
|
|||||||
print(f"{Colors.CYAN}{'-' * 60}{Colors.ENDC}")
|
print(f"{Colors.CYAN}{'-' * 60}{Colors.ENDC}")
|
||||||
|
|
||||||
OutputFormatter.menu_item(1, "初始化Git仓库")
|
OutputFormatter.menu_item(1, "初始化Git仓库")
|
||||||
OutputFormatter.menu_item(2, "提交并推送更改")
|
OutputFormatter.menu_item(2, "提交更改到本地")
|
||||||
OutputFormatter.menu_item(3, "从远程仓库拉取")
|
OutputFormatter.menu_item(3, "推送到远程仓库")
|
||||||
OutputFormatter.menu_item(4, "查看仓库状态")
|
OutputFormatter.menu_item(4, "从远程仓库拉取")
|
||||||
OutputFormatter.menu_item(5, "管理远程仓库")
|
OutputFormatter.menu_item(5, "查看仓库状态")
|
||||||
OutputFormatter.menu_item(6, "退出程序")
|
OutputFormatter.menu_item(6, "管理远程仓库")
|
||||||
|
OutputFormatter.menu_item(7, "退出程序")
|
||||||
|
print(f"{Colors.CYAN}{'-' * 60}{Colors.ENDC}")
|
||||||
|
|
||||||
|
# 显示永久提示
|
||||||
|
OutputFormatter.tip("提交代码前建议先拉取最新代码,减少代码冲突")
|
||||||
|
OutputFormatter.tip("使用SSH进行Git提交更方便快捷和安全")
|
||||||
print(f"{Colors.CYAN}{'-' * 60}{Colors.ENDC}")
|
print(f"{Colors.CYAN}{'-' * 60}{Colors.ENDC}")
|
||||||
|
|
||||||
def handle_init_repo(self):
|
def handle_init_repo(self):
|
||||||
@@ -52,9 +111,9 @@ class GitManagerUI:
|
|||||||
# 配置远程仓库
|
# 配置远程仓库
|
||||||
self.remote_mgr.configure_remotes_interactive()
|
self.remote_mgr.configure_remotes_interactive()
|
||||||
|
|
||||||
def handle_commit_and_push(self):
|
def handle_commit(self):
|
||||||
"""处理提交并推送"""
|
"""处理提交到本地"""
|
||||||
OutputFormatter.header("提交并推送更改")
|
OutputFormatter.header("提交更改到本地")
|
||||||
|
|
||||||
if not self.git_ops.is_git_repo():
|
if not self.git_ops.is_git_repo():
|
||||||
OutputFormatter.error("当前目录不是Git仓库,请先初始化")
|
OutputFormatter.error("当前目录不是Git仓库,请先初始化")
|
||||||
@@ -86,9 +145,26 @@ class GitManagerUI:
|
|||||||
if not self.git_ops.commit(commit_msg or ""):
|
if not self.git_ops.commit(commit_msg or ""):
|
||||||
return
|
return
|
||||||
|
|
||||||
|
OutputFormatter.tip("提交成功!如需推送到远程仓库,请选择菜单选项3")
|
||||||
|
|
||||||
|
def handle_push(self):
|
||||||
|
"""处理推送到远程"""
|
||||||
|
OutputFormatter.header("推送到远程仓库")
|
||||||
|
|
||||||
|
if not self.git_ops.is_git_repo():
|
||||||
|
OutputFormatter.error("当前目录不是Git仓库,请先初始化")
|
||||||
|
return
|
||||||
|
|
||||||
|
# 检查是否有提交可推送
|
||||||
|
OutputFormatter.status('running', "检查待推送的提交...")
|
||||||
|
|
||||||
# 推送到远程仓库
|
# 推送到远程仓库
|
||||||
selected_remotes = self.remote_mgr.select_remote_for_push()
|
selected_remotes = self.remote_mgr.select_remote_for_push()
|
||||||
|
|
||||||
|
if not selected_remotes:
|
||||||
|
OutputFormatter.warning("未选择远程仓库")
|
||||||
|
return
|
||||||
|
|
||||||
for remote in selected_remotes:
|
for remote in selected_remotes:
|
||||||
self.git_ops.push(remote)
|
self.git_ops.push(remote)
|
||||||
|
|
||||||
@@ -132,13 +208,15 @@ class GitManagerUI:
|
|||||||
OutputFormatter.menu_item(1, "查看远程仓库")
|
OutputFormatter.menu_item(1, "查看远程仓库")
|
||||||
OutputFormatter.menu_item(2, "添加GitHub远程仓库")
|
OutputFormatter.menu_item(2, "添加GitHub远程仓库")
|
||||||
OutputFormatter.menu_item(3, "添加Gitea远程仓库")
|
OutputFormatter.menu_item(3, "添加Gitea远程仓库")
|
||||||
OutputFormatter.menu_item(4, "删除远程仓库")
|
OutputFormatter.menu_item(4, "添加自建Git仓库")
|
||||||
OutputFormatter.menu_item(5, "返回主菜单")
|
OutputFormatter.menu_item(5, "配置Gitea服务器")
|
||||||
|
OutputFormatter.menu_item(6, "删除远程仓库")
|
||||||
|
OutputFormatter.menu_item(7, "返回主菜单")
|
||||||
print(f"{Colors.CYAN}{'-' * 60}{Colors.ENDC}")
|
print(f"{Colors.CYAN}{'-' * 60}{Colors.ENDC}")
|
||||||
|
|
||||||
choice = InputValidator.get_choice(
|
choice = InputValidator.get_choice(
|
||||||
f"{Colors.BRIGHT_CYAN}>> 请选择 [1-5]: {Colors.ENDC}",
|
f"{Colors.BRIGHT_CYAN}>> 请选择 [1-7]: {Colors.ENDC}",
|
||||||
range(1, 6)
|
range(1, 8)
|
||||||
)
|
)
|
||||||
|
|
||||||
if choice == 1:
|
if choice == 1:
|
||||||
@@ -148,33 +226,44 @@ class GitManagerUI:
|
|||||||
elif choice == 3:
|
elif choice == 3:
|
||||||
self.remote_mgr.add_gitea_remote()
|
self.remote_mgr.add_gitea_remote()
|
||||||
elif choice == 4:
|
elif choice == 4:
|
||||||
self.remote_mgr.remove_remote()
|
self.remote_mgr.add_custom_remote()
|
||||||
elif choice == 5:
|
elif choice == 5:
|
||||||
|
self.remote_mgr.configure_gitea_settings()
|
||||||
|
elif choice == 6:
|
||||||
|
self.remote_mgr.remove_remote()
|
||||||
|
elif choice == 7:
|
||||||
break
|
break
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
"""运行主程序"""
|
"""运行主程序"""
|
||||||
|
# 首先选择工作目录
|
||||||
|
if not self.select_work_directory():
|
||||||
|
return
|
||||||
|
|
||||||
|
# 显示欢迎信息
|
||||||
self.show_welcome()
|
self.show_welcome()
|
||||||
|
|
||||||
while True:
|
while True:
|
||||||
self.show_main_menu()
|
self.show_main_menu()
|
||||||
|
|
||||||
choice = InputValidator.get_choice(
|
choice = InputValidator.get_choice(
|
||||||
f"{Colors.BRIGHT_MAGENTA}>> 请输入选项 [1-6]: {Colors.ENDC}",
|
f"{Colors.BRIGHT_MAGENTA}>> 请输入选项 [1-7]: {Colors.ENDC}",
|
||||||
range(1, 7)
|
range(1, 8)
|
||||||
)
|
)
|
||||||
|
|
||||||
if choice == 1:
|
if choice == 1:
|
||||||
self.handle_init_repo()
|
self.handle_init_repo()
|
||||||
elif choice == 2:
|
elif choice == 2:
|
||||||
self.handle_commit_and_push()
|
self.handle_commit()
|
||||||
elif choice == 3:
|
elif choice == 3:
|
||||||
self.handle_pull()
|
self.handle_push()
|
||||||
elif choice == 4:
|
elif choice == 4:
|
||||||
self.handle_show_status()
|
self.handle_pull()
|
||||||
elif choice == 5:
|
elif choice == 5:
|
||||||
self.handle_manage_remotes()
|
self.handle_show_status()
|
||||||
elif choice == 6:
|
elif choice == 6:
|
||||||
|
self.handle_manage_remotes()
|
||||||
|
elif choice == 7:
|
||||||
print(f"\n{Colors.BRIGHT_GREEN}{'=' * 60}")
|
print(f"\n{Colors.BRIGHT_GREEN}{'=' * 60}")
|
||||||
print(f"{Colors.BRIGHT_GREEN}{Colors.BOLD} 感谢使用QuickGit!祝您工作愉快!{Colors.ENDC}")
|
print(f"{Colors.BRIGHT_GREEN}{Colors.BOLD} 感谢使用QuickGit!祝您工作愉快!{Colors.ENDC}")
|
||||||
print(f"{Colors.BRIGHT_GREEN}{'=' * 60}{Colors.ENDC}\n")
|
print(f"{Colors.BRIGHT_GREEN}{'=' * 60}{Colors.ENDC}\n")
|
||||||
|
|||||||
@@ -2,7 +2,9 @@
|
|||||||
工具类模块 - 提供命令执行、输出格式化等工具函数
|
工具类模块 - 提供命令执行、输出格式化等工具函数
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
import os
|
||||||
import subprocess
|
import subprocess
|
||||||
|
import sys
|
||||||
|
|
||||||
|
|
||||||
class Colors:
|
class Colors:
|
||||||
@@ -128,6 +130,11 @@ class OutputFormatter:
|
|||||||
"""打印警告信息"""
|
"""打印警告信息"""
|
||||||
print(f"{Colors.BRIGHT_YELLOW}[!]{Colors.ENDC} {Colors.YELLOW}{text}{Colors.ENDC}")
|
print(f"{Colors.BRIGHT_YELLOW}[!]{Colors.ENDC} {Colors.YELLOW}{text}{Colors.ENDC}")
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def tip(text: str):
|
||||||
|
"""打印提示信息"""
|
||||||
|
print(f"{Colors.BRIGHT_CYAN}[*]{Colors.ENDC} {Colors.CYAN}{text}{Colors.ENDC}")
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def step(num: int, text: str):
|
def step(num: int, text: str):
|
||||||
"""打印步骤信息"""
|
"""打印步骤信息"""
|
||||||
@@ -160,6 +167,83 @@ class OutputFormatter:
|
|||||||
print(f"{icon} {text}")
|
print(f"{icon} {text}")
|
||||||
|
|
||||||
|
|
||||||
|
class PlatformUtils:
|
||||||
|
"""跨平台工具类"""
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def clear_screen():
|
||||||
|
"""清屏 - 跨平台兼容"""
|
||||||
|
# Windows
|
||||||
|
if os.name == 'nt':
|
||||||
|
os.system('cls')
|
||||||
|
# Linux/macOS
|
||||||
|
else:
|
||||||
|
os.system('clear')
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def is_windows() -> bool:
|
||||||
|
"""检查是否为 Windows 系统"""
|
||||||
|
return os.name == 'nt'
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def is_linux() -> bool:
|
||||||
|
"""检查是否为 Linux 系统"""
|
||||||
|
return sys.platform.startswith('linux')
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def is_mac() -> bool:
|
||||||
|
"""检查是否为 macOS 系统"""
|
||||||
|
return sys.platform == 'darwin'
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def get_platform_name() -> str:
|
||||||
|
"""获取平台名称"""
|
||||||
|
if PlatformUtils.is_windows():
|
||||||
|
return "Windows"
|
||||||
|
elif PlatformUtils.is_linux():
|
||||||
|
return "Linux"
|
||||||
|
elif PlatformUtils.is_mac():
|
||||||
|
return "macOS"
|
||||||
|
else:
|
||||||
|
return "Unknown"
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def normalize_path(path: str) -> str:
|
||||||
|
"""
|
||||||
|
标准化路径 - 跨平台兼容
|
||||||
|
|
||||||
|
Args:
|
||||||
|
path: 输入路径
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
标准化后的绝对路径
|
||||||
|
"""
|
||||||
|
# 展开用户目录 (~)
|
||||||
|
path = os.path.expanduser(path)
|
||||||
|
# 转换为绝对路径
|
||||||
|
path = os.path.abspath(path)
|
||||||
|
# 标准化路径分隔符
|
||||||
|
path = os.path.normpath(path)
|
||||||
|
return path
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def is_valid_directory(path: str) -> bool:
|
||||||
|
"""
|
||||||
|
检查路径是否为有效目录
|
||||||
|
|
||||||
|
Args:
|
||||||
|
path: 要检查的路径
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
是否为有效目录
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
normalized_path = PlatformUtils.normalize_path(path)
|
||||||
|
return os.path.isdir(normalized_path)
|
||||||
|
except Exception:
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
class InputValidator:
|
class InputValidator:
|
||||||
"""输入验证器"""
|
"""输入验证器"""
|
||||||
|
|
||||||
@@ -224,3 +308,40 @@ class InputValidator:
|
|||||||
return default
|
return default
|
||||||
|
|
||||||
return user_input in ['y', 'yes']
|
return user_input in ['y', 'yes']
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def get_directory(prompt: str, default: str = "") -> str:
|
||||||
|
"""
|
||||||
|
获取用户输入的目录路径
|
||||||
|
|
||||||
|
Args:
|
||||||
|
prompt: 提示信息
|
||||||
|
default: 默认目录(如果用户直接回车)
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
标准化后的目录路径
|
||||||
|
"""
|
||||||
|
while True:
|
||||||
|
# 显示提示
|
||||||
|
if default:
|
||||||
|
user_input = input(f"{prompt} (回车使用当前目录: {default}): ").strip()
|
||||||
|
else:
|
||||||
|
user_input = input(f"{prompt}: ").strip()
|
||||||
|
|
||||||
|
# 如果为空,使用默认值
|
||||||
|
if not user_input:
|
||||||
|
if default:
|
||||||
|
return PlatformUtils.normalize_path(default)
|
||||||
|
else:
|
||||||
|
OutputFormatter.error("目录路径不能为空")
|
||||||
|
continue
|
||||||
|
|
||||||
|
# 标准化路径
|
||||||
|
normalized_path = PlatformUtils.normalize_path(user_input)
|
||||||
|
|
||||||
|
# 检查目录是否存在
|
||||||
|
if PlatformUtils.is_valid_directory(normalized_path):
|
||||||
|
return normalized_path
|
||||||
|
else:
|
||||||
|
OutputFormatter.error(f"目录不存在: {normalized_path}")
|
||||||
|
OutputFormatter.info("请输入有效的目录路径")
|
||||||
|
|||||||
9
run.sh
Normal file
9
run.sh
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# QuickGit 启动脚本 (Linux/macOS)
|
||||||
|
|
||||||
|
# 设置 UTF-8 编码
|
||||||
|
export LANG=zh_CN.UTF-8
|
||||||
|
export LC_ALL=zh_CN.UTF-8
|
||||||
|
|
||||||
|
# 运行程序
|
||||||
|
python3 quickgit.py
|
||||||
75
使用说明.md
75
使用说明.md
@@ -1,5 +1,25 @@
|
|||||||
# QuickGit 使用说明
|
# QuickGit 使用说明
|
||||||
|
|
||||||
|
**⚠️ 重要提示:本工具仅支持通过 SSH 方式连接 GitHub 和 Gitea 远程仓库,不支持 HTTPS。**
|
||||||
|
|
||||||
|
## 前置要求
|
||||||
|
|
||||||
|
### 必需配置 SSH 密钥
|
||||||
|
1. 生成 SSH 密钥:
|
||||||
|
```bash
|
||||||
|
ssh-keygen -t ed25519 -C "your_email@example.com"
|
||||||
|
```
|
||||||
|
|
||||||
|
2. 将公钥添加到 GitHub/Gitea:
|
||||||
|
- GitHub: Settings → SSH and GPG keys → New SSH key
|
||||||
|
- Gitea: 设置 → SSH/GPG 密钥 → 添加密钥
|
||||||
|
|
||||||
|
3. 测试连接:
|
||||||
|
```bash
|
||||||
|
ssh -T git@github.com
|
||||||
|
ssh -T git@git.shumengya.top -p 8022
|
||||||
|
```
|
||||||
|
|
||||||
## 已修复的问题
|
## 已修复的问题
|
||||||
|
|
||||||
### 1. 添加文件失败问题
|
### 1. 添加文件失败问题
|
||||||
@@ -54,22 +74,59 @@ Git状态: [已初始化]
|
|||||||
>> 主菜单
|
>> 主菜单
|
||||||
------------------------------------------------------------
|
------------------------------------------------------------
|
||||||
[1] 初始化Git仓库
|
[1] 初始化Git仓库
|
||||||
[2] 提交并推送更改
|
[2] 提交更改到本地
|
||||||
[3] 从远程仓库拉取
|
[3] 推送到远程仓库
|
||||||
[4] 查看仓库状态
|
[4] 从远程仓库拉取
|
||||||
[5] 管理远程仓库
|
[5] 查看仓库状态
|
||||||
[6] 退出程序
|
[6] 管理远程仓库
|
||||||
|
[7] 退出程序
|
||||||
------------------------------------------------------------
|
------------------------------------------------------------
|
||||||
>> 请输入选项 [1-6]:
|
[*] 提交代码前建议先拉取最新代码,减少代码冲突
|
||||||
|
[*] 使用SSH进行Git提交更方便快捷和安全
|
||||||
|
------------------------------------------------------------
|
||||||
|
>> 请输入选项 [1-7]:
|
||||||
```
|
```
|
||||||
|
|
||||||
## 功能说明
|
## 功能说明
|
||||||
|
|
||||||
所有功能均正常工作:
|
所有功能均正常工作:
|
||||||
- ✓ 初始化Git仓库
|
- ✓ 初始化Git仓库
|
||||||
- ✓ 提交并推送更改
|
- ✓ 提交更改到本地(不推送)
|
||||||
- ✓ 从远程仓库拉取
|
- ✓ 推送到远程仓库(通过 SSH)
|
||||||
|
- ✓ 从远程仓库拉取(通过 SSH)
|
||||||
- ✓ 查看仓库状态
|
- ✓ 查看仓库状态
|
||||||
- ✓ 管理远程仓库(GitHub/Gitea)
|
- ✓ 管理远程仓库(GitHub/Gitea/自建 Git,仅 SSH)
|
||||||
|
- ✓ 配置 Gitea 服务器(自定义主机和端口)
|
||||||
|
- ✓ 添加自建 Git 仓库(GitLab、自建 Gitea、Gogs 等)
|
||||||
|
|
||||||
|
### 远程仓库管理菜单
|
||||||
|
```
|
||||||
|
[1] 查看远程仓库
|
||||||
|
[2] 添加GitHub远程仓库
|
||||||
|
[3] 添加Gitea远程仓库
|
||||||
|
[4] 添加自建Git仓库 ← 新功能
|
||||||
|
[5] 配置Gitea服务器 ← 新功能
|
||||||
|
[6] 删除远程仓库
|
||||||
|
[7] 返回主菜单
|
||||||
|
```
|
||||||
|
|
||||||
|
### 远程仓库 URL 格式
|
||||||
|
- **GitHub**: `git@github.com:shumengya/{repo}.git`
|
||||||
|
- **Gitea**: `ssh://git@git.shumengya.top:8022/{user}/{repo}.git`
|
||||||
|
- 主机和端口可通过菜单配置
|
||||||
|
- **自建 Git**: 支持自定义 SSH URL
|
||||||
|
- GitLab: `git@gitlab.com:user/repo.git`
|
||||||
|
- 自建服务器: `ssh://git@your-server.com:port/user/repo.git`
|
||||||
|
|
||||||
|
**注意**:不支持 HTTPS URL 格式(如 `https://github.com/user/repo.git`)
|
||||||
|
|
||||||
|
### 配置文件
|
||||||
|
配置保存在:`~/.quickgit_config.json`
|
||||||
|
|
||||||
|
可配置项:
|
||||||
|
- Gitea 主机地址
|
||||||
|
- Gitea SSH 端口
|
||||||
|
- GitHub 用户名
|
||||||
|
- 默认分支名
|
||||||
|
|
||||||
界面美观、对齐完美、功能稳定!
|
界面美观、对齐完美、功能稳定!
|
||||||
|
|||||||
164
菜单提示说明.md
Normal file
164
菜单提示说明.md
Normal file
@@ -0,0 +1,164 @@
|
|||||||
|
# QuickGit 主菜单提示功能
|
||||||
|
|
||||||
|
## 功能说明
|
||||||
|
|
||||||
|
在主菜单下方添加了两条永久提示,帮助用户养成良好的 Git 使用习惯。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 显示效果
|
||||||
|
|
||||||
|
```
|
||||||
|
============================================================
|
||||||
|
>> 主菜单
|
||||||
|
------------------------------------------------------------
|
||||||
|
[1] 初始化Git仓库
|
||||||
|
[2] 提交并推送更改
|
||||||
|
[3] 从远程仓库拉取
|
||||||
|
[4] 查看仓库状态
|
||||||
|
[5] 管理远程仓库
|
||||||
|
[6] 退出程序
|
||||||
|
------------------------------------------------------------
|
||||||
|
[*] 提交代码前建议先拉取最新代码,减少代码冲突
|
||||||
|
[*] 使用SSH进行Git提交更方便快捷和安全
|
||||||
|
------------------------------------------------------------
|
||||||
|
>> 请输入选项 [1-6]:
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 提示内容
|
||||||
|
|
||||||
|
### 提示 1: 先拉取再提交
|
||||||
|
```
|
||||||
|
[*] 提交代码前建议先拉取最新代码,减少代码冲突
|
||||||
|
```
|
||||||
|
|
||||||
|
**目的:**
|
||||||
|
- 避免代码冲突
|
||||||
|
- 养成良好的协作习惯
|
||||||
|
- 减少合并错误
|
||||||
|
|
||||||
|
**最佳实践流程:**
|
||||||
|
1. 先执行 `[3] 从远程仓库拉取`
|
||||||
|
2. 解决可能的冲突
|
||||||
|
3. 再执行 `[2] 提交并推送更改`
|
||||||
|
|
||||||
|
### 提示 2: 使用 SSH
|
||||||
|
```
|
||||||
|
[*] 使用SSH进行Git提交更方便快捷和安全
|
||||||
|
```
|
||||||
|
|
||||||
|
**优势:**
|
||||||
|
- **更安全**: 使用公钥加密,不需要每次输入密码
|
||||||
|
- **更快捷**: 配置一次,永久使用
|
||||||
|
- **更方便**: 无需记住密码,自动认证
|
||||||
|
|
||||||
|
**SSH 配置步骤:**
|
||||||
|
|
||||||
|
1. **生成 SSH 密钥:**
|
||||||
|
```bash
|
||||||
|
ssh-keygen -t ed25519 -C "your_email@example.com"
|
||||||
|
```
|
||||||
|
|
||||||
|
2. **查看公钥:**
|
||||||
|
```bash
|
||||||
|
# Linux/macOS
|
||||||
|
cat ~/.ssh/id_ed25519.pub
|
||||||
|
|
||||||
|
# Windows
|
||||||
|
type %USERPROFILE%\.ssh\id_ed25519.pub
|
||||||
|
```
|
||||||
|
|
||||||
|
3. **添加公钥到远程仓库:**
|
||||||
|
- GitHub: Settings → SSH and GPG keys → New SSH key
|
||||||
|
- Gitea: Settings → SSH/GPG Keys → Add Key
|
||||||
|
|
||||||
|
4. **测试连接:**
|
||||||
|
```bash
|
||||||
|
# GitHub
|
||||||
|
ssh -T git@github.com
|
||||||
|
|
||||||
|
# Gitea
|
||||||
|
ssh -T git@git.shumengya.top -p 8022
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 设计原则
|
||||||
|
|
||||||
|
### 1. 醒目但不干扰
|
||||||
|
- 使用青色 `[*]` 图标
|
||||||
|
- 位置在菜单选项之后
|
||||||
|
- 不影响菜单选择
|
||||||
|
|
||||||
|
### 2. 简洁明了
|
||||||
|
- 每条提示不超过 30 个字符
|
||||||
|
- 直接说明要点
|
||||||
|
- 易于理解
|
||||||
|
|
||||||
|
### 3. 实用性强
|
||||||
|
- 针对常见问题
|
||||||
|
- 提供最佳实践
|
||||||
|
- 帮助用户避免错误
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 技术实现
|
||||||
|
|
||||||
|
### 代码位置
|
||||||
|
文件: `quickgit/ui.py`
|
||||||
|
|
||||||
|
### 实现代码
|
||||||
|
```python
|
||||||
|
def show_main_menu(self):
|
||||||
|
"""显示主菜单"""
|
||||||
|
print(f"\n{Colors.BRIGHT_MAGENTA}{Colors.BOLD}>> 主菜单{Colors.ENDC}")
|
||||||
|
print(f"{Colors.CYAN}{'-' * 60}{Colors.ENDC}")
|
||||||
|
|
||||||
|
OutputFormatter.menu_item(1, "初始化Git仓库")
|
||||||
|
OutputFormatter.menu_item(2, "提交并推送更改")
|
||||||
|
OutputFormatter.menu_item(3, "从远程仓库拉取")
|
||||||
|
OutputFormatter.menu_item(4, "查看仓库状态")
|
||||||
|
OutputFormatter.menu_item(5, "管理远程仓库")
|
||||||
|
OutputFormatter.menu_item(6, "退出程序")
|
||||||
|
print(f"{Colors.CYAN}{'-' * 60}{Colors.ENDC}")
|
||||||
|
|
||||||
|
# 显示永久提示
|
||||||
|
OutputFormatter.tip("提交代码前建议先拉取最新代码,减少代码冲突")
|
||||||
|
OutputFormatter.tip("使用SSH进行Git提交更方便快捷和安全")
|
||||||
|
print(f"{Colors.CYAN}{'-' * 60}{Colors.ENDC}")
|
||||||
|
```
|
||||||
|
|
||||||
|
### 使用的函数
|
||||||
|
```python
|
||||||
|
# 定义在 quickgit/utils.py
|
||||||
|
OutputFormatter.tip(text: str)
|
||||||
|
# 显示格式: [*] + 青色文字
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 用户反馈
|
||||||
|
|
||||||
|
这些提示将帮助用户:
|
||||||
|
- ✅ 减少代码冲突
|
||||||
|
- ✅ 了解 SSH 的优势
|
||||||
|
- ✅ 养成良好的 Git 工作流程
|
||||||
|
- ✅ 提高工作效率
|
||||||
|
- ✅ 增强代码安全性
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 未来扩展
|
||||||
|
|
||||||
|
可以考虑添加更多实用提示:
|
||||||
|
- Git 分支管理建议
|
||||||
|
- .gitignore 配置提示
|
||||||
|
- 提交信息规范建议
|
||||||
|
- 标签使用说明
|
||||||
|
|
||||||
|
但要注意:
|
||||||
|
- 提示数量不宜过多(建议不超过 3 条)
|
||||||
|
- 内容要简洁实用
|
||||||
|
- 避免信息过载
|
||||||
150
跨平台说明.md
Normal file
150
跨平台说明.md
Normal file
@@ -0,0 +1,150 @@
|
|||||||
|
# 跨平台兼容性说明
|
||||||
|
|
||||||
|
QuickGit 现已完全支持 **Windows**、**Linux** 和 **macOS** 三大平台!
|
||||||
|
|
||||||
|
## 快速开始
|
||||||
|
|
||||||
|
### Windows
|
||||||
|
```bash
|
||||||
|
# 方式1:使用启动脚本(推荐)
|
||||||
|
run.bat
|
||||||
|
|
||||||
|
# 方式2:直接运行
|
||||||
|
python quickgit.py
|
||||||
|
```
|
||||||
|
|
||||||
|
### Linux/macOS
|
||||||
|
```bash
|
||||||
|
# 首次使用:添加执行权限
|
||||||
|
chmod +x run.sh
|
||||||
|
|
||||||
|
# 方式1:使用启动脚本(推荐)
|
||||||
|
./run.sh
|
||||||
|
|
||||||
|
# 方式2:直接运行
|
||||||
|
python3 quickgit.py
|
||||||
|
```
|
||||||
|
|
||||||
|
## 平台特定功能
|
||||||
|
|
||||||
|
### 自动编码配置
|
||||||
|
- **Windows:** `run.bat` 自动设置 UTF-8 编码 (`chcp 65001`)
|
||||||
|
- **Linux/macOS:** `run.sh` 设置 `LANG` 和 `LC_ALL` 环境变量
|
||||||
|
|
||||||
|
### 跨平台工具类 (PlatformUtils)
|
||||||
|
|
||||||
|
新增 `PlatformUtils` 类提供跨平台支持:
|
||||||
|
|
||||||
|
```python
|
||||||
|
from quickgit.utils import PlatformUtils
|
||||||
|
|
||||||
|
# 清屏(自动适配平台)
|
||||||
|
PlatformUtils.clear_screen()
|
||||||
|
|
||||||
|
# 平台检测
|
||||||
|
if PlatformUtils.is_windows():
|
||||||
|
print("Running on Windows")
|
||||||
|
elif PlatformUtils.is_linux():
|
||||||
|
print("Running on Linux")
|
||||||
|
elif PlatformUtils.is_mac():
|
||||||
|
print("Running on macOS")
|
||||||
|
|
||||||
|
# 获取平台名称
|
||||||
|
platform = PlatformUtils.get_platform_name() # "Windows", "Linux", "macOS"
|
||||||
|
```
|
||||||
|
|
||||||
|
## 测试清单
|
||||||
|
|
||||||
|
在 Linux/macOS 上测试时,请验证以下功能:
|
||||||
|
|
||||||
|
- [ ] 启动脚本 `./run.sh` 正常运行
|
||||||
|
- [ ] 彩色输出正确显示
|
||||||
|
- [ ] 中文字符正常显示(UTF-8编码)
|
||||||
|
- [ ] Git 初始化功能正常
|
||||||
|
- [ ] Git 提交推送功能正常
|
||||||
|
- [ ] Git 拉取功能正常
|
||||||
|
- [ ] 远程仓库管理功能正常
|
||||||
|
- [ ] 所有 ASCII 边框对齐(60字符宽)
|
||||||
|
- [ ] 状态指示器 `[√]`, `[×]`, `[i]`, `[!]`, `[>]` 正常显示
|
||||||
|
|
||||||
|
## 已验证的兼容性
|
||||||
|
|
||||||
|
### Python 版本
|
||||||
|
- ✅ Python 3.6+
|
||||||
|
- ✅ Python 3.10+ (type hints: `list[str]`, `tuple[bool, str]`)
|
||||||
|
|
||||||
|
### 操作系统
|
||||||
|
- ✅ Windows 10/11
|
||||||
|
- ✅ Linux (Ubuntu, Debian, Fedora, Arch, etc.)
|
||||||
|
- ✅ macOS 10.15+
|
||||||
|
|
||||||
|
### 终端
|
||||||
|
- ✅ Windows Terminal
|
||||||
|
- ✅ PowerShell
|
||||||
|
- ✅ CMD (Windows 10+)
|
||||||
|
- ✅ Bash
|
||||||
|
- ✅ Zsh
|
||||||
|
- ✅ Fish
|
||||||
|
|
||||||
|
## 注意事项
|
||||||
|
|
||||||
|
1. **Python 命令差异:**
|
||||||
|
- Windows: `python`
|
||||||
|
- Linux/macOS: `python3`
|
||||||
|
|
||||||
|
2. **脚本权限:**
|
||||||
|
- Linux/macOS 首次使用需要: `chmod +x run.sh`
|
||||||
|
|
||||||
|
3. **编码要求:**
|
||||||
|
- 终端必须支持 UTF-8 编码
|
||||||
|
- 使用启动脚本可自动配置
|
||||||
|
|
||||||
|
4. **颜色支持:**
|
||||||
|
- 现代终端均支持 ANSI 颜色代码
|
||||||
|
- Windows 10+ 原生支持
|
||||||
|
- 旧版 Windows 可能需要启用虚拟终端
|
||||||
|
|
||||||
|
## 故障排查
|
||||||
|
|
||||||
|
### 问题:中文乱码
|
||||||
|
**解决:**
|
||||||
|
```bash
|
||||||
|
# Linux/macOS
|
||||||
|
export LANG=zh_CN.UTF-8
|
||||||
|
export LC_ALL=zh_CN.UTF-8
|
||||||
|
|
||||||
|
# Windows
|
||||||
|
chcp 65001
|
||||||
|
```
|
||||||
|
|
||||||
|
### 问题:颜色不显示
|
||||||
|
**检查:**
|
||||||
|
- 终端是否支持 ANSI 颜色
|
||||||
|
- Windows: 使用 Windows Terminal 或 PowerShell
|
||||||
|
|
||||||
|
### 问题:run.sh 没有执行权限
|
||||||
|
**解决:**
|
||||||
|
```bash
|
||||||
|
chmod +x run.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
### 问题:python3 命令不存在
|
||||||
|
**解决:**
|
||||||
|
```bash
|
||||||
|
# 创建软链接
|
||||||
|
sudo ln -s /usr/bin/python3 /usr/bin/python
|
||||||
|
|
||||||
|
# 或安装 Python 3
|
||||||
|
# Ubuntu/Debian:
|
||||||
|
sudo apt install python3
|
||||||
|
|
||||||
|
# Fedora:
|
||||||
|
sudo dnf install python3
|
||||||
|
|
||||||
|
# macOS (使用 Homebrew):
|
||||||
|
brew install python3
|
||||||
|
```
|
||||||
|
|
||||||
|
## 贡献
|
||||||
|
|
||||||
|
如果您在特定平台上发现兼容性问题,欢迎提交 Issue 或 Pull Request!
|
||||||
Reference in New Issue
Block a user