├── .auto_script └── del_old_files.py ├── .github ├── CODEOWNERS ├── ISSUE_TEMPLATE │ ├── bug_feedback.yml │ ├── config.yml │ ├── feature_request.yml │ └── new_command_request.yml ├── PULL_REQUEST_TEMPLATE.md └── dependabot.yml ├── .gitignore ├── ABOUT_TRANSLATION.md ├── AutoPack ├── AutoPack.py ├── packinit.iss └── requirements.txt ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── README_DEV.md ├── USER_HANDBOOK.md ├── config.json ├── docs └── image │ └── README │ └── 1718315176839.png ├── ico.ico ├── requirements.txt ├── zh-tw ├── 中文git-pack.py └── 中文git.py ├── 中文git-pack.py ├── 中文git.exe ├── 中文git.py ├── 中文git更新程序.exe └── 中文git更新程序.py /.auto_script/del_old_files.py: -------------------------------------------------------------------------------- 1 | import os 2 | import sys 3 | import platform 4 | 5 | system = platform.system() 6 | print(f'[WARN] Test flag: System is {system}') 7 | if system == 'Darwin': 8 | # macOS 系统文件名 9 | main_exe = '中文git_macos' 10 | update_exe = '中文git更新程序_macos' 11 | elif system == 'Linux': 12 | # Linux 系统文件名 13 | main_exe = '中文git_linux' 14 | update_exe = '中文git更新程序_linux' 15 | elif system == 'Windows': 16 | # Windows 系统文件名 17 | main_exe = '中文git_windows.exe' 18 | update_exe = '中文git更新程序_windows.exe' 19 | else: 20 | raise NotImplementedError(f"[ERROR] 未知的操作系统: {system}") 21 | 22 | script_path = os.path.dirname(sys.argv[0]) 23 | 24 | try: 25 | os.remove(os.path.join(os.path.dirname(script_path), main_exe)) 26 | os.remove(os.path.join(os.path.dirname(script_path), update_exe)) 27 | except FileNotFoundError: 28 | if system == 'Windows': 29 | print("[WARN] No file need to del.") 30 | else: 31 | print("[WARN] 没有需要删除的旧文件") 32 | sys.exit(0) 33 | except Exception as e: 34 | if system == 'Windows': 35 | print(f"[ERROR] Failed to del file(s): {e}") 36 | else: 37 | print(f"[ERROR] 删除文件时出错: {e}") 38 | sys.exit(1) 39 | 40 | if system == 'Windows': 41 | print("[INFO] Successfully del old file(s).") 42 | else: 43 | print("[INFO] 旧文件删除完成!") 44 | -------------------------------------------------------------------------------- /.github/CODEOWNERS: -------------------------------------------------------------------------------- 1 | # 在这里的文件需要特定人员的批准 2 | 3 | # 对于任何操作都必须由代码所有者审查批准 4 | .github/** @DuckDuckStudio 5 | 6 | # 对于以下内容,需要代码所有者 *仔细* 审查 7 | LICENSE @DuckDuckStudio 8 | CONTRIBUTING.md @DuckDuckStudio 9 | ico.ico @DuckDuckStudio 10 | 11 | # 对于以下内容,需要Duck Studio中的人员审查 12 | AutoPack/** @DuckDuckStudio @Luna-Grace 13 | .gitignore @DuckDuckStudio @Luna-Grace @fjwxzde 14 | 中文git.exe @DuckDuckStudio @Luna-Grace @fjwxzde 15 | 中文git更新程序.exe @DuckDuckStudio @Luna-Grace @fjwxzde 16 | 17 | # 对于以下内容,需要代码所有者审查,但不一定需要 *仔细* 18 | docs/** @DuckDuckStudio @Luna-Grace 19 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_feedback.yml: -------------------------------------------------------------------------------- 1 | name: '🐛 BUG反馈' 2 | description: 向我们反馈你遇到的错误 3 | title: "[BUG]: " 4 | labels: ["bug", "DEV-需要注意", "DEV-未经测试"] 5 | body: 6 | - type: checkboxes 7 | attributes: 8 | label: 在继续之前,请确认以下内容 9 | description: 在发布您的问题之前,请确认以下内容。 10 | options: 11 | - label: 我已经搜索过已存在的问题,并没有存在相同的正在进行中/重复/已解决的问题 12 | required: true 13 | - label: 如果该问题在预览版中被解决,我没有被告知 14 | required: true 15 | - type: dropdown 16 | attributes: 17 | label: 选择一个问题类别 18 | description: 你遇到了什么样的问题? 19 | options: 20 | - 安装问题 21 | - 依赖问题 22 | - 更新问题 23 | - 使用问题 24 | - winget相关问题 25 | - 其他 26 | validations: 27 | required: true 28 | - type: textarea 29 | attributes: 30 | label: 描述你遇到的问题 31 | placeholder: 请在此简要描述您的问题 32 | validations: 33 | required: true 34 | - type: textarea 35 | attributes: 36 | label: 描述如何重现你遇到的问题 37 | placeholder: 如何重现该问题?(填写此字段对问题调查很有帮助!) 38 | validations: 39 | required: true 40 | - type: textarea 41 | attributes: 42 | label: 实际行为 43 | placeholder: 你遇到的情况是什么样的 44 | validations: 45 | required: true 46 | - type: textarea 47 | attributes: 48 | label: 预期行为 49 | placeholder: 正常情况下应该是什么样的 50 | validations: 51 | required: true 52 | - type: textarea 53 | attributes: 54 | label: 版本信息 55 | description: 请将你运行 `中文git 版本` 后的输出粘贴到这里 56 | placeholder: | 57 | [中文git 版本] 58 | 中文Git by 鸭鸭「カモ」 59 | 版本: 60 | 安装在: 61 | git version 62 | 63 | render: raw 64 | validations: 65 | required: true 66 | - type: textarea 67 | attributes: 68 | label: 屏幕截图或日志 (可选) 69 | description: 请上传你记录的日志/屏幕截图,因为它们将帮助我们找到问题的根本原因。你可以使用`Start-Transcript -Path output.log`来记录在PowerShell中的情况。 70 | validations: 71 | required: false 72 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/config.yml: -------------------------------------------------------------------------------- 1 | blank_issues_enabled: true 2 | contact_links: 3 | - name: 询问问题 4 | url: https://github.com/DuckDuckStudio/Chinese_git/discussions/new 5 | about: 你对某事感到疑惑?发起一个新的讨论以向社区寻求答案。 6 | - name: 查看已经打开的问题 7 | url: https://github.com/DuckDuckStudio/Chinese_git/issues 8 | about: 请确认你的问题没有与已存在的问题重复。 9 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.yml: -------------------------------------------------------------------------------- 1 | name: "🚀 新功能请求 / 想法" 2 | title: "[Feat]: " 3 | description: 提出新功能或改进建议 (这并不意味着你必须实现它)。 4 | labels: ["新功能","DEV-需要注意"] 5 | body: 6 | - type: markdown 7 | attributes: 8 | value: | 9 | 感谢您抽出时间与我们讨论新功能的想法! 10 | - type: textarea 11 | attributes: 12 | label: 对新功能/建议的描述 13 | placeholder: 告诉我们你想实现什么。 14 | validations: 15 | required: true 16 | - type: textarea 17 | attributes: 18 | label: 为什么需要实现此功能 19 | placeholder: 告诉我们为什么需要这个功能?能带来什么好处? 20 | validations: 21 | required: true 22 | - type: textarea 23 | attributes: 24 | label: 对于实施该功能的方法的建议 (可选) 25 | placeholder: 建议我们如何实现这一点 (建议填写此字段,这对实施很有帮助!) 26 | validations: 27 | required: false 28 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/new_command_request.yml: -------------------------------------------------------------------------------- 1 | name: "➕ 新命令请求" 2 | description: 建议支持某个Git命令 (这并不意味这你需要实现它) 3 | labels: ["DEV-需要注意", "新功能", "缺少"] 4 | title: "[Feat(新命令)]: " 5 | body: 6 | - type: checkboxes 7 | attributes: 8 | label: 在继续之前,请确认以下内容 9 | description: 在发布您的Issue之前,请确认以下内容。 10 | options: 11 | - label: 我已经搜索过已存在的Issue,并没有存在相同的正在进行中/重复/已解决的Issue 12 | required: true 13 | - label: 如果该命令在预览版中实现,我没有被告知 14 | required: true 15 | - label: 该命令是Git原有的命令,不用额外依赖 (我们不接受非Git原有的命令) 16 | required: true 17 | - type: dropdown 18 | attributes: 19 | label: 选择一个命令类别 20 | description: 是Git的命令还是中文Git的命令? 21 | options: 22 | - 请求支持新的Git命令 23 | - 请求新的中文Git命令 24 | validations: 25 | required: true 26 | - type: textarea 27 | attributes: 28 | label: 你需要添加什么命令 29 | placeholder: 请在这里填写你需要添加的命令 30 | validations: 31 | required: true 32 | - type: textarea 33 | attributes: 34 | label: 你需要添加的命令是做什么用的 35 | placeholder: 请在这里描述你需要添加的命令的作用 36 | validations: 37 | required: true 38 | - type: textarea 39 | attributes: 40 | label: 对于实施该功能的方法的建议 (可选) 41 | placeholder: 建议我们如何实现这一点 (建议填写此字段,这对实施很有帮助!) 42 | validations: 43 | required: false 44 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | ### 检查清单 2 | - [ ] 有链接Issue吗? -- Resolve 3 | - [ ] 你检查过没有其他重复的 [拉取请求](https://github.com/DuckDuckStudio/Chinese_git/pulls) 吗? 4 | - [ ] 此拉取请求仅针对一个问题/功能吗? 5 | - [ ] 你在本地验证过你的修改吗? 6 | - [ ] 你确定你的描述足以让开发人员理解你的意图以及解决方案? 7 | 8 | ### 修改说明 9 | 10 | 11 | 12 | --- 13 | 14 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | # To get started with Dependabot version updates, you'll need to specify which 2 | # package ecosystems to update and where the package manifests are located. 3 | # Please see the documentation for all configuration options: 4 | # https://docs.github.com/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file 5 | 6 | version: 2 7 | updates: 8 | - package-ecosystem: "pip" # See documentation for possible values 9 | directory: "/" # Location of package manifests 10 | schedule: 11 | interval: "daily" 12 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | build/ 12 | develop-eggs/ 13 | dist/ 14 | downloads/ 15 | eggs/ 16 | .eggs/ 17 | lib/ 18 | lib64/ 19 | parts/ 20 | sdist/ 21 | var/ 22 | wheels/ 23 | share/python-wheels/ 24 | *.egg-info/ 25 | .installed.cfg 26 | *.egg 27 | MANIFEST 28 | 29 | # PyInstaller 30 | # Usually these files are written by a python script from a template 31 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 32 | *.manifest 33 | *.spec 34 | 35 | # Installer logs 36 | pip-log.txt 37 | pip-delete-this-directory.txt 38 | 39 | # Unit test / coverage reports 40 | htmlcov/ 41 | .tox/ 42 | .nox/ 43 | .coverage 44 | .coverage.* 45 | .cache 46 | nosetests.xml 47 | coverage.xml 48 | *.cover 49 | *.py,cover 50 | .hypothesis/ 51 | .pytest_cache/ 52 | cover/ 53 | 54 | # Translations 55 | *.mo 56 | *.pot 57 | 58 | # Django stuff: 59 | *.log 60 | local_settings.py 61 | db.sqlite3 62 | db.sqlite3-journal 63 | 64 | # Flask stuff: 65 | instance/ 66 | .webassets-cache 67 | 68 | # Scrapy stuff: 69 | .scrapy 70 | 71 | # Sphinx documentation 72 | docs/_build/ 73 | 74 | # PyBuilder 75 | .pybuilder/ 76 | target/ 77 | 78 | # Jupyter Notebook 79 | .ipynb_checkpoints 80 | 81 | # IPython 82 | profile_default/ 83 | ipython_config.py 84 | 85 | # pyenv 86 | # For a library or package, you might want to ignore these files since the code is 87 | # intended to run in multiple environments; otherwise, check them in: 88 | # .python-version 89 | 90 | # pipenv 91 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. 92 | # However, in case of collaboration, if having platform-specific dependencies or dependencies 93 | # having no cross-platform support, pipenv may install dependencies that don't work, or not 94 | # install all needed dependencies. 95 | #Pipfile.lock 96 | 97 | # poetry 98 | # Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control. 99 | # This is especially recommended for binary packages to ensure reproducibility, and is more 100 | # commonly ignored for libraries. 101 | # https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control 102 | #poetry.lock 103 | 104 | # pdm 105 | # Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control. 106 | #pdm.lock 107 | # pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it 108 | # in version control. 109 | # https://pdm.fming.dev/#use-with-ide 110 | .pdm.toml 111 | 112 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm 113 | __pypackages__/ 114 | 115 | # Celery stuff 116 | celerybeat-schedule 117 | celerybeat.pid 118 | 119 | # SageMath parsed files 120 | *.sage.py 121 | 122 | # Environments 123 | .env 124 | .venv 125 | env/ 126 | venv/ 127 | ENV/ 128 | env.bak/ 129 | venv.bak/ 130 | 131 | # Spyder project settings 132 | .spyderproject 133 | .spyproject 134 | 135 | # Rope project settings 136 | .ropeproject 137 | 138 | # mkdocs documentation 139 | /site 140 | 141 | # mypy 142 | .mypy_cache/ 143 | .dmypy.json 144 | dmypy.json 145 | 146 | # Pyre type checker 147 | .pyre/ 148 | 149 | # pytype static type analyzer 150 | .pytype/ 151 | 152 | # Cython debug symbols 153 | cython_debug/ 154 | 155 | # PyCharm 156 | # JetBrains specific template is maintained in a separate JetBrains.gitignore that can 157 | # be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore 158 | # and can be added to the global gitignore or merged into this file. For a more nuclear 159 | # option (not recommended) you can uncomment the following to ignore the entire idea folder. 160 | #.idea/ 161 | 162 | # IDE 163 | .vs/ 164 | .vscode/ 165 | .idea/ 166 | 167 | # Releases 168 | AutoPack/Releases/ 169 | AutoPack/Chinese_git/ 170 | AutoPack/ReleaseNotes.md 171 | yazicbs.github.io/ 172 | 173 | # copyright 174 | 软著/ 175 | 176 | # test 177 | previous_notice.txt 178 | Script/ 179 | C#/ 180 | -------------------------------------------------------------------------------- /ABOUT_TRANSLATION.md: -------------------------------------------------------------------------------- 1 | # 关于翻译 2 | 3 | 目前已有的翻译 4 | 5 | | 语言 | 翻译者 | 完整度 | 版本 | README | README_DEV | USER_HANDBOOK | Chinese_git | Chinese_git-pack | 6 | | -------- | -------- | ------ | ---- | ------ | ---------- | ------------- | ----------- | ---------------- | 7 | | 简体中文 | 官方语言 | 100% | v3.3 | ✓ | ✓ | ✓ | ✓ | ✓ | 8 | | 繁體中文 | 官方翻译 | 40% | v1.5 | ✕ | ✕ | ✕ | ✓ | ✓ | 9 | -------------------------------------------------------------------------------- /AutoPack/AutoPack.py: -------------------------------------------------------------------------------- 1 | import os 2 | import sys 3 | import py7zr 4 | import zipfile 5 | import shutil 6 | import requests 7 | import subprocess 8 | from colorama import init, Fore 9 | # 中文Git发行版自动打包程序 10 | 11 | # --- init --- 12 | init(autoreset=True)# 颜色显示 13 | script_dir = os.path.dirname(os.path.abspath(sys.argv[0]))# 所在目录 14 | os.chdir(script_dir)# 确保命令执行位置 15 | # ------------ 16 | 17 | # --- repo config --- 18 | repo = "Chinese_git" 19 | repo_git = f"https://github.com/DuckDuckStudio/{repo}.git" 20 | repo_dir = os.path.join(script_dir, repo) 21 | # ------------------- 22 | 23 | # --- releases config --- 24 | releases_version = input("请输入Releases版本: ") 25 | 26 | ## --- uniform tag --- 27 | if releases_version.startswith("v."): 28 | releases_version = "v" + releases_version[2:] 29 | elif not releases_version.startswith("v"): 30 | releases_version = "v" + releases_version 31 | ## ------------------- 32 | 33 | pack_releases_dir = os.path.join(script_dir, 'Releases', releases_version, 'Chinese_git') 34 | py_releases_dir = os.path.join(script_dir, 'Releases', releases_version, 'Chinese_git_py') 35 | releases_dir = os.path.join(script_dir, 'Releases', releases_version) 36 | 37 | ## --- create dir --- 38 | os.makedirs(pack_releases_dir, exist_ok=True) 39 | os.makedirs(py_releases_dir, exist_ok=True) 40 | ## ------------------ 41 | 42 | pack_main = os.path.join(repo_dir, "中文git.exe") 43 | pack_update = os.path.join(repo_dir, "中文git更新程序.exe") 44 | py_main = os.path.join(repo_dir, "中文git.py") 45 | notice_file = os.path.join(repo_dir, "previous_notice.txt") 46 | license_file = os.path.join(repo_dir, "LICENSE") 47 | config_file = os.path.join(repo_dir, "config.json") 48 | # ----------------------- 49 | 50 | # --- def --- 51 | def clone(): 52 | result = subprocess.run(["git", "clone", repo_git, "--depth", "1"], capture_output=True, text=True) 53 | if result.returncode == 0: 54 | print(f"{Fore.GREEN}✓{Fore.RESET} 克隆仓库成功") 55 | return True 56 | else: 57 | print(f"{Fore.RED}✕{Fore.RESET} 克隆仓库时出错:\n{Fore.RED}{result.stderr}{Fore.RESET}") 58 | return False 59 | 60 | def get_notice(): 61 | try: 62 | response = requests.get("https://duckduckstudio.github.io/yazicbs.github.io/Tools/chinese_git/notice/notice.txt") 63 | response.raise_for_status() 64 | with open(notice_file, 'wb') as file: 65 | file.write(response.content) 66 | print(f"{Fore.GREEN}✓{Fore.RESET} 获取公告文件 (方法一) 成功") 67 | return True 68 | except Exception as e: 69 | print(f"{Fore.YELLOW}⚠{Fore.RESET} 获取公告文件 (方法一) 时出错:\n{Fore.RED}{e}{Fore.RESET}") 70 | try: 71 | result = subprocess.run(["git", "clone", "https://github.com/DuckDuckStudio/yazicbs.github.io.git", "--depth", "1"], capture_output=True, text=True) 72 | if result.returncode == 0: 73 | shutil.copy(".\\yazicbs.github.io\\Tools\\chinese_git\\notice\\notice.txt", notice_file) 74 | print(f"{Fore.GREEN}✓{Fore.RESET} 获取公告文件 (方法二) 成功") 75 | return True 76 | else: 77 | print(f"{Fore.RED}✕{Fore.RESET} 获取公告文件 (方法二) 时出错:\n{Fore.RED}{result.stderr}{Fore.RESET}") 78 | return False 79 | except Exception as e: 80 | print(f"{Fore.RED}✕{Fore.RESET} 获取公告文件 (方法二) 时出错:\n{Fore.RED}{e}{Fore.RESET}") 81 | return False 82 | 83 | def rename_file(old_name, new_name, path): 84 | try: 85 | old_file = os.path.join(path, old_name) 86 | new_file = os.path.join(path, new_name) 87 | os.rename(old_file, new_file) 88 | return True 89 | except Exception as e: 90 | print(f"{Fore.RED}✕{Fore.RESET} 处理文件名时出错:\n{Fore.RED}{e}{Fore.RESET}") 91 | return False 92 | 93 | def copy_file(): 94 | try: 95 | shutil.copy(pack_main, pack_releases_dir) 96 | shutil.copy(pack_update, pack_releases_dir) 97 | # --- 98 | shutil.copy(py_main, py_releases_dir) 99 | # --- 100 | shutil.copy(notice_file, py_releases_dir) 101 | shutil.copy(notice_file, pack_releases_dir) 102 | # --- 103 | shutil.copy(license_file, py_releases_dir) 104 | shutil.copy(license_file, pack_releases_dir) 105 | # --- 106 | shutil.copy(config_file, py_releases_dir) 107 | shutil.copy(config_file, pack_releases_dir) 108 | # ----- 109 | shutil.copy(pack_main, releases_dir) 110 | if not rename_file(os.path.basename(pack_main), "Chinese_git.exe", releases_dir): 111 | return False 112 | shutil.copy(pack_update, releases_dir) 113 | if not rename_file(os.path.basename(pack_update), "Pack_Version_Update.exe", releases_dir): 114 | return False 115 | shutil.copy(py_main, releases_dir) 116 | if not rename_file(os.path.basename(py_main), "Chinese_git.py", releases_dir): 117 | return False 118 | # ----- 119 | print(f"{Fore.GREEN}✓{Fore.RESET} 复制文件成功") 120 | return True 121 | except Exception as e: 122 | print(f"{Fore.RED}✕{Fore.RESET} 复制文件时出错:\n{Fore.RED}{e}{Fore.RESET}") 123 | return False 124 | 125 | def generate_iss_file(): 126 | # releases_version 已在前面定义 127 | if releases_version.startswith('v'): 128 | iss_version = releases_version[1:] 129 | else: 130 | iss_version = releases_version 131 | iss_file = f'''[Setup] 132 | AppName=中文Git 133 | #define cngitversion "{iss_version}" 134 | AppVersion=v{{#cngitversion}} 135 | VersionInfoVersion={{#cngitversion}} 136 | AppPublisher=DuckStudio 137 | VersionInfoCopyright=Copyright (c) 鸭鸭「カモ」 138 | AppPublisherURL=https://duckduckstudio.github.io/yazicbs.github.io/Tools/chinese_git/ 139 | DefaultDirName={{autopf}}\\Chinese_git 140 | DefaultGroupName=中文Git 141 | UninstallDisplayIcon={{app}}\\中文git.exe 142 | OutputDir={releases_dir} 143 | OutputBaseFilename=Chinese_git_Setup_v{{#cngitversion}} 144 | SetupIconFile={os.path.join(os.path.dirname(script_dir), "ico.ico")} 145 | LicenseFile={os.path.join(os.path.dirname(script_dir), "LICENSE")} 146 | Compression=lzma2 147 | SolidCompression=yes 148 | 149 | [Languages] 150 | Name: "english"; MessagesFile: "compiler:Default.isl" 151 | Name: "chinesesimplified"; MessagesFile: "compiler:Languages\\ChineseSimplified.isl" 152 | Name: "japanese"; MessagesFile: "compiler:Languages\\Japanese.isl" 153 | 154 | [Files] 155 | Source: "{pack_releases_dir}\\*"; DestDir: "{{app}}" 156 | 157 | [Icons] 158 | Name: "{{group}}\\中文Git"; Filename: "{{app}}\\中文git.exe" 159 | 160 | [Run] 161 | Filename: "{{sys}}\\cmd.exe"; Parameters: "/C setx PATH ""{{app}};%PATH%"" /M"; Flags: runhidden 162 | 163 | [UninstallRun] 164 | Filename: "{{sys}}\\cmd.exe"; Parameters: "/C setx PATH ""%PATH:{{app}};=%"" /M"; Flags: runhidden; RunOnceId: UninstallSetPath 165 | ''' 166 | try: 167 | with open(os.path.join(releases_dir, "pack.iss"), 'w') as file: 168 | file.write(iss_file) 169 | print(f"{Fore.GREEN}✓{Fore.RESET} 已生成打包用iss文件") 170 | return True 171 | except Exception as e: 172 | print(f"{Fore.RED}✕{Fore.RESET} 生成打包用iss文件时出错:\n{Fore.RED}{e}{Fore.RESET}") 173 | return False 174 | 175 | def compress_folder_to_7z(source_folder, target_folder, archive_name): 176 | try: 177 | # 压缩文件夹为7z格式 178 | with py7zr.SevenZipFile(str(os.path.join(target_folder, archive_name + '.7z')), 'w') as archive: 179 | archive.writeall(source_folder, arcname=os.path.basename(source_folder)) 180 | 181 | print(f"{Fore.GREEN}✓{Fore.RESET} 压缩7z发行版 {Fore.BLUE}{archive_name}{Fore.RESET} 成功") 182 | return True 183 | except Exception as e: 184 | print(f"{Fore.RED}✕{Fore.RESET} 压缩7z发行版 {Fore.BLUE}{archive_name}{Fore.RESET} 时出错:\n{Fore.RED}{e}{Fore.RESET}") 185 | return False 186 | 187 | def compress_folder_to_zip(source_folder, target_folder, archive_name): 188 | try: 189 | # 压缩文件夹为zip格式 190 | with zipfile.ZipFile(str(os.path.join(target_folder, archive_name + '.zip')), 'w', zipfile.ZIP_DEFLATED) as archive: 191 | for root, dirs, files in os.walk(source_folder): 192 | for file in files: 193 | archive.write(str(os.path.join(root, file)), os.path.relpath(str(os.path.join(root, file)), source_folder)) 194 | 195 | print(f"{Fore.GREEN}✓{Fore.RESET} 压缩zip发行版 {Fore.BLUE}{archive_name}{Fore.RESET} 成功") 196 | return True 197 | except Exception as e: 198 | print(f"{Fore.RED}✕{Fore.RESET} 压缩zip发行版 {Fore.BLUE}{archive_name}{Fore.RESET} 时出错:\n{Fore.RED}{e}{Fore.RESET}") 199 | return False 200 | 201 | def compress_releases(): 202 | try: 203 | compress_folder_to_zip(pack_releases_dir, releases_dir, "Chinese_git") 204 | compress_folder_to_zip(py_releases_dir, releases_dir, "Chinese_git_py") 205 | compress_folder_to_7z(pack_releases_dir, releases_dir, "Chinese_git") 206 | compress_folder_to_7z(py_releases_dir, releases_dir, "Chinese_git_py") 207 | subprocess.run(["iscc", os.path.join(releases_dir, "pack.iss")], check=True) 208 | return True 209 | except Exception: 210 | return False 211 | # ----------- 212 | 213 | def jobs_clean_up(step): 214 | # 按照失败的步骤清理工作文件 215 | if step == "clone": 216 | if os.path.exists(repo_dir): 217 | try: 218 | shutil.rmtree(pack_releases_dir) 219 | shutil.rmtree(py_releases_dir) 220 | shutil.rmtree(repo_dir) 221 | print(f"{Fore.GREEN}✓{Fore.RESET} 成功清理工作文件") 222 | return True 223 | except Exception as e: 224 | print(f"{Fore.RED}✕{Fore.RESET} 清理失败,因为:\n{Fore.RED}{e}{Fore.RESET}") 225 | return False 226 | else: 227 | print(f"{Fore.YELLOW}⚠{Fore.RESET} 跳过清理,因为目录 {Fore.BLUE}{repo_dir}{Fore.RESET} 不存在") 228 | return True 229 | elif step == "finish": 230 | if os.path.exists(repo_dir): 231 | # Chinese_git 仓库 232 | try: 233 | # 移除非空目录 repo_dir 234 | shutil.rmtree(repo_dir) 235 | print(f"{Fore.GREEN}✓{Fore.RESET} 成功清理 Chinese_git 仓库文件") 236 | # 权限 237 | except PermissionError: 238 | print(f"{Fore.RED}✕{Fore.RESET} 清理 Chinese_git 仓库文件失败: {Fore.YELLOW}权限不足{Fore.RESET}") 239 | return False 240 | except Exception as e: 241 | print(f"{Fore.RED}✕{Fore.RESET} 清理 Chinese_git 仓库文件失败: {Fore.RED}{e}{Fore.RESET}") 242 | return False 243 | if os.path.exists(os.path.join(script_dir, "yazicbs.github.io")): 244 | # (方法二) 公告文件所在仓库 245 | try: 246 | shutil.rmtree(os.path.join(script_dir, "yazicbs.github.io")) 247 | print(f"{Fore.GREEN}✓{Fore.RESET} 成功清理 yazicbs.github.io 仓库文件") 248 | except PermissionError: 249 | print(f"{Fore.RED}✕{Fore.RESET} 清理 yazicbs.github.io 仓库文件失败: {Fore.YELLOW}权限不足{Fore.RESET}") 250 | return False 251 | except Exception as e: 252 | print(f"{Fore.RED}✕{Fore.RESET} 清理 yazicbs.github.io 仓库文件失败: {Fore.RED}{e}{Fore.RESET}") 253 | return False 254 | if os.path.exists(os.path.join(releases_dir, "pack.iss")): 255 | # 移除单文件 256 | try: 257 | os.remove(os.path.join(releases_dir, "pack.iss")) 258 | print(f"{Fore.GREEN}✓{Fore.RESET} 成功清理 pack.iss 文件") 259 | except PermissionError: 260 | print(f"{Fore.RED}✕{Fore.RESET} 清理 pack.iss 文件失败: {Fore.YELLOW}权限不足{Fore.RESET}") 261 | return False 262 | except Exception as e: 263 | print(f"{Fore.RED}✕{Fore.RESET} 清理 pack.iss 文件失败: {Fore.RED}{e}{Fore.RESET}") 264 | return False 265 | print(f"{Fore.GREEN}✓{Fore.RESET} 成功清理工作区!") 266 | return True 267 | else: 268 | print(f"{Fore.RED}✕{Fore.RESET} 未知步骤 {Fore.BLUE}{step}{Fore.RESET}") 269 | return False 270 | 271 | # --- main --- 272 | def main(): 273 | try: 274 | if clone(): 275 | if get_notice(): 276 | if copy_file(): 277 | if generate_iss_file(): 278 | if compress_releases(): 279 | if jobs_clean_up("finish"): 280 | return 0 281 | else: 282 | jobs_clean_up("clone") 283 | else: 284 | jobs_clean_up("clone") 285 | # 如果某个操作失败 286 | return 1 287 | except KeyboardInterrupt: 288 | print(f"{Fore.BLUE}[!]{Fore.RESET} 操作取消") 289 | return 2 290 | # ------------ 291 | 292 | sys.exit(main()) 293 | -------------------------------------------------------------------------------- /AutoPack/packinit.iss: -------------------------------------------------------------------------------- 1 | [Setup] 2 | AppName=中文Git 3 | #define cngitversion "程序版本" 4 | AppVersion=v{#cngitversion} 5 | VersionInfoVersion={#cngitversion} 6 | AppPublisher=DuckStudio 7 | VersionInfoCopyright=Copyright (c) 鸭鸭「カモ」 8 | AppPublisherURL=https://duckduckstudio.github.io/yazicbs.github.io/Tools/chinese_git/ 9 | DefaultDirName={autopf}\Chinese_git 10 | DefaultGroupName=中文Git 11 | UninstallDisplayIcon={app}\中文git.exe 12 | OutputDir=D:\Duckhome\projects\MSVS\Source\Repos\Chinese_git\AutoPack\Releases\v{#cngitversion} 13 | OutputBaseFilename=Chinese_git_Setup_v{#cngitversion} 14 | SetupIconFile=D:\Duckhome\projects\MSVS\Source\Repos\Chinese_git\ico.ico 15 | LicenseFile=D:\Duckhome\projects\MSVS\Source\Repos\Chinese_git\发行版\LICENSE 16 | Compression=lzma2 17 | SolidCompression=yes 18 | 19 | [Languages] 20 | Name: "english"; MessagesFile: "compiler:Default.isl" 21 | Name: "chinesesimplified"; MessagesFile: "compiler:Languages\ChineseSimplified.isl" 22 | Name: "japanese"; MessagesFile: "compiler:Languages\Japanese.isl" 23 | 24 | [Files] 25 | Source: "D:\Duckhome\projects\MSVS\Source\Repos\Chinese_git\AutoPack\Releases\v{#cngitversion}\Chinese_git\*"; DestDir: "{app}" 26 | 27 | [Icons] 28 | Name: "{group}\中文Git"; Filename: "{app}\中文git.exe" 29 | 30 | [Run] 31 | Filename: "{sys}\cmd.exe"; Parameters: "/C setx PATH ""{app};%PATH%"" /M"; Flags: runhidden 32 | 33 | [UninstallRun] 34 | Filename: "{sys}\cmd.exe"; Parameters: "/C setx PATH ""%PATH:{app};=%"" /M"; Flags: runhidden; RunOnceId: UninstallSetPath 35 | -------------------------------------------------------------------------------- /AutoPack/requirements.txt: -------------------------------------------------------------------------------- 1 | requests==2.32.3 2 | colorama==0.4.6 3 | py7zr==0.22.0 4 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # 中文Git 开发者文档 2 | 3 | 如果你是开发人员,想要贡献中文Git,这个开发者文档会告诉你如何开始。 4 | 5 | ## 项目结构 6 | 7 | 中文Git项目的结构如下: 8 | 9 | ``` 10 | 中文Git 11 | | .gitignore 12 | | ABOUT_TRANSLATION.md 13 | | config.json 14 | | CONTRIBUTING.md 15 | | ico.ico 16 | | LICENSE 17 | | README.md 18 | | README_DEV.md 19 | | requirements.txt 20 | | USER_HANDBOOK.md 21 | | 中文git-pack.py 22 | | 中文git.exe 23 | | 中文git.py 24 | | 中文git更新程序.exe 25 | | 中文git更新程序.py 26 | | 27 | +---.auto_script 28 | | del_old_files.py 29 | | 30 | +---.github 31 | | | CODEOWNERS.md 32 | | | dependabot.yml 33 | | | PULL_REQUEST_TEMPLATE.md 34 | | | 35 | | \---ISSUE_TEMPLATE 36 | | bug_feedback.yml 37 | | config.yml 38 | | feature_request.yml 39 | | new_command_request.yml 40 | | 41 | +---AutoPack 42 | | AutoPack.py 43 | | AutoPack_CN.py 44 | | packinit.iss 45 | | requirements.txt 46 | | 47 | +---docs 48 | | \---image 49 | | \---README 50 | | 1718315176839.png 51 | | 52 | \---zh-tw 53 | 中文git-pack.py 54 | 中文git.py 55 | ``` 56 | 57 | * `zh-tw`: 项目的 繁体中文 翻译 58 | * `.gitignore`: Git 忽略文件 59 | * `中文git-pack.py`: 中文Git的打包版的主要代码文件,包含了中文Git的核心功能。 60 | * `中文git.exe`: 中文Git的主要代码文件的打包版(使用Pyinstaller打包),包含了中文Git的核心功能。 61 | * `中文git.py`: 中文Git的主要代码文件,包含了中文Git的核心功能。 62 | * `ABOUT_TRANSLATION.md`: 项目的翻译进度展示文件 63 | * `中文git更新程序.py`: 中文Git的打包版的更新代码文件 64 | * `中文git更新程序.exe`: 中文Git的打包版的更新程序(使用Pyinstaller打包) 65 | * `CONTRIBUTING.md`(本文件): 开发者文档,用于开发人员了解项目的内部结构和如何贡献。 66 | * `ico.ico`: 中文Git 项目图标 67 | * `LICENSE`: 开源许可文件(GPL 2.0) 68 | * `README_DEV.md`: 项目的详细用户指南,用于向看不惯`README.md`的用户介绍中文Git 69 | * `README.md`: 项目的直白话用户指南,用于向用户介绍中文Git。 70 | * `USER_HANDBOOK.md`: 项目的用户手册,用于向用户详细介绍如何使用 71 | 72 | > _对于新的文件调整待补充说明_ 73 | 74 | ## 如何开始贡献 75 | 76 | 欢迎各种形式的贡献,无论是提交bug报告、提出改进建议还是直接提交代码修复问题。以下是贡献步骤: 77 | 78 | 1. fork 本项目 79 | 2. 克隆项目到本地 80 | 3. 在新仓库上进行修改 81 | 4. 提交你的更改 82 | 5. 提交Pull Request,描述你的修改并等待审核 83 | 84 | ### 你可以贡献什么 85 | 1. 添加新的可用命令 86 | 这非常简单,如果您不想做错误处理,直接在`git_command(command, *args)`函数中添加命令匹配即可。 87 | 2. 对现有的可用命令的处理进行改进 88 | 您可以在`git_command(command, *args)`函数中的`if git_command:`后看到对于各个命令的处理,每个命令在一个`if`中,您可以添加新的处理,或者优化现有处理。在添加新的处理时请使用`elif`而不是另外的`if`。 89 | 3. 文档 90 | 说实话,当初为了好玩把这几个文档弄得这么奇葩...唉,总之,如果您可以帮忙整合/理文档,我非常感谢。 91 | 他们几乎都是相同的内容,计划将他们合并成一个文档,但我始终下不了手。 92 | 4. 自动流 93 | 目前此软件包还是我自己手动通过[命令](#如何打包)打包的,如果您能帮忙编写有关Linux/Macos系统上的发布流那就太好了!我没有用这两个系统的设备,我对他们几乎一无所知。 94 | 95 | ## 报告问题和提出建议 96 | 97 | 如果你发现了bug或者有任何改进建议,欢迎在GitHub上提交Issues。在提交Issue时,请提供清晰的描述以及复现步骤。建议使用Issue模板提交您的问题。 98 | 99 | ## 项目许可 100 | 101 | 中文Git采用 GPL 2.0 许可证,详情请参阅[LICENSE](https://github.com/DuckDuckStudio/Chinese_git/blob/main/LICENSE)文件。 102 | 103 | 感谢您的支持和贡献! 104 | 105 | ## 如何打包 106 | 107 | > [!NOTE] 108 | > 打包前请安装依赖! 109 | 110 | 本项目有三种从py到exe的打包方式: 111 | 112 | 1. pyinstaller 113 | 打包命令为: 114 | ```bash 115 | pyinstaller --onefile -i ico.ico --distpath=. --name="中文git.exe" "中文git-pack.py" 116 | pyinstaller --onefile -i ico.ico --distpath=. --name="中文git更新程序.exe" "中文git更新程序.py" 117 | ``` 118 | 2. Nuitka 119 | 打包命令为: 120 | ```bash 121 | python -m nuitka --output-dir=. --show-progress --windows-icon-from-ico=ico.ico --onefile --remove-output "中文git-pack.py" 122 | python -m nuitka --output-dir=. --show-progress --windows-icon-from-ico=ico.ico --onefile --remove-output "中文git更新程序.py" 123 | ``` 124 | 3. 使用AutoPack工具 125 | ```bash 126 | python "AutoPack\AutoPack.py" 127 | ``` 128 | 129 | ## 关于winget包请求 130 | 如果你发现最新发行版在winget包中不可用,请向[microsoft/winget](https://github.com/microsoft/winget-pkgs)提交程序清单。 131 | 在提交时还请 @DuckDuckStudio / @Luna-Grace ,感谢。 132 | 使用`winget show --id DuckStudio.ChineseGit --source winget --exact --versions`来查找可用版本。 133 | 你可以直接提交拉取请求,也可以创建议题让我们添加清单。 134 | 135 | ## 关于翻译 136 | 如果你希协助 中文Git 进行 繁体中文 本地化,请将您的翻译结果提交到文件夹 `zh-tw` 内。 137 | 对于翻译的要求: 138 | 1. 翻译必须遵循 简体中文 的翻译,除非 简体中文 的翻译出错 139 | 2. 翻译完成后请提交 PR 140 | 3. 在翻译时也请同时翻译`README_DEV.md`与`USER_HANDBOOK.md` 141 | 142 | ## 已知问题 143 | 144 | 请见[Issues页](https://github.com/DuckDuckStudio/Chinese_git/issues)。 145 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 2, June 1991 3 | 4 | Copyright (C) 1989, 1991 Free Software Foundation, Inc., 5 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 6 | Everyone is permitted to copy and distribute verbatim copies 7 | of this license document, but changing it is not allowed. 8 | 9 | Preamble 10 | 11 | The licenses for most software are designed to take away your 12 | freedom to share and change it. By contrast, the GNU General Public 13 | License is intended to guarantee your freedom to share and change free 14 | software--to make sure the software is free for all its users. This 15 | General Public License applies to most of the Free Software 16 | Foundation's software and to any other program whose authors commit to 17 | using it. (Some other Free Software Foundation software is covered by 18 | the GNU Lesser General Public License instead.) You can apply it to 19 | your programs, too. 20 | 21 | When we speak of free software, we are referring to freedom, not 22 | price. Our General Public Licenses are designed to make sure that you 23 | have the freedom to distribute copies of free software (and charge for 24 | this service if you wish), that you receive source code or can get it 25 | if you want it, that you can change the software or use pieces of it 26 | in new free programs; and that you know you can do these things. 27 | 28 | To protect your rights, we need to make restrictions that forbid 29 | anyone to deny you these rights or to ask you to surrender the rights. 30 | These restrictions translate to certain responsibilities for you if you 31 | distribute copies of the software, or if you modify it. 32 | 33 | For example, if you distribute copies of such a program, whether 34 | gratis or for a fee, you must give the recipients all the rights that 35 | you have. You must make sure that they, too, receive or can get the 36 | source code. And you must show them these terms so they know their 37 | rights. 38 | 39 | We protect your rights with two steps: (1) copyright the software, and 40 | (2) offer you this license which gives you legal permission to copy, 41 | distribute and/or modify the software. 42 | 43 | Also, for each author's protection and ours, we want to make certain 44 | that everyone understands that there is no warranty for this free 45 | software. If the software is modified by someone else and passed on, we 46 | want its recipients to know that what they have is not the original, so 47 | that any problems introduced by others will not reflect on the original 48 | authors' reputations. 49 | 50 | Finally, any free program is threatened constantly by software 51 | patents. We wish to avoid the danger that redistributors of a free 52 | program will individually obtain patent licenses, in effect making the 53 | program proprietary. To prevent this, we have made it clear that any 54 | patent must be licensed for everyone's free use or not licensed at all. 55 | 56 | The precise terms and conditions for copying, distribution and 57 | modification follow. 58 | 59 | GNU GENERAL PUBLIC LICENSE 60 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 61 | 62 | 0. This License applies to any program or other work which contains 63 | a notice placed by the copyright holder saying it may be distributed 64 | under the terms of this General Public License. The "Program", below, 65 | refers to any such program or work, and a "work based on the Program" 66 | means either the Program or any derivative work under copyright law: 67 | that is to say, a work containing the Program or a portion of it, 68 | either verbatim or with modifications and/or translated into another 69 | language. (Hereinafter, translation is included without limitation in 70 | the term "modification".) Each licensee is addressed as "you". 71 | 72 | Activities other than copying, distribution and modification are not 73 | covered by this License; they are outside its scope. The act of 74 | running the Program is not restricted, and the output from the Program 75 | is covered only if its contents constitute a work based on the 76 | Program (independent of having been made by running the Program). 77 | Whether that is true depends on what the Program does. 78 | 79 | 1. You may copy and distribute verbatim copies of the Program's 80 | source code as you receive it, in any medium, provided that you 81 | conspicuously and appropriately publish on each copy an appropriate 82 | copyright notice and disclaimer of warranty; keep intact all the 83 | notices that refer to this License and to the absence of any warranty; 84 | and give any other recipients of the Program a copy of this License 85 | along with the Program. 86 | 87 | You may charge a fee for the physical act of transferring a copy, and 88 | you may at your option offer warranty protection in exchange for a fee. 89 | 90 | 2. You may modify your copy or copies of the Program or any portion 91 | of it, thus forming a work based on the Program, and copy and 92 | distribute such modifications or work under the terms of Section 1 93 | above, provided that you also meet all of these conditions: 94 | 95 | a) You must cause the modified files to carry prominent notices 96 | stating that you changed the files and the date of any change. 97 | 98 | b) You must cause any work that you distribute or publish, that in 99 | whole or in part contains or is derived from the Program or any 100 | part thereof, to be licensed as a whole at no charge to all third 101 | parties under the terms of this License. 102 | 103 | c) If the modified program normally reads commands interactively 104 | when run, you must cause it, when started running for such 105 | interactive use in the most ordinary way, to print or display an 106 | announcement including an appropriate copyright notice and a 107 | notice that there is no warranty (or else, saying that you provide 108 | a warranty) and that users may redistribute the program under 109 | these conditions, and telling the user how to view a copy of this 110 | License. (Exception: if the Program itself is interactive but 111 | does not normally print such an announcement, your work based on 112 | the Program is not required to print an announcement.) 113 | 114 | These requirements apply to the modified work as a whole. If 115 | identifiable sections of that work are not derived from the Program, 116 | and can be reasonably considered independent and separate works in 117 | themselves, then this License, and its terms, do not apply to those 118 | sections when you distribute them as separate works. But when you 119 | distribute the same sections as part of a whole which is a work based 120 | on the Program, the distribution of the whole must be on the terms of 121 | this License, whose permissions for other licensees extend to the 122 | entire whole, and thus to each and every part regardless of who wrote it. 123 | 124 | Thus, it is not the intent of this section to claim rights or contest 125 | your rights to work written entirely by you; rather, the intent is to 126 | exercise the right to control the distribution of derivative or 127 | collective works based on the Program. 128 | 129 | In addition, mere aggregation of another work not based on the Program 130 | with the Program (or with a work based on the Program) on a volume of 131 | a storage or distribution medium does not bring the other work under 132 | the scope of this License. 133 | 134 | 3. You may copy and distribute the Program (or a work based on it, 135 | under Section 2) in object code or executable form under the terms of 136 | Sections 1 and 2 above provided that you also do one of the following: 137 | 138 | a) Accompany it with the complete corresponding machine-readable 139 | source code, which must be distributed under the terms of Sections 140 | 1 and 2 above on a medium customarily used for software interchange; or, 141 | 142 | b) Accompany it with a written offer, valid for at least three 143 | years, to give any third party, for a charge no more than your 144 | cost of physically performing source distribution, a complete 145 | machine-readable copy of the corresponding source code, to be 146 | distributed under the terms of Sections 1 and 2 above on a medium 147 | customarily used for software interchange; or, 148 | 149 | c) Accompany it with the information you received as to the offer 150 | to distribute corresponding source code. (This alternative is 151 | allowed only for noncommercial distribution and only if you 152 | received the program in object code or executable form with such 153 | an offer, in accord with Subsection b above.) 154 | 155 | The source code for a work means the preferred form of the work for 156 | making modifications to it. For an executable work, complete source 157 | code means all the source code for all modules it contains, plus any 158 | associated interface definition files, plus the scripts used to 159 | control compilation and installation of the executable. However, as a 160 | special exception, the source code distributed need not include 161 | anything that is normally distributed (in either source or binary 162 | form) with the major components (compiler, kernel, and so on) of the 163 | operating system on which the executable runs, unless that component 164 | itself accompanies the executable. 165 | 166 | If distribution of executable or object code is made by offering 167 | access to copy from a designated place, then offering equivalent 168 | access to copy the source code from the same place counts as 169 | distribution of the source code, even though third parties are not 170 | compelled to copy the source along with the object code. 171 | 172 | 4. You may not copy, modify, sublicense, or distribute the Program 173 | except as expressly provided under this License. Any attempt 174 | otherwise to copy, modify, sublicense or distribute the Program is 175 | void, and will automatically terminate your rights under this License. 176 | However, parties who have received copies, or rights, from you under 177 | this License will not have their licenses terminated so long as such 178 | parties remain in full compliance. 179 | 180 | 5. You are not required to accept this License, since you have not 181 | signed it. However, nothing else grants you permission to modify or 182 | distribute the Program or its derivative works. These actions are 183 | prohibited by law if you do not accept this License. Therefore, by 184 | modifying or distributing the Program (or any work based on the 185 | Program), you indicate your acceptance of this License to do so, and 186 | all its terms and conditions for copying, distributing or modifying 187 | the Program or works based on it. 188 | 189 | 6. Each time you redistribute the Program (or any work based on the 190 | Program), the recipient automatically receives a license from the 191 | original licensor to copy, distribute or modify the Program subject to 192 | these terms and conditions. You may not impose any further 193 | restrictions on the recipients' exercise of the rights granted herein. 194 | You are not responsible for enforcing compliance by third parties to 195 | this License. 196 | 197 | 7. If, as a consequence of a court judgment or allegation of patent 198 | infringement or for any other reason (not limited to patent issues), 199 | conditions are imposed on you (whether by court order, agreement or 200 | otherwise) that contradict the conditions of this License, they do not 201 | excuse you from the conditions of this License. If you cannot 202 | distribute so as to satisfy simultaneously your obligations under this 203 | License and any other pertinent obligations, then as a consequence you 204 | may not distribute the Program at all. For example, if a patent 205 | license would not permit royalty-free redistribution of the Program by 206 | all those who receive copies directly or indirectly through you, then 207 | the only way you could satisfy both it and this License would be to 208 | refrain entirely from distribution of the Program. 209 | 210 | If any portion of this section is held invalid or unenforceable under 211 | any particular circumstance, the balance of the section is intended to 212 | apply and the section as a whole is intended to apply in other 213 | circumstances. 214 | 215 | It is not the purpose of this section to induce you to infringe any 216 | patents or other property right claims or to contest validity of any 217 | such claims; this section has the sole purpose of protecting the 218 | integrity of the free software distribution system, which is 219 | implemented by public license practices. Many people have made 220 | generous contributions to the wide range of software distributed 221 | through that system in reliance on consistent application of that 222 | system; it is up to the author/donor to decide if he or she is willing 223 | to distribute software through any other system and a licensee cannot 224 | impose that choice. 225 | 226 | This section is intended to make thoroughly clear what is believed to 227 | be a consequence of the rest of this License. 228 | 229 | 8. If the distribution and/or use of the Program is restricted in 230 | certain countries either by patents or by copyrighted interfaces, the 231 | original copyright holder who places the Program under this License 232 | may add an explicit geographical distribution limitation excluding 233 | those countries, so that distribution is permitted only in or among 234 | countries not thus excluded. In such case, this License incorporates 235 | the limitation as if written in the body of this License. 236 | 237 | 9. The Free Software Foundation may publish revised and/or new versions 238 | of the General Public License from time to time. Such new versions will 239 | be similar in spirit to the present version, but may differ in detail to 240 | address new problems or concerns. 241 | 242 | Each version is given a distinguishing version number. If the Program 243 | specifies a version number of this License which applies to it and "any 244 | later version", you have the option of following the terms and conditions 245 | either of that version or of any later version published by the Free 246 | Software Foundation. If the Program does not specify a version number of 247 | this License, you may choose any version ever published by the Free Software 248 | Foundation. 249 | 250 | 10. If you wish to incorporate parts of the Program into other free 251 | programs whose distribution conditions are different, write to the author 252 | to ask for permission. For software which is copyrighted by the Free 253 | Software Foundation, write to the Free Software Foundation; we sometimes 254 | make exceptions for this. Our decision will be guided by the two goals 255 | of preserving the free status of all derivatives of our free software and 256 | of promoting the sharing and reuse of software generally. 257 | 258 | NO WARRANTY 259 | 260 | 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY 261 | FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN 262 | OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES 263 | PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED 264 | OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 265 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS 266 | TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE 267 | PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, 268 | REPAIR OR CORRECTION. 269 | 270 | 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 271 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR 272 | REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, 273 | INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING 274 | OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED 275 | TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY 276 | YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER 277 | PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE 278 | POSSIBILITY OF SUCH DAMAGES. 279 | 280 | END OF TERMS AND CONDITIONS 281 | 282 | How to Apply These Terms to Your New Programs 283 | 284 | If you develop a new program, and you want it to be of the greatest 285 | possible use to the public, the best way to achieve this is to make it 286 | free software which everyone can redistribute and change under these terms. 287 | 288 | To do so, attach the following notices to the program. It is safest 289 | to attach them to the start of each source file to most effectively 290 | convey the exclusion of warranty; and each file should have at least 291 | the "copyright" line and a pointer to where the full notice is found. 292 | 293 | ChineseGit, an open-source tool that allows you to execute git commands in Chinese. 294 | Copyright (C) 2024 鸭鸭「カモ」 295 | 296 | This program is free software; you can redistribute it and/or modify 297 | it under the terms of the GNU General Public License as published by 298 | the Free Software Foundation; either version 2 of the License, or 299 | (at your option) any later version. 300 | 301 | This program is distributed in the hope that it will be useful, 302 | but WITHOUT ANY WARRANTY; without even the implied warranty of 303 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 304 | GNU General Public License for more details. 305 | 306 | You should have received a copy of the GNU General Public License along 307 | with this program; if not, write to the Free Software Foundation, Inc., 308 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 309 | 310 | Also add information on how to contact you by electronic and paper mail. 311 | 312 | If the program is interactive, make it output a short notice like this 313 | when it starts in an interactive mode: 314 | 315 | Gnomovision version 69, Copyright (C) year name of author 316 | Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 317 | This is free software, and you are welcome to redistribute it 318 | under certain conditions; type `show c' for details. 319 | 320 | The hypothetical commands `show w' and `show c' should show the appropriate 321 | parts of the General Public License. Of course, the commands you use may 322 | be called something other than `show w' and `show c'; they could even be 323 | mouse-clicks or menu items--whatever suits your program. 324 | 325 | You should also get your employer (if you work as a programmer) or your 326 | school, if any, to sign a "copyright disclaimer" for the program, if 327 | necessary. Here is a sample; alter the names: 328 | 329 | Yoyodyne, Inc., hereby disclaims all copyright interest in the program 330 | `Gnomovision' (which makes passes at compilers) written by James Hacker. 331 | 332 | , 1 April 1989 333 | Ty Coon, President of Vice 334 | 335 | This General Public License does not permit incorporating your program into 336 | proprietary programs. If your program is a subroutine library, you may 337 | consider it more useful to permit linking proprietary applications with the 338 | library. If this is what you want to do, use the GNU Lesser General 339 | Public License instead of this License. 340 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 中文Git 2 | 3 | [![项目展示图](https://duckduckstudio.github.io/yazicbs.github.io/Tools/chinese_git/photos/展示图.png)](https://duckduckstudio.github.io/yazicbs.github.io/Tools/chinese_git/) 4 | 5 | [![GitHub Release](https://img.shields.io/github/release/DuckDuckStudio/Chinese_git?style=flat)](https://github.com/DuckDuckStudio/Chinese_git/releases/latest) [![Github All Releases](https://img.shields.io/github/downloads/DuckDuckStudio/Chinese_git/total.svg?style=flat)]() [![Github LICENSE](https://img.shields.io/github/license/DuckDuckStudio/Chinese_git?style=flat)]() 6 | 7 | 项目网站:[[点我前往]](https://duckduckstudio.github.io/yazicbs.github.io/Tools/chinese_git/) 8 | 9 | 你还在为忘记 git 的命令而发愁吗? 10 | 你还要每次执行 git 命令都要去搜索吗? 11 | 机会来了!使用中文Git,这些统统不是问题! 12 | ~~赶紧拿起电话订购吧!~~ 13 | 14 | > [!NOTE] 15 | > 本 README 文件内容为直白讲述,如果看不惯请查看 [README_DEV](https://github.com/DuckDuckStudio/Chinese_git/blob/main/README_DEV.md) 文件。 16 | > 如果你希望协助更新这些文档以及 中文Git ,请查看[CONTRIBUTING](https://github.com/DuckDuckStudio/Chinese_git/blob/main/CONTRIBUTING.md)文件。感谢您的支持!您的支持是我们继续维护的动力! 17 | > 项目LICENSE:GPL-2.0 18 | > 你也可以查看 中文Git 的[用户手册](https://github.com/DuckDuckStudio/Chinese_git/blob/main/USER_HANDBOOK.md)来了解更多信息。 19 | 20 | ## 项目介绍 21 | 中文Git 是一个使用中文命令操作 Git 的简单工具,旨在使不熟悉英文的用户更轻松地使用 Git。 22 | 使用 中文Git 可以使用中文指令进行常见的 Git 操作,再也不用去背英文啦! 23 | 24 | ## 如何获取 25 | 请前往[仓库发行版页](https://github.com/DuckDuckStudio/Chinese_git/releases/)下载最新版中文Git。 26 | 如果你已有中文Git,只是希望更新,请查看条目[如何更新中文Git](#如何更新)。 27 | 28 | ### 使用 winget 29 | 你也可以使用 _winget_ 来获取中文Git,请留意支持 _winget_ 获取的版本。 30 | 使用以下命令安装: 31 | ```bash 32 | winget install DuckStudio.ChineseGit 33 | ``` 34 | 输出类似这样: 35 | ![1718315176839](https://duckduckstudio.github.io/Chinese_git/image/README/1718315176839.png) 36 | 37 | > [!TIP] 38 | > 设支持的版本号为n,则 $2.4 \leqslant n \leqslant 2.10$ 39 | > winget会错误的将版本2.10显示为版本2.1,更多信息请见[microsoft/winget-pkgs#196868](https://github.com/microsoft/winget-pkgs/issues/196868) 40 | 41 | ## 项目依赖 42 | 在使用 中文Git 前,请确保你有以下依赖,否则 中文Git 将变成废物。 43 | 44 | ### Python 45 | 请确保您的系统已配置Python环境,并已安装所需库。 46 | 运行以下命令检查Python版本: 47 | 48 | ```bash 49 | python --version 50 | ``` 51 | 52 | 你可能会看到类似这样的输出: 53 | 54 | ``` 55 | C:\Users\user_name>python --version 56 | Python 3.12.0 57 | ``` 58 | 59 | 运行以下命令以安装所需库: 60 | 61 | ```bash 62 | pip install -r requirements.txt 63 | ``` 64 | 65 | 如果你无法运行指令,请参阅芙芙工具箱文档(懒得再写一个文档了)中的[[Q:我该如何添加python到系统PATH环境变量]](https://duckduckstudio.github.io/yazicbs.github.io/Tools/Fufu_Tools/wiki/%E5%B8%B8%E8%A7%81%E9%97%AE%E9%A2%98Q&A/%E4%B8%BB%E7%A8%8B%E5%BA%8F/#add-python-to-path) 66 | 67 | 对于实在是不会配置(或者根本就是懒)的人,也有个备选方案,你可以前往仓库发行版下载最新版本的压缩包,里面包含打包好的 中文Git.exe 程序。但在执行命令时可能会不一样,详细请参阅下面的[如何执行命令](#如何执行命令)。 68 | > [!TIP] 69 | > 使用 _winget_ 获取的不用配置Python。 70 | 71 | ### Git 72 | 请确保你的设备中已配置 Git 。 73 | Git是一个版本管理工具...(省略一堆介绍,反正你也知道)...在使用 中文Git 前必须配置 Git 。 74 | 运行以下命令以检查: 75 | ```bash 76 | git -v 77 | ``` 78 | 如果你看到类似这样的输出则表明你不用管他了: 79 | ``` 80 | git version 2.47.1.windows.1 81 | ``` 82 | 如果你无法运行命令,请[下载Git](https://git-scm.com/downloads)。如果你已下载Git还无法运行命令,请添加Git到环境变量。(看我干嘛,我又没在[官方文档](https://git-scm.com/book/zh/v2)中找到如何配置,上面的 Python 怎么配置的 Git 就怎么配置) 83 | > [!IMPORTANT] 84 | > 此项为必须,即使你使用打包版 85 | 86 | ## 如何执行命令 87 | 88 | 一般情况下,你可以使用以下这个命令来使用 中文Git : 89 | ```bash 90 | python 中文git.py 命令 91 | ``` 92 | 如果你使用的是打包好的 中文Git ,请用以下命令来使用 中文Git : 93 | ```bash 94 | path\to\中文git.exe 命令 95 | ``` 96 | 97 | > [!NOTE] 98 | > 在使用 python 运行 中文Git 时,请确保 中文git.py 的路径正确!可以使用相对路径。 99 | > 在使用 打包后的中文Git.exe 运行时,请使用绝对路径 100 | 101 | ### 优化 102 | 每次都要输这么多的命令...烦死了。 103 | 我们来优化一下命令吧! 104 | 105 | #### 打包版 106 | 1. 将程序目录添加到系统环境变量`PATH`中。 107 | 类似的具体操作请参阅 [[芙芙工具箱] Q:我该如何添加python到系统PATH环境变量](https://duckduckstudio.github.io/yazicbs.github.io/Tools/Fufu_Tools/wiki/常见问题Q&A/主程序/index.html#add-python-to-path) 108 | 2. 重启你的设备 109 | 3. 验证 110 | 运行以下命令以验证配置: 111 | ```bash 112 | 中文git 版本 113 | ``` 114 | 你应该会看到如下输出: 115 | ``` 116 | 中文Git by 鸭鸭「カモ」 117 | 版本:v2.x 118 | 安装在: D:\...\Chinese_git\中文git.exe 119 | git version 2.47.1.windows.1 120 | 121 | ``` 122 | *(版本不一样没关系)* 123 | 124 | #### 源码 125 | > [!WARNING] 126 | > 此方法可能仅对只传入一个参数时才有效,更多信息请见[DuckDuckStudio/Fufu_Tools#97](https://github.com/DuckDuckStudio/Fufu_Tools/issues/97) 127 | 128 | 1. 新建一个文件夹,名称随意(这里假设叫`Chinese_git_Script`。~~很复杂也没事,反正命令用不到~~) 129 | 2. 在文件夹中新建一个叫`中文git.ps1`的脚本,并在脚本中添加以下内容: 130 | - 对于 **py版** : 131 | ```powershell 132 | param( 133 | [string]$command, 134 | [string[]]$inputArgs 135 | ) 136 | 137 | python "D:\中文Git的完整路径\中文git.py" $command $inputArgs 138 | ``` 139 | > [!WARNING] 140 | > 如果你创建了虚拟Python环境,请将`python`改为虚拟环境中的`python.exe`。 141 | > 示例: 142 | > ```powershell 143 | > param( 144 | > [string]$command, 145 | > [string[]]$inputArgs 146 | > ) 147 | > $venv_python = "D:\虚拟环境路径\Scripts\python.exe" 148 | > $scriptPath = "D:\完整路径\中文git.py" 149 | > & $venv_python $scriptPath $command $inputArgs 150 | > ``` 151 | 3. 将我们前面新建好的目录添加到系统环境变量`PATH`中。 152 | 类似的具体操作请参阅 [[芙芙工具箱] Q:我该如何添加python到系统PATH环境变量](https://duckduckstudio.github.io/yazicbs.github.io/Tools/Fufu_Tools/wiki/常见问题Q&A/主程序/index.html#add-python-to-path) 153 | 4. 重启你的设备 154 | 5. 验证 155 | 运行以下命令以验证配置: 156 | ```bash 157 | 中文git 版本 158 | ``` 159 | 你应该会看到如下输出: 160 | ``` 161 | 中文Git by 鸭鸭「カモ」 162 | 版本:v2.x 163 | 安装在: D:\...\Chinese_git\中文git.py 164 | git version 2.47.1.windows.1 165 | 166 | ``` 167 | *(版本不一样没关系)* 168 | 169 | ## 如何更新 170 | - 对于`v1.6`及以下版本: 171 | 把你旧的 中文Git 删掉换成新的 中文Git 就行。 172 | - 对于`v1.7`-`v2.3`版本: 173 | - py版 174 | 运行命令`中文git 更新`。 175 | - 打包版 176 | 把你旧的 中文Git 删掉换成新的 中文Git 就行。 177 | - 对于`v2.4`及以上版本: 178 | 运行命令`中文git 更新`。 179 | 180 | > [!TIP] 181 | > 如果 winget 上有可用的新版本的话,你也可以试试这个命令: 182 | > ```bash 183 | > winget update --id DuckStudio.ChineseGit 184 | > ``` 185 | 186 | > [!NOTE] 187 | > 如果你使用`v2.4`及以上版本的**打包版**中文Git,则你可以`cd`到安装目录后运行`.\Pack_Version_Update.exe --version vx.y`手动更新中文Git到指定版本,请将命令中的`vx.y`替换为你需要更新到的版本。 188 | > 请注意,自 v2.4 起,中文git的更新程序默认认为中文git叫`中文git.py`或`中文git.exe`,并不是GitHub发行版上的`Chinese_git.py`或`Chinese_git.exe`。 189 | 190 | ## 可用命令 191 | 192 | 这些是在 中文Git 中可以使用的命令,如果你需要的 Git 命令在这里没有列出...快点[提交Issues](https://github.com/DuckDuckStudio/Chinese_git/issues)听见没!搞快点! 193 | 194 | > [!TIP] 195 | > 这里的可用命令为仓库中最新版本的可用命令,每个Releases的可用命令请查看对应的tag的`README/README_DEV/USER_HANDBOOK`。 196 | > 例如(v1.8的可用命令): 197 | > [https://github.com/DuckDuckStudio/Chinese_git/blob/**v1.8**/USER_HANDBOOK.md#可用命令](https://github.com/DuckDuckStudio/Chinese_git/blob/v1.8/USER_HANDBOOK.md#可用命令) 198 | 199 | | 现在叫啥 | 原来长啥样 | 干啥的 | 200 | |-----------------------|------------------------|--------------------------------------| 201 | | 拉取 | pull | 从远程仓库拉取源码 | 202 | | 推送 | push | 将本地仓库中的提交推送到远程仓库中 | 203 | | 提交 | commit -m | 提交你的更改 | 204 | | 新建分支 | checkout -b | 创建一个全新的分支 | 205 | | 切换分支 / 签出到 | checkout | 我不在这个分支写了!我要去另一个分支写! | 206 | | 合并 | merge | 混合在一起~ | 207 | | 变基 | rebase | 变基合并分支 | 208 | | 暂存 | add | ~~我就只暂存,就是不提交。欸~就是玩~~ 将你的修改暂时存起来以备提交 | 209 | | 状态 | status | 让我看看!看看你是什么状态! | 210 | | 日志 | log | 让我看看!看看你之前都提交了什么玩意 | 211 | | 删除分支 (+确认) | branch -D(-d) | 这个家没有你(删除的分支)的位置了! | 212 | | 远程地址 | remote -v | 你在另一头(远程)叫什么,住哪里(链接) | 213 | | 远程分支 | branch -r | 你在另一头(远程)有谁(哪些分支) | 214 | | 所有分支 | branch -a | 列出仓库的所有分支 | 215 | | 版本 | -v | 如命令所示,显示你使用的 中文Git 版本与 Git 版本 | 216 | | 克隆 | clone | 你的代码就是我的!我的代码还是我的! | 217 | | 图形化日志 | log --graph | 查看图形化的提交日志 | 218 | | 是否忽略 | check-ignore -v | 看看我有没有把你丢掉 | 219 | | 初始化 | init | 新 宠 | 220 | | 本地分支 (+最新提交 +与上游分支关系) | branch (-v/-vv) | 列出所有本地分支(+最新提交 +与上游分支关系) | 221 | | 强推 | push --force | 让我先拉取再推送?我就不! | 222 | | 更名分支 | branch -m | 我不叫旧分支名了,我要叫新分支名! | 223 | | 更新 | / | 我要玩新的中文Git嘛~ | 224 | | 还原 | revert | 还是以前的好 | 225 | | 重置 (+保留更改(默认)/+删除更改) | reset (--mixed/--hard) | 把我推到过去,让我重来一次! | 226 | | 公告 | / | 没人比我更懂中文Git | 227 | | 差异 | diff | 找 不 同 ~ | 228 | | 清理 | clean | 不要了,扔掉 | 229 | | 清理引用 | remote prune | 清除在远程仓库中不存在的分支 | 230 | | 配置 | config | 让我调调 | 231 | 232 | > [!TIP] 233 | > 在 [README_DEV](https://github.com/DuckDuckStudio/Chinese_git/blob/main/README_DEV.md#%E5%8F%AF%E7%94%A8%E5%91%BD%E4%BB%A4) 和 [用户手册](https://github.com/DuckDuckStudio/Chinese_git/blob/main/USER_HANDBOOK.md#%E5%8F%AF%E7%94%A8%E5%91%BD%E4%BB%A4) 中有更详细的说明。~~这里的只是开个玩笑。~~ 234 | 235 | > [!NOTE] 236 | > 对于`提交`命令,如果提交信息带空格请用`"`将提交信息括起来 237 | > 对于`新建分支`命令,该命令会在新建完分支后自动签出到新分支 238 | 239 | ### 示例 240 | 241 | ```bash 242 | $ python 中文git.py 暂存 所有 243 | $ python 中文git.py 提交 更新README 244 | $ python 中文git.py 推送 245 | ``` 246 | 247 | 输出如下: 248 | 249 | ``` 250 | [Powered by 虚空终端] PS D:\...\Chinese_git> python 中文git.py 暂存 所有 251 | 252 | [Powered by 虚空终端] PS D:\...\Chinese_git> python 中文git.py 提交 更新README 253 | [main 11bef48] 更新README 254 | 2 files changed, 200 insertions(+), 1 deletion(-) 255 | create mode 100644 "\344\270\255\346\226\207git.py" 256 | 257 | [Powered by 虚空终端] PS D:\...\Chinese_git> python 中文git.py 推送 258 | 错误: fatal: unable to access 'https://github.com/DuckDuckStudio/Chinese_git.git/': Failure when receiving data from the peer 259 | ``` 260 | ~~可以看到推送失败了(倒~~ 261 | 262 | ## 已知问题 263 | 264 | 请见[Issues页](https://github.com/DuckDuckStudio/Chinese_git/issues)。 265 | -------------------------------------------------------------------------------- /README_DEV.md: -------------------------------------------------------------------------------- 1 | # 中文Git 2 | 3 | [![项目展示图](https://duckduckstudio.github.io/yazicbs.github.io/Tools/chinese_git/photos/展示图.png)](https://duckduckstudio.github.io/yazicbs.github.io/Tools/chinese_git/) 4 | 5 | 项目网站:[[点我前往]](https://duckduckstudio.github.io/yazicbs.github.io/Tools/chinese_git/) 6 | 7 | > [!NOTE] 8 | > 想要贡献更新这些文档以及中文Git项目?请查看[CONTRIBUTING](https://github.com/DuckDuckStudio/Chinese_git/blob/main/CONTRIBUTING.md)文件。感谢您的支持!您的支持是我们持续维护的动力! 9 | > 项目遵循 GPL-2.0 许可协议。 10 | 11 | ## 项目介绍 12 | 13 | 中文Git是一个简单的工具,旨在使不熟悉英文的用户更轻松地使用Git。 14 | 通过中文Git,您可以使用中文命令执行常见的Git操作,无需再背诵英文指令! 15 | 16 | ## 如何获取 17 | 请前往[仓库发行版页](https://github.com/DuckDuckStudio/Chinese_git/releases/)下载最新版中文Git。 18 | 如果你已有中文Git,只是希望更新,请查看条目[如何更新中文Git](#如何更新)。 19 | 20 | ### 使用 winget 21 | 你也可以使用 _winget_ 来获取中文Git,请留意支持 _winget_ 获取的版本。 22 | 使用以下命令安装: 23 | ```bash 24 | winget install DuckStudio.ChineseGit 25 | ``` 26 | 输出类似这样: 27 | ![1718315176839](https://duckduckstudio.github.io/Chinese_git/image/README/1718315176839.png) 28 | 29 | > [!TIP] 30 | > 使用 _winget_ 获取的不用配置Python。 31 | 32 | > [!TIP] 33 | > 设支持的版本号为n,则 $2.4 \leqslant n \leqslant 2.10$ 34 | > winget会错误的将版本2.10显示为版本2.1,更多信息请见[microsoft/winget-pkgs#196868](https://github.com/microsoft/winget-pkgs/issues/196868) 35 | 36 | ## 项目依赖 37 | 38 | 在使用中文Git之前,请确保您满足以下依赖,否则中文Git将无法正常工作。 39 | 40 | ### Python 41 | 42 | 请确保您的系统已配置Python环境,并已安装所需库。 43 | 运行以下命令检查Python版本: 44 | 45 | ```bash 46 | python --version 47 | ``` 48 | 49 | 你可能会看到类似这样的输出: 50 | 51 | ``` 52 | C:\Users\user_name>python --version 53 | Python 3.12.0 54 | ``` 55 | 56 | 运行以下命令以安装所需库: 57 | 58 | ```bash 59 | pip install -r requirements.txt 60 | ``` 61 | 62 | 如果无法运行命令,请参考芙芙工具箱文档中的[[Q:我该如何添加Python到系统PATH环境变量]](https://duckduckstudio.github.io/yazicbs.github.io/Tools/Fufu_Tools/wiki/%E5%B8%B8%E8%A7%81%E9%97%AE%E9%A2%98Q&A/%E4%B8%BB%E7%A8%8B%E5%BA%8F/#add-python-to-path) 63 | 64 | ### Git 65 | 66 | 请确保您的系统已经配置了Git。 67 | Git是一个版本管理工具...(省略一大段介绍,您也知道的)...在使用中文Git之前,必须配置好Git。 68 | 运行以下命令检查Git版本: 69 | 70 | ```bash 71 | git -v 72 | ``` 73 | 74 | 如果输出类似于以下内容,则说明无需进行更改: 75 | 76 | ``` 77 | git version 2.47.1.windows.1 78 | ``` 79 | 80 | 如果无法运行命令,请[下载Git](https://git-scm.com/downloads)。如果已经下载了Git但无法运行命令,请将Git添加到环境变量中。(配置方法与Python相同,请参考官方文档[https://git-scm.com/book/zh/v2](https://git-scm.com/book/zh/v2%EF%BC%89)) 81 | 82 | > [!NOTE] 83 | > 即使使用打包版,此项也是必须的。 84 | 85 | ## 如何执行命令 86 | 87 | 通常情况下,您可以使用以下命令执行中文Git: 88 | 89 | ```bash 90 | python 中文git.py 命令 91 | ``` 92 | 93 | 如果您使用的是已打包好的中文Git,则使用以下命令: 94 | 95 | ```bash 96 | path\to\中文git.exe 命令 97 | ``` 98 | 99 | > [!NOTE] 100 | > 在使用 python 运行 中文Git 时,请确保 中文git.py 的路径正确!可以使用相对路径。 101 | > 在使用 打包后的中文Git.exe 运行时,请使用绝对路径 102 | 103 | ### 优化 104 | 每次都要输这么多的命令...烦死了。 105 | 我们来优化一下命令吧! 106 | 107 | #### 打包版 108 | 1. 将程序目录添加到系统环境变量`PATH`中。 109 | 类似的具体操作请参阅 [[芙芙工具箱] Q:我该如何添加python到系统PATH环境变量](https://duckduckstudio.github.io/yazicbs.github.io/Tools/Fufu_Tools/wiki/常见问题Q&A/主程序/index.html#add-python-to-path) 110 | 2. 重启你的设备 111 | 3. 验证 112 | 运行以下命令以验证配置: 113 | ```bash 114 | 中文git 版本 115 | ``` 116 | 你应该会看到如下输出: 117 | ``` 118 | 中文Git by 鸭鸭「カモ」 119 | 版本:v2.x 120 | 安装在: D:\...\Chinese_git\中文git.exe 121 | git version 2.47.1.windows.1 122 | 123 | ``` 124 | *(版本不一样没关系)* 125 | 126 | #### 源码 127 | > [!WARNING] 128 | > 此方法可能仅对只传入一个参数时才有效,更多信息请见[DuckDuckStudio/Fufu_Tools#97](https://github.com/DuckDuckStudio/Fufu_Tools/issues/97) 129 | 130 | 1. 新建一个文件夹,名称随意(这里假设叫`Chinese_git_Script`。~~很复杂也没事,反正命令用不到~~) 131 | 2. 在文件夹中新建一个叫`中文git.ps1`的脚本,并在脚本中添加以下内容: 132 | - 对于 **py版** : 133 | ```powershell 134 | param( 135 | [string]$command, 136 | [string[]]$inputArgs 137 | ) 138 | 139 | python "D:\中文Git的完整路径\中文git.py" $command $inputArgs 140 | ``` 141 | > [!WARNING] 142 | > 如果你创建了虚拟Python环境,请将`python`改为虚拟环境中的`python.exe`。 143 | > 示例: 144 | > ```powershell 145 | > param( 146 | > [string]$command, 147 | > [string[]]$inputArgs 148 | > ) 149 | > $venv_python = "D:\虚拟环境路径\Scripts\python.exe" 150 | > $scriptPath = "D:\完整路径\中文git.py" 151 | > & $venv_python $scriptPath $command $inputArgs 152 | > ``` 153 | 3. 将我们前面新建好的目录添加到系统环境变量`PATH`中。 154 | 类似的具体操作请参阅 [[芙芙工具箱] Q:我该如何添加python到系统PATH环境变量](https://duckduckstudio.github.io/yazicbs.github.io/Tools/Fufu_Tools/wiki/常见问题Q&A/主程序/index.html#add-python-to-path) 155 | 4. 重启你的设备 156 | 5. 验证 157 | 运行以下命令以验证配置: 158 | ```bash 159 | 中文git 版本 160 | ``` 161 | 你应该会看到如下输出: 162 | ``` 163 | 中文Git by 鸭鸭「カモ」 164 | 版本:v2.x 165 | 安装在: D:\...\Chinese_git\中文git.py 166 | git version 2.47.1.windows.1 167 | 168 | ``` 169 | *(版本不一样没关系)* 170 | 171 | ## 如何更新 172 | - 对于`v1.6`及以下版本: 173 | 把你旧的 中文Git 删掉换成新的 中文Git 就行。 174 | - 对于`v1.7`-`v2.3`版本: 175 | - py版 176 | 运行命令`中文git 更新`。 177 | - 打包版 178 | 把你旧的 中文Git 删掉换成新的 中文Git 就行。 179 | - 对于`v2.4`及以上版本: 180 | 运行命令`中文git 更新`。 181 | 182 | > [!TIP] 183 | > 如果 winget 上有可用的新版本的话,你也可以试试这个命令: 184 | > ```bash 185 | > winget update --id DuckStudio.ChineseGit 186 | > ``` 187 | 188 | > [!NOTE] 189 | > 如果你使用`v2.4`及以上版本的**打包版**中文Git,则你可以`cd`到安装目录后运行`.\Pack_Version_Update.exe --version vx.y`手动更新中文Git到指定版本,请将命令中的`vx.y`替换为你需要更新到的版本。 190 | > 请注意,自 v2.4 起,中文git的更新程序默认认为中文git叫`中文git.py`或`中文git.exe`,并不是GitHub发行版上的`Chinese_git.py`或`Chinese_git.exe`。 191 | 192 | ## 可用命令 193 | 194 | 以下是中文Git支持的命令列表。如果您需要的Git命令不在列表中,请[提交Issues](https://github.com/DuckDuckStudio/Chinese_git/issues)告诉我们! 195 | 196 | > [!TIP] 197 | > 这里的可用命令为仓库中最新版本的可用命令,每个Releases的可用命令请查看对应的tag的`README/README_DEV/USER_HANDBOOK`。 198 | > 例如(v1.8的可用命令): 199 | > [https://github.com/DuckDuckStudio/Chinese_git/blob/**v1.8**/USER_HANDBOOK.md#可用命令](https://github.com/DuckDuckStudio/Chinese_git/blob/v1.8/USER_HANDBOOK.md#可用命令) 200 | 201 | | 在中文Git中的命令 | 在Git中的命令 | 用途 | 202 | |-----------------------|------------------------|---------------------------------------------------------------------------| 203 | | 拉取 | pull | 从远程仓库拉取源码 ([git文档](https://git-scm.com/docs/git-pull/zh_HANS-CN)) | 204 | | 推送 | push | 将本地仓库中的提交推送到远程仓库中 ([git文档](https://git-scm.com/docs/git-push/zh_HANS-CN)) | 205 | | 提交 | commit -m | 提交您的更改 | 206 | | 新建分支 | checkout -b | 创建一个全新的分支 | 207 | | 切换分支 / 签出到 | checkout | 切换到另一个分支 ([git文档](https://git-scm.com/docs/git-checkout/zh_HANS-CN)) | 208 | | 合并 | merge | 合并分支(可能会产生冲突) ([git文档](https://git-scm.com/docs/git-merge/zh_HANS-CN)) | 209 | | 变基 | rebase | 变基合并分支(可能会产生冲突) ([git文档](https://git-scm.com/docs/git-rebase/zh_HANS-CN)) | 210 | | 暂存 | add | 暂存您的修改以备提交 ([git文档](https://git-scm.com/docs/git-add/zh_HANS-CN)) | 211 | | 状态 | status | 查看当前仓库状态 ([git文档](https://git-scm.com/docs/git-status/zh_HANS-CN)) | 212 | | 日志 | log | 查看提交日志 ([git文档](https://git-scm.com/docs/git-log/zh_HANS-CN)) | 213 | | 删除分支 (+确认) | branch -D(-d) | 删除指定分支(+合并检查) | 214 | | 远程地址 | remote -v | 查看远程仓库地址 | 215 | | 远程分支 | branch -r | 查看远程仓库的分支列表 | 216 | | 所有分支 | branch -a | 查看仓库的所有分支列表 | 217 | | 版本 | -v | 显示中文Git版本和Git版本 | 218 | | 克隆 | clone | 克隆远程仓库到本地 ([git文档](https://git-scm.com/docs/git-clone/zh_HANS-CN)) | 219 | | 图形化日志 | log --graph | 查看图形化的提交日志 | 220 | | 是否忽略 | check-ignore -v | 检查文件/文件夹是否被`.gitignore`忽略 | 221 | | 初始化 | init | 初始化一个新的 Git 仓库 ([git文档](https://git-scm.com/docs/git-init/zh_HANS-CN)) | 222 | | 本地分支 (+最新提交 +与上游分支关系) | branch (-v/-vv) | 列出所有本地分支(+最新提交 +与上游分支关系) | 223 | | 强推 | push --force | 将本地仓库的提交**强制**推送到远程仓库中 | 224 | | 更名分支 | branch -m | 修改本地仓库分支名 | 225 | | 更新 | / | 更新 中文Git | 226 | | 还原 | revert | 还原某些现有提交 ([git文档](https://git-scm.com/docs/git-revert/zh_HANS-CN)) | 227 | | 重置 (+保留更改(默认)/+删除更改) | reset (--mixed/--hard) | 移动 HEAD 指针以及修改暂存区和工作目录中的文件状态 | 228 | | 公告 | / | 显示中文Git版本的最新公告 | 229 | | 差异 | diff | 显示提交和工作区等变化 ([git文档](https://git-scm.com/docs/git-diff/zh_HANS-CN)) | 230 | | 清理引用 | remote prune | 清除在远程仓库中不存在的分支 | 231 | | 清理 | clean | 删除工作目录树中未跟踪的文件 ([git文档](https://git-scm.com/docs/git-clean/zh_HANS-CN)) | 232 | | 配置 | config | 获取和设置仓库或全局选项 ([git文档](https://git-scm.com/docs/git-config/zh_HANS-CN)) | 233 | 234 | > [!NOTE] 235 | > 对于`提交`命令,如果提交信息带空格请用`"`将提交信息括起来 236 | > 对于`新建分支`命令,该命令会在新建完分支后自动签出到新分支 237 | 238 | ### 示例 239 | 240 | ```bash 241 | $ python 中文git.py 暂存 所有 242 | $ python 中文git.py 提交 更新README 243 | $ python 中文git.py 推送 244 | ``` 245 | 246 | 输出如下: 247 | 248 | ``` 249 | [Power by 虚空终端] PS D:\...\Chinese_git> python 中文git.py 暂存 所有 250 | 251 | [Power by 虚空终端] PS D:\...\Chinese_git> python 中文git.py 提交 更新README 252 | [main 11bef48] 更新README 253 | 2 files changed, 200 insertions(+), 1 deletion(-) 254 | create mode 100644 "\344\270\255\346\226\207git.py" 255 | 256 | [Power by 虚空终端] PS D:\...\Chinese_git> python 中文git.py 推送 257 | 错误: fatal: unable to access 'https://github.com/DuckDuckStudio/Chinese_git.git/': Failure when receiving data from the peer 258 | ``` 259 | 260 | ## 已知问题 261 | 262 | 请见[Issues页](https://github.com/DuckDuckStudio/Chinese_git/issues)。 263 | -------------------------------------------------------------------------------- /USER_HANDBOOK.md: -------------------------------------------------------------------------------- 1 | # 中文Git 用户手册 2 | 3 | [![项目展示图](https://duckduckstudio.github.io/yazicbs.github.io/Tools/chinese_git/photos/展示图.png)](https://duckduckstudio.github.io/yazicbs.github.io/Tools/chinese_git/) 4 | 5 | 项目网站:[[点我前往]](https://duckduckstudio.github.io/yazicbs.github.io/Tools/chinese_git/) 6 | 7 | 这是 中文Git 的用户手册,你可以在这里找到一些有关 中文Git 的使用方法。 8 | 9 | ## 如何获取 10 | 请前往[仓库发行版页](https://github.com/DuckDuckStudio/Chinese_git/releases/)下载最新版中文Git。 11 | 如果你已有中文Git,只是希望更新,请查看条目[如何更新中文Git](#如何更新)。 12 | 13 | ### 使用 winget 14 | 你也可以使用 _winget_ 来获取中文Git,请留意支持 _winget_ 获取的版本。 15 | 使用以下命令安装: 16 | ```bash 17 | winget install DuckStudio.ChineseGit 18 | ``` 19 | 输出类似这样: 20 | ![1718315176839](https://duckduckstudio.github.io/Chinese_git/image/README/1718315176839.png) 21 | 22 | > [!TIP] 23 | > 使用 _winget_ 获取的不用配置Python。 24 | 25 | > [!TIP] 26 | > 设支持的版本号为n,则 $2.4 \leqslant n \leqslant 2.10$ 27 | > winget会错误的将版本2.10显示为版本2.1,更多信息请见[microsoft/winget-pkgs#196868](https://github.com/microsoft/winget-pkgs/issues/196868) 28 | 29 | ## 依赖 30 | 31 | ### Git 32 | 33 | 在使用 中文Git 前,你必须先配置好 Git 。中文Git 只是一个帮你用中文命令来执行 Git 命令的工具,不能代替 Git 。 34 | 运行以下命令以检查: 35 | 36 | ```bash 37 | git -v 38 | ``` 39 | 40 | 如果输出类似于以下内容,则说明无需进行更改: 41 | 42 | ``` 43 | git version 2.47.1.windows.1 44 | ``` 45 | 46 | 如果无法执行命令: 47 | * 未下载 Git 48 | 请 [下载Git](https://git-scm.com/downloads) 。 49 | * 已下载 Git 50 | 请 **将Git添加到环境变量** (方法可自行百度,添加完后若未起效请重启您的设备) 51 | 52 | ### Python 53 | 54 | 如果你希望从源码 (`中文git.py`) 使用 中文Git ,请先配置好 Python。 55 | 56 | 运行以下命令以检查: 57 | 58 | ```bash 59 | python --version 60 | ``` 61 | 62 | 你可能会看到类似这样的输出: 63 | 64 | ``` 65 | C:\Users\user_name>python --version 66 | Python 3.12.0 67 | ``` 68 | 69 | 运行以下命令以安装所需库: 70 | 71 | ```bash 72 | pip install -r requirements.txt 73 | ``` 74 | 75 | 如果无法执行命令: 76 | * 未下载 Python 解释器 77 | 请 [下载Python](https://www.python.org/downloads/) 。 78 | * 已下载 Python 解释器 79 | 请 **将Python添加到环境变量** (具体请参阅[[Q:我该如何添加Python到系统PATH环境变量]](https://duckduckstudio.github.io/yazicbs.github.io/Tools/Fufu_Tools/wiki/%E5%B8%B8%E8%A7%81%E9%97%AE%E9%A2%98Q&A/%E4%B8%BB%E7%A8%8B%E5%BA%8F/#add-python-to-path)) 80 | 81 | 在您配置完这些依赖后,您应该就可以正常的使用 中文Git 了。 82 | 目前来看,你似乎可以使用 中文Git 的Python源码来在 Linux 和 macos 系统上运行 中文Git ,但是我没试过,所以不能保证稳定性。 83 | 84 | ## 如何使用 85 | ### 优化 86 | 每次都要输这么多的命令...烦死了。 87 | 我们来优化一下命令吧! 88 | 89 | #### 打包版 90 | 1. 将程序目录添加到系统环境变量`PATH`中。 91 | 类似的具体操作请参阅 [[芙芙工具箱] Q:我该如何添加python到系统PATH环境变量](https://duckduckstudio.github.io/yazicbs.github.io/Tools/Fufu_Tools/wiki/常见问题Q&A/主程序/index.html#add-python-to-path) 92 | 2. 重启你的设备 93 | 3. 验证 94 | 运行以下命令以验证配置: 95 | ```bash 96 | 中文git 版本 97 | ``` 98 | 你应该会看到如下输出: 99 | ``` 100 | 中文Git by 鸭鸭「カモ」 101 | 版本:v2.x 102 | 安装在: D:\...\Chinese_git\中文git.exe 103 | git version 2.47.1.windows.1 104 | 105 | ``` 106 | *(版本不一样没关系)* 107 | 108 | #### 源码 109 | > [!WARNING] 110 | > 此方法可能仅对只传入一个参数时才有效,更多信息请见[DuckDuckStudio/Fufu_Tools#97](https://github.com/DuckDuckStudio/Fufu_Tools/issues/97) 111 | 112 | 1. 新建一个文件夹,名称随意(这里假设叫`Chinese_git_Script`。~~很复杂也没事,反正命令用不到~~) 113 | 2. 在文件夹中新建一个叫`中文git.ps1`的脚本,并在脚本中添加以下内容: 114 | - 对于 **py版** : 115 | ```powershell 116 | param( 117 | [string]$command, 118 | [string[]]$inputArgs 119 | ) 120 | 121 | python "D:\中文Git的完整路径\中文git.py" $command $inputArgs 122 | ``` 123 | > [!WARNING] 124 | > 如果你创建了虚拟Python环境,请将`python`改为虚拟环境中的`python.exe`。 125 | > 示例: 126 | > ```powershell 127 | > param( 128 | > [string]$command, 129 | > [string[]]$inputArgs 130 | > ) 131 | > $venv_python = "D:\虚拟环境路径\Scripts\python.exe" 132 | > $scriptPath = "D:\完整路径\中文git.py" 133 | > & $venv_python $scriptPath $command $inputArgs 134 | > ``` 135 | 3. 将我们前面新建好的目录添加到系统环境变量`PATH`中。 136 | 类似的具体操作请参阅 [[芙芙工具箱] Q:我该如何添加python到系统PATH环境变量](https://duckduckstudio.github.io/yazicbs.github.io/Tools/Fufu_Tools/wiki/常见问题Q&A/主程序/index.html#add-python-to-path) 137 | 4. 重启你的设备 138 | 5. 验证 139 | 运行以下命令以验证配置: 140 | ```bash 141 | 中文git 版本 142 | ``` 143 | 你应该会看到如下输出: 144 | ``` 145 | 中文Git by 鸭鸭「カモ」 146 | 版本:v2.x 147 | 安装在: D:\...\Chinese_git\中文git.py 148 | git version 2.47.1.windows.1 149 | 150 | ``` 151 | *(版本不一样没关系)* 152 | 153 | 这样,你就可以不用在每次执行 中文Git 时都使用完整路径了,您只需使用以下代码即可: 154 | ```powershell 155 | 中文git 命令 156 | ``` 157 | 请将`命令`替换为你需要执行的 中文Git 的命令,详细可用命令请查看下方的 [可用命令](#可用命令) 条目 158 | 159 | ## 可用命令 160 | 以下是 中文Git 目前的可用命令,如需添加更多命令请提交 Issues 或者 PR 161 | 关于如何贡献,请查看[CONTRIBUTING](https://github.com/DuckDuckStudio/Chinese_git/blob/main/CONTRIBUTING.md)文件。 162 | 163 | > [!TIP] 164 | > 这里的可用命令为仓库中最新版本的可用命令,每个Releases的可用命令请查看对应的tag的`README/README_DEV/USER_HANDBOOK`。 165 | > 例如(v1.8的可用命令): 166 | > [https://github.com/DuckDuckStudio/Chinese_git/blob/**v1.8**/USER_HANDBOOK.md#可用命令](https://github.com/DuckDuckStudio/Chinese_git/blob/v1.8/USER_HANDBOOK.md#可用命令) 167 | 168 | | 在中文Git中的命令 | 在Git中的命令 | 用途 | 169 | |-----------------------|------------------------|---------------------------------------------------------------------------| 170 | | 拉取 | pull | 从远程仓库拉取源码 ([git文档](https://git-scm.com/docs/git-pull/zh_HANS-CN)) | 171 | | 推送 | push | 将本地仓库中的提交推送到远程仓库中 ([git文档](https://git-scm.com/docs/git-push/zh_HANS-CN)) | 172 | | 提交 | commit -m | 提交您的更改 | 173 | | 新建分支 | checkout -b | 创建一个全新的分支 | 174 | | 切换分支 / 签出到 | checkout | 切换到另一个分支 ([git文档](https://git-scm.com/docs/git-checkout/zh_HANS-CN)) | 175 | | 合并 | merge | 合并分支(可能会产生冲突) ([git文档](https://git-scm.com/docs/git-merge/zh_HANS-CN)) | 176 | | 变基 | rebase | 变基合并分支(可能会产生冲突) ([git文档](https://git-scm.com/docs/git-rebase/zh_HANS-CN)) | 177 | | 暂存 | add | 暂存您的修改以备提交 ([git文档](https://git-scm.com/docs/git-add/zh_HANS-CN)) | 178 | | 状态 | status | 查看当前仓库状态 ([git文档](https://git-scm.com/docs/git-status/zh_HANS-CN)) | 179 | | 日志 | log | 查看提交日志 ([git文档](https://git-scm.com/docs/git-log/zh_HANS-CN)) | 180 | | 删除分支 (+确认) | branch -D(-d) | 删除指定分支(+合并检查) | 181 | | 远程地址 | remote -v | 查看远程仓库地址 | 182 | | 远程分支 | branch -r | 查看远程仓库的分支列表 | 183 | | 所有分支 | branch -a | 查看仓库的所有分支列表 | 184 | | 版本 | -v | 显示中文Git版本和Git版本 | 185 | | 克隆 | clone | 克隆远程仓库到本地 ([git文档](https://git-scm.com/docs/git-clone/zh_HANS-CN)) | 186 | | 图形化日志 | log --graph | 查看图形化的提交日志 | 187 | | 是否忽略 | check-ignore -v | 检查文件/文件夹是否被`.gitignore`忽略 | 188 | | 初始化 | init | 初始化一个新的 Git 仓库 ([git文档](https://git-scm.com/docs/git-init/zh_HANS-CN)) | 189 | | 本地分支 (+最新提交 +与上游分支关系) | branch (-v/-vv) | 列出所有本地分支(+最新提交 +与上游分支关系) | 190 | | 强推 | push --force | 将本地仓库的提交**强制**推送到远程仓库中 | 191 | | 更名分支 | branch -m | 修改本地仓库分支名 | 192 | | 更新 | / | 更新 中文Git | 193 | | 还原 | revert | 还原某些现有提交 ([git文档](https://git-scm.com/docs/git-revert/zh_HANS-CN)) | 194 | | 重置 (+保留更改(默认)/+删除更改) | reset (--mixed/--hard) | 移动 HEAD 指针以及修改暂存区和工作目录中的文件状态 | 195 | | 公告 | / | 显示中文Git版本的最新公告 | 196 | | 差异 | diff | 显示提交和工作区等变化 ([git文档](https://git-scm.com/docs/git-diff/zh_HANS-CN)) | 197 | | 清理引用 | remote prune origin | 清除在远程仓库中不存在的分支 | 198 | | 清理 | clean | 删除工作目录树中未跟踪的文件 ([git文档](https://git-scm.com/docs/git-clean/zh_HANS-CN)) | 199 | | 配置 | config | 获取和设置仓库或全局选项 ([git文档](https://git-scm.com/docs/git-config/zh_HANS-CN)) | 200 | 201 | > [!NOTE] 202 | > 对于`提交`命令,如果提交信息带空格请用`"`将提交信息括起来 203 | > 对于`新建分支`命令,该命令会在新建完分支后自动签出到新分支 204 | 205 | ## 如何更新 206 | - 对于`v1.6`及以下版本: 207 | 把你旧的 中文Git 删掉换成新的 中文Git 就行。 208 | - 对于`v1.7`-`v2.3`版本: 209 | - py版 210 | 运行命令`中文git 更新`。 211 | - 打包版 212 | 把你旧的 中文Git 删掉换成新的 中文Git 就行。 213 | - 对于`v2.4`及以上版本: 214 | 运行命令`中文git 更新`。 215 | 216 | > [!TIP] 217 | > 如果 winget 上有可用的新版本的话,你也可以试试这个命令: 218 | > ```bash 219 | > winget update --id DuckStudio.ChineseGit 220 | > ``` 221 | 222 | > [!NOTE] 223 | > 如果你使用`v2.4`及以上版本的**打包版**中文Git,则你可以`cd`到安装目录后运行`.\Pack_Version_Update.exe --version vx.y`手动更新中文Git到指定版本,请将命令中的`vx.y`替换为你需要更新到的版本。 224 | 225 | ## 配置文件说明 226 | 默认配置文件 *(v2.9)* 如下: 227 | ```json 228 | { 229 | "information": { 230 | "version": "v2.9" 231 | }, 232 | "application": { 233 | "notice": { 234 | "time": "", 235 | "level": "", 236 | "content": "" 237 | }, 238 | "run": { 239 | "auto_check_update": "True", 240 | "auto_get_notice": "True" 241 | } 242 | } 243 | } 244 | ``` 245 | 246 | - `information` → 关于程序与配置文件的信息 247 | - `version` → 配置文件对应的程序版本 *(暂未使用)* 248 | - `application` → 关于程序的设置 249 | - `notice` → 关于公告的信息 *(暂未使用)* 250 | - `time` → 最新公告的发布时间 *(暂未使用)* 251 | - `level` → 最新公告的等级 *(暂未使用)* 252 | - `content` → 最新公告的内容 *(暂未使用)* 253 | - `run` → 关于运行时的设置 254 | - `auto_check_update` → 是否在每次执行完命令后都检查更新 (默认为`True`,不为`True`时不自动检查) - 禁用该功能可大幅提升运行速度,但将失去自动更新检查功能 255 | - `auto_get_notice` → 是否在每次执行完命令后都获取最新公告 (默认为`True`,不为`True`时不自动获取) - 禁用该功能可大幅提升运行速度,但将失去自动公告获取 256 | 257 | ## 已知问题 258 | 259 | 请见[Issues页](https://github.com/DuckDuckStudio/Chinese_git/issues)。 260 | 261 | ## 关于编码 262 | 中文Git 的所有项目文件源码以及发行版文件均使用 UTF-8 编码,如出现乱码请使用 UTF-8 编码而非简体中文系统默认的 GBK 编码。 263 | -------------------------------------------------------------------------------- /config.json: -------------------------------------------------------------------------------- 1 | { 2 | "information": { 3 | "version": "v3.3" 4 | }, 5 | "application": { 6 | "notice": { 7 | "time": "", 8 | "level": "", 9 | "content": "" 10 | }, 11 | "run": { 12 | "auto_check_update": "True", 13 | "auto_get_notice": "True" 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /docs/image/README/1718315176839.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DuckDuckStudio/Chinese_git/f6927361880c34d8de7a58ddc2e361fa56d80069/docs/image/README/1718315176839.png -------------------------------------------------------------------------------- /ico.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DuckDuckStudio/Chinese_git/f6927361880c34d8de7a58ddc2e361fa56d80069/ico.ico -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | requests==2.32.3 2 | colorama==0.4.6 3 | -------------------------------------------------------------------------------- /zh-tw/中文git-pack.py: -------------------------------------------------------------------------------- 1 | import subprocess 2 | import sys 3 | import os 4 | 5 | script_path = os.path.dirname(__file__) 6 | full_path = os.path.join(script_path, "中文git.exe") 7 | 8 | def git_command(command, *args): 9 | git_command_mapping = { 10 | "拉取": "pull", 11 | "推送": "push", 12 | "提交": "commit", 13 | "新建分支": "checkout -b", 14 | "切換分支": "checkout", 15 | "合併": "merge", 16 | "暫存": "add", 17 | "查看狀態": "status", 18 | "查看日誌": "log", 19 | "重置": "reset", 20 | "刪除分支": "branch -D", 21 | "遠端地址": "remote -v", 22 | "遠端更新": "remote update", 23 | "查看遠端分支": "branch -r", 24 | "版本": "-v", 25 | "刪除提交": "reset --hard HEAD~", 26 | "克隆": "clone", 27 | "配置": "config", 28 | "簽出到": "checkout", 29 | "查看圖形化日誌": "log --graph", 30 | "是否忽略": "check-ignore -v", 31 | "初始化": "init", 32 | "查看本地分支": "branch", 33 | # 可根據需要添加更多映射 34 | } 35 | git_config_subcommands = { 36 | "全局": "--global", 37 | "系統": "--system" 38 | } 39 | if command == "幫助": 40 | print("使用方法:") 41 | print(full_path, " <中文指令> [參數]") 42 | print("即:", full_path, "<你想幹什麼> [具體要啥]") 43 | print("支持的中文指令:") 44 | for cmd in git_command_mapping: 45 | print("-", cmd) 46 | print("詳細支持命令請查看README_DEV文件:https://github.com/DuckDuckStudio/Chinese_git/blob/main/README_DEV.md#可用命令") 47 | return 48 | 49 | git_command = git_command_mapping.get(command) 50 | if git_command: 51 | try: 52 | if command == "提交": 53 | if not args: 54 | commit_message = input("請輸入提交信息: ") 55 | result = subprocess.run(['git', git_command, '-m', commit_message], capture_output=True, text=True) 56 | else: 57 | result = subprocess.run(['git', git_command, '-m', args[0]], capture_output=True, text=True) 58 | elif command == "暫存": 59 | if args and args[0] == "所有": 60 | result = subprocess.run(['git', 'add', '.'], capture_output=True, text=True) 61 | elif not args: 62 | print("你要暫存什麼你沒告訴我啊") 63 | else: 64 | result = subprocess.run(['git', 'add'] + list(args), capture_output=True, text=True) 65 | elif command == "切換分支" or command == "簽出到": 66 | if not args: 67 | branch = input("請輸入需要切換的分支:") 68 | result = subprocess.run(['git', git_command, branch], capture_output=True, text=True) 69 | elif len(args) == 1: 70 | result = subprocess.run(['git', git_command] + list(args), capture_output=True, text=True) 71 | else: 72 | print("多餘的參數") 73 | elif command == "新建分支": 74 | if not args: 75 | new_branch = input("請輸入新分支名稱: ") 76 | result = subprocess.run(['git', git_command, new_branch], capture_output=True, text=True) 77 | elif len(args) == 1: 78 | result = subprocess.run(['git', git_command] + list(args), capture_output=True, text=True) 79 | else: 80 | print("多餘的參數") 81 | elif command == "刪除分支": 82 | if not args: 83 | print("刪除分支命令需要指定要刪除的分支名稱。") 84 | elif len(args) > 2: 85 | print("多餘的參數") 86 | return 87 | elif len(args) == 2 and args[1] == "+確認": 88 | git_command = "git branch -d" 89 | else: 90 | print("無效的附加參數") 91 | return 92 | result = subprocess.run(['git', git_command, args[0]], capture_output=True, text=True) 93 | elif command == "版本": 94 | print("中文Git by 鸭鸭「カモ」") 95 | print("版本:v1.5-pack") 96 | print("繁體中文翻譯版") 97 | print("安裝在:", full_path) 98 | result = subprocess.run(['git', git_command] + list(args), capture_output=True, text=True) 99 | elif command == "刪除提交": 100 | if not args: 101 | print("請輸入要刪除的提交類型(最新提交/倒數第n個提交/具體某個提交)。") 102 | else: 103 | if args[0] == "最新提交": 104 | result = subprocess.run(['git', git_command, 'HEAD~1'], capture_output=True, text=True) 105 | elif args[0].startswith("倒數第"): 106 | try: 107 | num = int(args[0][3:]) 108 | result = subprocess.run(['git', git_command, f'HEAD~{num}'], capture_output=True, text=True) 109 | except ValueError: 110 | print("參數錯誤,請輸入倒數第n個提交,n為正整數。") 111 | return 112 | else: 113 | result = subprocess.run(['git', git_command, args[0]], capture_output=True, text=True) 114 | elif command == "克隆": 115 | if not args: 116 | repository = input("請輸入遠程倉庫鏈接(以.git結尾):") 117 | result = subprocess.run(['git', git_command, repository], capture_output=True, text=True) 118 | else: 119 | result = subprocess.run(['git', git_command] + list(args), capture_output=True, text=True) 120 | elif command == "配置": 121 | if not args: 122 | print("配置命令需要指定配置選項和值。") 123 | elif len(args) == 1: 124 | print("配置命令需要指定配置值。") 125 | else: 126 | config_option = args[0] 127 | config_value = args[1] 128 | config_subcommand = None 129 | # 检查是否存在配置范围 130 | if len(args) == 3: 131 | config_subcommand = args[2] 132 | if config_subcommand not in git_config_subcommands: 133 | print("配置範圍錯誤,可選範圍為:全局、系統。") 134 | return 135 | git_config_command = ['git', git_command, config_option, config_value] 136 | if config_subcommand:# 如果存在配置范围 137 | git_config_command.insert(2, git_config_subcommands[config_subcommand]) 138 | result = subprocess.run(git_config_command, capture_output=True, text=True) 139 | elif command == "是否忽略": 140 | if not args: 141 | file = input("請輸入需要檢查的文件/文件夾:") 142 | result = subprocess.run(['git', git_command, file], capture_output=True, text=True) 143 | else: 144 | result = subprocess.run(['git', git_command] + list(args), capture_output=True, text=True) 145 | elif command == "查看本地分支": 146 | if len(args) > 2: 147 | print("多餘的參數") 148 | return 149 | elif args[0] == "+最後提交": 150 | git_command = "branch -v" 151 | elif (args[0] == "+最後提交" and args[1] == "+與上游分支關係") or (args[0] == "+與上游分支關係" and args[1] == "+最后提交"): 152 | git_command = "branch -vv" 153 | else: 154 | print("無效的參數") 155 | result = subprocess.run(['git', git_command], capture_output=True, text=True) 156 | elif command == "合併": 157 | if not args: 158 | branch = input("請輸入需要合併到當前分支的分支:") 159 | result = subprocess.run(['git', git_command, branch], capture_output=True, text=True) 160 | else: 161 | result = subprocess.run(['git', git_command] + list(args), capture_output=True, text=True) 162 | else: 163 | result = subprocess.run(['git', git_command] + list(args), capture_output=True, text=True) 164 | 165 | if result.returncode == 0: 166 | print(result.stdout) 167 | else: 168 | print("錯誤:", result.stderr) 169 | except Exception as e: 170 | print("執行git命令時出錯:", e) 171 | else: 172 | print("不支持的git命令:", command) 173 | 174 | if __name__ == "__main__": 175 | if len(sys.argv) > 1: 176 | git_command(sys.argv[1], *sys.argv[2:]) 177 | else: 178 | print("使用方法:") 179 | print(full_path, " <中文指令> [參數]") 180 | print("即:", full_path, "<你想幹什麼> [具體要啥]") 181 | -------------------------------------------------------------------------------- /zh-tw/中文git.py: -------------------------------------------------------------------------------- 1 | import subprocess 2 | import sys 3 | import os 4 | 5 | script_path = os.path.dirname(__file__) 6 | full_path = os.path.join(script_path, "中文git.py") 7 | 8 | def git_command(command, *args): 9 | git_command_mapping = { 10 | "拉取": "pull", 11 | "推送": "push", 12 | "提交": "commit", 13 | "新建分支": "checkout -b", 14 | "切換分支": "checkout", 15 | "合併": "merge", 16 | "暫存": "add", 17 | "查看狀態": "status", 18 | "查看日誌": "log", 19 | "重置": "reset", 20 | "刪除分支": "branch -D", 21 | "遠端地址": "remote -v", 22 | "遠端更新": "remote update", 23 | "查看遠端分支": "branch -r", 24 | "版本": "-v", 25 | "刪除提交": "reset --hard HEAD~", 26 | "克隆": "clone", 27 | "配置": "config", 28 | "簽出到": "checkout", 29 | "查看圖形化日誌": "log --graph", 30 | "是否忽略": "check-ignore -v", 31 | "初始化": "init", 32 | "查看本地分支": "branch", 33 | # 可根據需要添加更多映射 34 | } 35 | 36 | git_config_subcommands = { 37 | "全局": "--global", 38 | "系統": "--system" 39 | } 40 | if command == "幫助": 41 | print("使用方法:") 42 | print("python 中文git.py <中文指令> [參數]") 43 | print("即:python 中文git.py <你想幹什麼> [具體要啥]") 44 | print("支持的中文指令:") 45 | for cmd in git_command_mapping: 46 | print("-", cmd) 47 | print("詳細支持命令請查看README_DEV文件:https://github.com/DuckDuckStudio/Chinese_git/blob/main/README_DEV.md#可用命令") 48 | return 49 | 50 | git_command = git_command_mapping.get(command) 51 | if git_command: 52 | try: 53 | if command == "提交": 54 | if not args: 55 | commit_message = input("請輸入提交信息: ") 56 | result = subprocess.run(['git', git_command, '-m', commit_message], capture_output=True, text=True) 57 | else: 58 | result = subprocess.run(['git', git_command, '-m', args[0]], capture_output=True, text=True) 59 | elif command == "暫存": 60 | if args and args[0] == "所有": 61 | result = subprocess.run(['git', 'add', '.'], capture_output=True, text=True) 62 | elif not args: 63 | print("你要暫存什麼你沒告訴我啊") 64 | else: 65 | result = subprocess.run(['git', 'add'] + list(args), capture_output=True, text=True) 66 | elif command == "切換分支" or command == "簽出到": 67 | if not args: 68 | branch = input("請輸入需要切換的分支:") 69 | result = subprocess.run(['git', git_command, branch], capture_output=True, text=True) 70 | elif len(args) == 1: 71 | result = subprocess.run(['git', git_command] + list(args), capture_output=True, text=True) 72 | else: 73 | print("多餘的參數") 74 | elif command == "新建分支": 75 | if not args: 76 | new_branch = input("請輸入新分支名稱: ") 77 | result = subprocess.run(['git', git_command, new_branch], capture_output=True, text=True) 78 | elif len(args) == 1: 79 | result = subprocess.run(['git', git_command] + list(args), capture_output=True, text=True) 80 | else: 81 | print("多餘的參數") 82 | elif command == "刪除分支": 83 | if not args: 84 | print("刪除分支命令需要指定要刪除的分支名稱。") 85 | elif len(args) > 2: 86 | print("多餘的參數") 87 | return 88 | elif len(args) == 2 and args[1] == "+確認": 89 | git_command = "git branch -d" 90 | else: 91 | print("無效的附加參數") 92 | return 93 | result = subprocess.run(['git', git_command, args[0]], capture_output=True, text=True) 94 | elif command == "版本": 95 | print("中文Git by 鸭鸭「カモ」") 96 | print("版本:v1.5") 97 | print("繁體中文翻譯版") 98 | print("安裝在:", full_path) 99 | result = subprocess.run(['git', git_command] + list(args), capture_output=True, text=True) 100 | elif command == "刪除提交": 101 | if not args: 102 | print("請輸入要刪除的提交類型(最新提交/倒數第n個提交/具體某個提交)。") 103 | else: 104 | if args[0] == "最新提交": 105 | result = subprocess.run(['git', git_command, 'HEAD~1'], capture_output=True, text=True) 106 | elif args[0].startswith("倒數第"): 107 | try: 108 | num = int(args[0][3:]) 109 | result = subprocess.run(['git', git_command, f'HEAD~{num}'], capture_output=True, text=True) 110 | except ValueError: 111 | print("參數錯誤,請輸入倒數第n個提交,n為正整數。") 112 | return 113 | else: 114 | result = subprocess.run(['git', git_command, args[0]], capture_output=True, text=True) 115 | elif command == "克隆": 116 | if not args: 117 | repository = input("請輸入遠程倉庫鏈接(以.git結尾):") 118 | result = subprocess.run(['git', git_command, repository], capture_output=True, text=True) 119 | else: 120 | result = subprocess.run(['git', git_command] + list(args), capture_output=True, text=True) 121 | elif command == "配置": 122 | if not args: 123 | print("配置命令需要指定配置選項和值。") 124 | elif len(args) == 1: 125 | print("配置命令需要指定配置值。") 126 | else: 127 | config_option = args[0] 128 | config_value = args[1] 129 | config_subcommand = None 130 | # 检查是否存在配置范围 131 | if len(args) == 3: 132 | config_subcommand = args[2] 133 | if config_subcommand not in git_config_subcommands: 134 | print("配置範圍錯誤,可選範圍為:全局、系統。") 135 | return 136 | git_config_command = ['git', git_command, config_option, config_value] 137 | if config_subcommand:# 如果存在配置范围 138 | git_config_command.insert(2, git_config_subcommands[config_subcommand]) 139 | result = subprocess.run(git_config_command, capture_output=True, text=True) 140 | elif command == "是否忽略": 141 | if not args: 142 | file = input("請輸入需要檢查的文件/文件夾:") 143 | result = subprocess.run(['git', git_command, file], capture_output=True, text=True) 144 | else: 145 | result = subprocess.run(['git', git_command] + list(args), capture_output=True, text=True) 146 | elif command == "查看本地分支": 147 | if len(args) > 2: 148 | print("多餘的參數") 149 | return 150 | elif args[0] == "+最後提交": 151 | git_command = "branch -v" 152 | elif (args[0] == "+最後提交" and args[1] == "+與上游分支關係") or (args[0] == "+與上游分支關係" and args[1] == "+最后提交"): 153 | git_command = "branch -vv" 154 | else: 155 | print("無效的參數") 156 | result = subprocess.run(['git', git_command], capture_output=True, text=True) 157 | elif command == "合併": 158 | if not args: 159 | branch = input("請輸入需要合併到當前分支的分支:") 160 | result = subprocess.run(['git', git_command, branch], capture_output=True, text=True) 161 | else: 162 | result = subprocess.run(['git', git_command] + list(args), capture_output=True, text=True) 163 | else: 164 | result = subprocess.run(['git', git_command] + list(args), capture_output=True, text=True) 165 | 166 | if result.returncode == 0: 167 | print(result.stdout) 168 | else: 169 | print("錯誤:", result.stderr) 170 | except Exception as e: 171 | print("執行git命令時出錯:", e) 172 | else: 173 | print("不支持的git命令:", command) 174 | 175 | if __name__ == "__main__": 176 | if len(sys.argv) > 1: 177 | git_command(sys.argv[1], *sys.argv[2:]) 178 | else: 179 | print("使用方法:") 180 | print("python 中文git.py <中文指令> [參數]") 181 | print("即:python 中文git.py <你想幹什麼> [具體要啥]") 182 | -------------------------------------------------------------------------------- /中文git-pack.py: -------------------------------------------------------------------------------- 1 | import os 2 | import sys 3 | import json 4 | import requests 5 | import subprocess 6 | from colorama import init, Fore 7 | 8 | init(autoreset=True) 9 | script_path = os.path.dirname(sys.argv[0]) 10 | full_path = os.path.join(script_path, "中文git.exe") 11 | exit_code = 0 # 只有不正常退出需要定义 12 | 13 | # ---------- 版本定义及更新 ---------- 14 | # 定义版本号 15 | VERSION = 'v3.3-pack' 16 | 17 | # --- 读取配置文件 --- 18 | def fetch_json(): 19 | global exit_code 20 | config_url = "https://duckduckstudio.github.io/yazicbs.github.io/Tools/chinese_git/files/json/config.json" 21 | headers = { 22 | 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36' 23 | } 24 | try: 25 | response = requests.get(config_url, headers=headers) 26 | if response.status_code == 200: 27 | json_data = response.json() 28 | print(f"{Fore.GREEN}✓{Fore.RESET} 获取最新默认配置文件成功") 29 | return json_data 30 | else: 31 | print(f"{Fore.RED}✕{Fore.RESET} 无法获取最新默认配置文件\n{Fore.BLUE}[!]{Fore.RESET} 返回状态码: {Fore.YELLOW}{response.status_code}{Fore.RESET}") 32 | exit_code = 1 33 | return None 34 | except Exception as e: 35 | print(f"{Fore.RED}✕{Fore.RESET} 尝试获取最新默认配置文件失败,错误: {Fore.RED}{e}{Fore.RESET}") 36 | exit_code = 1 37 | return None 38 | 39 | def merge_json(old_json, new_json): 40 | # 合并两个 JSON 对象 41 | updated_json = old_json.copy() 42 | 43 | # 处理旧 JSON 中的键 44 | keys_to_remove = [] 45 | for key in updated_json: 46 | if key not in new_json: 47 | keys_to_remove.append(key) 48 | 49 | for key in keys_to_remove: 50 | del updated_json[key] 51 | 52 | # 合并新 JSON 中的值 53 | for key in new_json: 54 | if key in updated_json and isinstance(updated_json[key], dict) and isinstance(new_json[key], dict): 55 | # 如果是字典类型,递归合并 56 | updated_json[key] = merge_json(updated_json[key], new_json[key]) 57 | else: 58 | # 直接更新值 59 | updated_json[key] = new_json[key] 60 | 61 | return updated_json 62 | 63 | def update_json(): 64 | global exit_code 65 | new_json = fetch_json() 66 | if not new_json: 67 | return 1 68 | try: 69 | with open(config_file, 'r') as f: 70 | old_json = json.load(f) 71 | 72 | updated_json = merge_json(old_json, new_json) 73 | 74 | # 将更新后的配置写入文件 75 | with open(config_file, 'w') as f: 76 | json.dump(updated_json, f, indent=4) 77 | 78 | print(f"{Fore.GREEN}✓{Fore.RESET} 默认配置文件更新成功") 79 | return 0 80 | except Exception as e: 81 | print(f"{Fore.RED}✕{Fore.RESET} 更新配置文件时出错:\n{Fore.RED}{e}{Fore.RESET}") 82 | exit_code = 1 83 | return 1 84 | 85 | config_file = os.path.join(os.path.dirname(os.path.abspath(sys.argv[0])), "config.json") 86 | if os.path.exists(config_file): 87 | try: 88 | with open(config_file, 'r') as file: 89 | config_data = json.load(file) 90 | auto_check_update = config_data['application']['run']['auto_check_update'] 91 | auto_get_notice = config_data['application']['run']['auto_get_notice'] 92 | except Exception as e: 93 | auto_check_update = True 94 | auto_get_notice = True 95 | print(f"{Fore.RED}✕{Fore.RESET} 读取配置文件时出错:\n{Fore.RED}{e}{Fore.RESET}\n{Fore.BLUE}[!]{Fore.RESET} 请检查配置文件是否正确,您可以先删除配置文件然后运行任意中文git的命令来重新生成默认配置文件。") 96 | exit_code = 1 97 | else: 98 | # 没有配置文件就默认都要 99 | auto_check_update = True 100 | auto_get_notice = True 101 | print(f"{Fore.YELLOW}⚠{Fore.RESET} 您的中文Git的安装目录下似乎{Fore.YELLOW}缺少配置文件{Fore.RESET},程序将尝试自动生成默认配置文件!") 102 | try: 103 | # 生成一个默认配置文件 104 | # 将数据结构转换为 JSON 格式的字符串 105 | json_str = { 106 | "information": { 107 | "version": "v3.0" 108 | }, 109 | "application": { 110 | "notice": { 111 | "time": "", 112 | "level": "", 113 | "content": "" 114 | }, 115 | "run": { 116 | "auto_check_update": "True", 117 | "auto_get_notice": "True" 118 | } 119 | } 120 | } 121 | 122 | json_str = json.dumps(json_str, indent=4) # indent 参数用于设置缩进(4空) 123 | 124 | # 将 JSON 字符串写入文件 125 | with open(config_file, 'w') as f: 126 | f.write(json_str) 127 | print(f"{Fore.GREEN}✓{Fore.RESET} 默认配置文件生成成功") 128 | except Exception as e: 129 | print(f"{Fore.RED}✕{Fore.RESET} 默认配置文件生成失败!请{Fore.YELLOW}手动添加{Fore.RESET}配置文件,否则将无法运行一些功能!") 130 | exit_code = 1 131 | print(f"{Fore.BLUE}[!]{Fore.RESET} 如果你觉得这不应该可以提交Issue") 132 | # ------------------- 133 | 134 | def always_check():# 每次执行命令都要检查的 135 | # ----------- 检查更新 ---------- 136 | current_version = VERSION.split('-')[0]# 分离-pack 137 | url = 'https://api.github.com/repos/DuckDuckStudio/Chinese_git/releases/latest' 138 | try: 139 | response = requests.get(url) 140 | data = response.json() 141 | latest_version = data['tag_name'] # 从 GitHub 获取最新版本号 142 | 143 | if latest_version != current_version: 144 | print(f"{Fore.BLUE}[!]{Fore.RESET} 发现新版本 {Fore.RED}{current_version}{Fore.RESET} → {Fore.GREEN}{latest_version}{Fore.RESET}\n运行 {Fore.BLUE}中文git 更新{Fore.RESET} 命令以更新。") 145 | except: 146 | pass 147 | 148 | def check_for_updates(): 149 | global exit_code 150 | # 提取版本号 151 | current_version = VERSION.split('-')[0] # 分离可能的 '-pack' 后缀 152 | 153 | # GitHub releases API URL 154 | url = 'https://api.github.com/repos/DuckDuckStudio/Chinese_git/releases/latest' 155 | 156 | try: 157 | response = requests.get(url) 158 | data = response.json() 159 | latest_version = data['tag_name'] # 从 GitHub 获取最新版本号 160 | 161 | if latest_version != current_version: 162 | print(f"{Fore.BLUE}[!]{Fore.RESET} 发现新版本 {Fore.RED}{current_version}{Fore.RESET} → {Fore.GREEN}{latest_version}{Fore.RESET} 可用!") 163 | return latest_version 164 | else: 165 | print(f"{Fore.GREEN}✓{Fore.RESET} 您已安装最新版本 {Fore.BLUE}{current_version}{Fore.RESET}。") 166 | return None 167 | except Exception as e: 168 | print(f"{Fore.RED}✕{Fore.RESET} 检查更新时出错: {e}") 169 | exit_code = 1 170 | return None 171 | 172 | # 自动检查更新并提示用户安装 173 | def auto_update(): 174 | global exit_code 175 | new_version = check_for_updates() 176 | 177 | if new_version: 178 | # 询问用户是否安装更新 179 | choice = input(f"{Fore.BLUE}?{Fore.RESET} 是否要安装此更新? (是/否): ").lower() 180 | if choice in ['是','y','yes']: 181 | print(f"{Fore.BLUE}[!]{Fore.RESET} 正在更新配置文件...") 182 | if update_json() == 1: 183 | print(f"{Fore.YELLOW}⚠{Fore.RESET} 请手动更新配置文件并提交issue") 184 | return 185 | print(f"{Fore.BLUE}[!]{Fore.RESET} 正在尝试更新更新程序...") 186 | new_filename = download_update_file(new_version) 187 | if new_filename: 188 | replace_current_program(new_filename) 189 | else: 190 | return 191 | print(f"{Fore.BLUE}[!]{Fore.RESET} 由于您使用的是打包版,请前往新窗口继续...") 192 | print(f"{Fore.BLUE}[!]{Fore.RESET} 正在启动更新程序...") 193 | try: 194 | os.system(f"start {script_path}\\中文git更新程序.exe --version {new_version}") 195 | sys.exit() 196 | except FileNotFoundError: 197 | print(f"{Fore.RED}✕{Fore.RESET} 未找到更新程序,请前往发行版页手动下载补全!") 198 | exit_code = 1 199 | except Exception as e: 200 | print(f"{Fore.RED}✕{Fore.RESET} 启动更新程序时出错: {Fore.RED}{e}{Fore.RESET}") 201 | exit_code = 1 202 | else: 203 | print(f"{Fore.BLUE}[!]{Fore.RESET} 已跳过更新。") 204 | 205 | # ------- 更新更新程序 ------- 206 | def download_update_file(version): 207 | global exit_code 208 | # 根据版本确定下载 URL 209 | download_url = f'https://github.com/DuckDuckStudio/Chinese_git/releases/download/{version}/Pack_Version_Update.exe' 210 | #spare_download_url = f'https://duckduckstudio.github.io/yazicbs.github.io/Tools/chinese_git/Spare-Download/Pack_Version_Update.exe' 211 | 212 | try: 213 | response = requests.get(download_url) 214 | 215 | new_filename = '中文git更新程序.exe' 216 | 217 | with open(new_filename, 'wb') as f: 218 | f.write(response.content) 219 | 220 | print(f"{Fore.GREEN}✓{Fore.RESET} 更新成功下载。") 221 | 222 | return new_filename 223 | except Exception as e: 224 | print(f"{Fore.RED}✕{Fore.RESET} 下载更新文件时出错: {e}") 225 | #choice = input(f"{Fore.BLUE}?{Fore.RESET} 是否切换备用下载路线(是/否):").lower() 226 | #if choice in ['是', 'y']: 227 | # try: 228 | # response = requests.get(spare_download_url) 229 | # filename = response.headers['Content-Disposition'].split('=')[1] 230 | # 231 | # new_filename = '中文Git.exe' 232 | # 233 | # with open(new_filename, 'wb') as f: 234 | # f.write(response.content) 235 | # 236 | # print(f"{Fore.GREEN}✓{Fore.RESET} 更新成功下载。") 237 | # 238 | # return new_filename 239 | # except Exception as e: 240 | # print(f"{Fore.RED}✕{Fore.RESET} 下载更新文件时出错: {e}") 241 | # exit_code = 1 242 | # return None 243 | exit_code = 1 244 | return None 245 | 246 | def replace_current_program(new_filename): 247 | global exit_code 248 | try: 249 | # 用下载的文件替换当前程序 250 | os.replace(new_filename, os.path.join(os.path.dirname(sys.argv[0]), "中文git更新程序.exe")) 251 | print(f"{Fore.GREEN}✓{Fore.RESET} 更新程序已成功更新。") 252 | except Exception as e: 253 | print(f"{Fore.RED}✕{Fore.RESET} 替换当前更新程序时出错: {e}") 254 | exit_code = 1 255 | 256 | # ---------- 版本更新 结束 ---------- 257 | 258 | def git_command(command, *args): 259 | global exit_code 260 | args = list(args) # 统一类型 261 | git_command_mapping = { 262 | "拉取": ["git", "pull"], 263 | "推送": ["git", "push"], 264 | "提交": ["git", "commit", "-m"], 265 | "新建分支": ["git", "checkout", "-b"], 266 | "合并": ["git", "merge"], 267 | "变基": ["git", "rebase"], 268 | "暂存": ["git", "add"], 269 | "状态": ["git", "status"], 270 | "日志": ["git", "log"], 271 | "删除分支": ["git", "branch", "-D"], 272 | "远程地址": ["git", "remote", "-v"], 273 | "远程更新": ["git", "remote", "update"], 274 | "远程分支": ["git", "branch", "-r"], 275 | "克隆": ["git", "clone"], 276 | "签出到": ["git", "checkout"], 277 | "图形化日志" :["git", "log", "--graph"], 278 | "是否忽略": ["git", "check-ignore", "-v"], 279 | "初始化": ["git", "init"], 280 | "本地分支": ["git", "branch"], 281 | "所有分支": ["git", "branch", "-a"], 282 | "强推": ["git", "push", "--force"], 283 | "更名分支": ["git", "branch", "-m"], 284 | # --- 特殊功能 --- 285 | "版本": ["git", "--version"], 286 | "更新": ["update"], # 没用到git 287 | # --- 结束 --- 288 | "还原": ["git", "revert"], 289 | "重置": ["git", "reset"], 290 | "差异": ["git", "diff"], 291 | "清理": ["git", "clean"], # TODO: 之后可以添加此命令的参数处理,例如 -n -f -df -xf 等 292 | "清理引用": ["git", "remote", "prune"], 293 | "配置": ["git", "config"], 294 | } 295 | if command == "帮助": 296 | print("使用方法:") 297 | print("中文git <中文指令> [参数]") 298 | print("即: 中文git <你想干什么> [具体要啥]") 299 | print("\n支持的中文命令请查看用户手册: https://github.com/DuckDuckStudio/Chinese_git/blob/main/USER_HANDBOOK.md#可用命令") 300 | return 301 | 302 | git_command = git_command_mapping.get(command) 303 | if git_command: 304 | try: 305 | if command == "提交": 306 | result = subprocess.run(['git', 'diff', '--cached', '--quiet'], stdout=subprocess.PIPE, stderr=subprocess.PIPE) 307 | if result.returncode == 0: # 0 代表没有修改, 1 代表有修改 308 | print(f"{Fore.YELLOW}⚠{Fore.RESET} 你似乎还没有暂存任何修改") 309 | choice = input(f"{Fore.BLUE}?{Fore.RESET} 是否要先暂存所有修改后直接提交: ").lower() 310 | if choice in ['是', 'y', 'yes']: 311 | subprocess.run(['git', 'add', '--all'], capture_output=True, text=True) 312 | else: 313 | exit_code = 1 314 | print(f"{Fore.RED}✕{Fore.RESET} 请先暂存修改后再提交") 315 | if not args and exit_code != 1: # 没有提交信息且前面没出错 316 | commit_message = input("请输入提交信息: ") 317 | if not commit_message: 318 | # 还不输提交信息? 玩我呢 319 | print(f"{Fore.RED}✕{Fore.RESET} 请提供提交信息") 320 | exit_code = 1 321 | result = subprocess.run(git_command + [commit_message], capture_output=True, text=True) 322 | else: 323 | # 有提交信息就直接提交 324 | result = subprocess.run(git_command + args, capture_output=True, text=True) 325 | elif command == "暂存": 326 | if args and args[0] == "所有": 327 | result = subprocess.run(git_command + ['--all'], capture_output=True, text=True) 328 | elif not args: 329 | print(f"{Fore.RED}✕{Fore.RESET} 你要暂存什么你没告诉我啊") 330 | exit_code = 1 331 | else: 332 | result = subprocess.run(git_command + args, capture_output=True, text=True) 333 | elif command == "签出到": 334 | if not args: 335 | branch = input("请输入需要切换的分支: ") 336 | result = subprocess.run(git_command + [branch], capture_output=True, text=True) 337 | elif len(args) == 1: 338 | result = subprocess.run(git_command + args, capture_output=True, text=True) 339 | else: 340 | print(f"{Fore.RED}✕{Fore.RESET} 多余的参数") 341 | exit_code = 1 342 | elif command == "新建分支": 343 | if not args: 344 | new_branch = input("请输入新分支名称: ") 345 | result = subprocess.run(git_command + [new_branch], capture_output=True, text=True) 346 | elif len(args) == 1: 347 | result = subprocess.run(git_command + args, capture_output=True, text=True) 348 | else: 349 | print(f"{Fore.RED}✕{Fore.RESET} 多余的参数") 350 | exit_code = 1 351 | elif command == "删除分支": 352 | if not args: 353 | print(f"{Fore.RED}✕{Fore.RESET} 删除分支命令需要指定要删除的分支名称") 354 | exit_code = 1 355 | elif len(args) == 2: 356 | if args[1] == "+确认": 357 | git_command = ["git", "branch", "-d"] 358 | result = subprocess.run(git_command + args, capture_output=True, text=True) 359 | elif command == "版本": 360 | print("中文Git by 鸭鸭「カモ」") 361 | print(f"版本: {Fore.BLUE}{VERSION}{Fore.RESET}") 362 | print(f"安装在: {Fore.BLUE}{full_path}{Fore.RESET}") 363 | result = subprocess.run(git_command, capture_output=True, text=True) 364 | elif command == "还原": 365 | if not args: 366 | print(f"{Fore.RED}✕{Fore.RESET} 还原命令需要参数") 367 | exit_code = 1 368 | else: 369 | if args[0] == "最新提交": 370 | result = subprocess.run(git_command + ['HEAD'], capture_output=True, text=True) 371 | elif args[0].startswith("倒数第"): 372 | try: 373 | if args[0].endswith('个提交'): 374 | num = args[0] 375 | num = num[3:-3] 376 | else: 377 | num = int(args[0][3:]) 378 | result = subprocess.run(git_command + [f'HEAD~{num}'], capture_output=True, text=True) 379 | except ValueError: 380 | print(f"{Fore.RED}✕{Fore.RESET} 参数错误,请输入倒数第n个提交,n为正整数。") 381 | exit_code = 1 382 | else: 383 | result = subprocess.run(git_command + args, capture_output=True, text=True) 384 | elif command == "克隆": 385 | if not args: 386 | repository = input("请输入远程仓库链接: ") 387 | result = subprocess.run(git_command + [repository], capture_output=True, text=True) 388 | else: 389 | result = subprocess.run(git_command + args, capture_output=True, text=True) 390 | elif command == "是否忽略": 391 | if not args: 392 | file = input("请输入需要检查的文件/文件夹: ") 393 | if not file: 394 | print(f"{Fore.RED}✕{Fore.RESET} 文件/文件夹名不能为空") 395 | exit_code = 1 396 | result = subprocess.run(git_command + [file], capture_output=True, text=True) 397 | else: 398 | result = subprocess.run(git_command + args, capture_output=True, text=True) 399 | elif command == "本地分支": 400 | if len(args) > 2: 401 | print(f"{Fore.RED}✕{Fore.RESET} 多余的参数") 402 | exit_code = 1 403 | elif args[0] == "+最后提交": 404 | git_command.append("-v") 405 | elif (args[0] == "+最后提交" and args[1] == "+与上游分支关系") or (args[0] == "+与上游分支关系" and args[1] == "+最后提交"): 406 | git_command.append("-vv") 407 | else: 408 | print(f"{Fore.RED}✕{Fore.RESET} 无效的参数") 409 | exit_code = 1 410 | result = subprocess.run(git_command + args, capture_output=True, text=True) 411 | elif command == "合并": 412 | if not args: 413 | branch = input("请输入需要合并到当前分支的分支: ") 414 | result = subprocess.run(git_command + [branch], capture_output=True, text=True) 415 | else: 416 | result = subprocess.run(git_command + args, capture_output=True, text=True) 417 | elif command == "更名分支": 418 | if not args: 419 | old_branch = input("请输入旧分支名:") 420 | new_branch = input("请输入新分支名:") 421 | if old_branch == new_branch: 422 | print(f"{Fore.RED}✕{Fore.RESET} 新旧分支名称相同") 423 | exit_code = 1 424 | result = subprocess.run(git_command + [old_branch, new_branch], capture_output=True, text=True) 425 | if args < 2: 426 | print(f"{Fore.RED}✕{Fore.RESET} 缺少参数") 427 | exit_code = 1 428 | else: 429 | result = subprocess.run(git_command + args, capture_output=True, text=True) 430 | elif command == "更新": 431 | print("中文Git by 鸭鸭「カモ」") 432 | print("正在检查更新...") 433 | auto_update() 434 | return 435 | elif command == "重置": 436 | if not args: 437 | print(f"{Fore.RED}✕{Fore.RESET} 重置指令需要具体的参数。") 438 | exit_code = 1 439 | elif len(args) > 2: 440 | print(f"{Fore.RED}✕{Fore.RESET} 多余的参数") 441 | exit_code = 1 442 | elif len(args) == 2: 443 | if args[1] == "+保留更改": # 默认 444 | git_command.append("--mixed") 445 | elif args[1] == "+删除更改": 446 | git_command.append("--hard") 447 | else: 448 | print(f"{Fore.RED}✕{Fore.RESET} 无效的附加参数") 449 | exit_code = 1 450 | 451 | if args[0] in ["最新提交", "HEAD"]: 452 | print(f"{Fore.YELLOW}⚠{Fore.RESET} 虽然您这样做不会出错,但这样做有意义吗(思考)") 453 | result = subprocess.run(git_command + ['HEAD'], capture_output=True, text=True) 454 | elif args[0].startswith("倒数第"): 455 | try: 456 | if args[0].endswith('个提交'): 457 | num = args[0] 458 | num = num[3:-3] 459 | else: 460 | num = int(args[0][3:]) 461 | result = subprocess.run(git_command + [f'HEAD~{num}'], capture_output=True, text=True) 462 | except ValueError: 463 | print(f"{Fore.RED}✕{Fore.RESET} 参数错误,请输入倒数第n个提交,n为正整数。") 464 | exit_code = 1 465 | else: 466 | result = subprocess.run(git_command + args, capture_output=True, text=True) 467 | elif command == "清理引用": 468 | if not args: 469 | # 默认 470 | git_command.append("origin") 471 | result = subprocess.run(git_command + args, capture_output=True, text=True) 472 | else: 473 | result = subprocess.run(git_command + args, capture_output=True, text=True) 474 | 475 | if result.returncode == 0 and exit_code == 0: 476 | print(result.stdout) 477 | elif exit_code != 1: # 已设置错误代码的都已输出错误信息 478 | print(f"{Fore.RED}✕{Fore.RESET} 错误: {result.stderr}") 479 | exit_code = 1 480 | 481 | if auto_check_update == "True": 482 | always_check() # 自动检查更新 483 | except Exception as e: 484 | print(f"{Fore.RED}✕{Fore.RESET} 执行git命令时出错: {e}") 485 | exit_code = 1 486 | if auto_check_update == "True": 487 | always_check() # 自动检查更新 488 | else: 489 | print("不支持的命令:", command) 490 | if auto_check_update == "True": 491 | always_check() # 自动检查更新 492 | exit_code = 1 493 | 494 | if __name__ == "__main__": 495 | if len(sys.argv) > 1: 496 | git_command(sys.argv[1], *sys.argv[2:]) 497 | else: 498 | print("使用方法:") 499 | print("中文git <中文指令> [参数]") 500 | print("即: 中文git <你想干什么> [具体要啥]") 501 | if auto_check_update == "True": 502 | always_check() # 自动检查更新 503 | exit_code = 1 504 | sys.exit(exit_code) 505 | -------------------------------------------------------------------------------- /中文git.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DuckDuckStudio/Chinese_git/f6927361880c34d8de7a58ddc2e361fa56d80069/中文git.exe -------------------------------------------------------------------------------- /中文git.py: -------------------------------------------------------------------------------- 1 | import os 2 | import sys 3 | import json 4 | import requests 5 | import subprocess 6 | from colorama import init, Fore 7 | 8 | init(autoreset=True) 9 | script_path = os.path.dirname(os.path.abspath(__file__)) 10 | full_path = os.path.join(script_path, "中文git.py") 11 | exit_code = 0 # 只有不正常退出需要定义 12 | 13 | # ---------- 版本定义及更新 ---------- 14 | # 定义版本号 15 | VERSION = 'v3.3' 16 | # GitHub releases API URL 17 | url = 'https://api.github.com/repos/DuckDuckStudio/Chinese_git/releases/latest' 18 | 19 | # --- 读取配置文件 --- 20 | def fetch_json(): 21 | global exit_code 22 | config_url = "https://duckduckstudio.github.io/yazicbs.github.io/Tools/chinese_git/files/json/config.json" 23 | headers = { 24 | 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36' 25 | } 26 | try: 27 | response = requests.get(config_url, headers=headers) 28 | if response.status_code == 200: 29 | json_data = response.json() 30 | print(f"{Fore.GREEN}✓{Fore.RESET} 获取最新默认配置文件成功") 31 | return json_data 32 | else: 33 | print(f"{Fore.RED}✕{Fore.RESET} 无法获取最新默认配置文件\n{Fore.BLUE}[!]{Fore.RESET} 返回状态码: {Fore.YELLOW}{response.status_code}{Fore.RESET}") 34 | exit_code = 1 35 | return None 36 | except Exception as e: 37 | print(f"{Fore.RED}✕{Fore.RESET} 尝试获取最新默认配置文件失败,错误: {Fore.RED}{e}{Fore.RESET}") 38 | exit_code = 1 39 | return None 40 | 41 | def merge_json(old_json, new_json): 42 | # 合并两个 JSON 对象 43 | updated_json = old_json.copy() 44 | 45 | # 处理旧 JSON 中的键 46 | keys_to_remove = [] 47 | for key in updated_json: 48 | if key not in new_json: 49 | keys_to_remove.append(key) 50 | 51 | for key in keys_to_remove: 52 | del updated_json[key] 53 | 54 | # 合并新 JSON 中的值 55 | for key in new_json: 56 | if key in updated_json and isinstance(updated_json[key], dict) and isinstance(new_json[key], dict): 57 | # 如果是字典类型,递归合并 58 | updated_json[key] = merge_json(updated_json[key], new_json[key]) 59 | else: 60 | # 直接更新值 61 | updated_json[key] = new_json[key] 62 | 63 | return updated_json 64 | 65 | def update_json(): 66 | global exit_code 67 | new_json = fetch_json() 68 | if not new_json: 69 | return 1 70 | try: 71 | with open(config_file, 'r') as f: 72 | old_json = json.load(f) 73 | 74 | updated_json = merge_json(old_json, new_json) 75 | 76 | # 将更新后的配置写入文件 77 | with open(config_file, 'w') as f: 78 | json.dump(updated_json, f, indent=4) 79 | 80 | print(f"{Fore.GREEN}✓{Fore.RESET} 默认配置文件更新成功") 81 | return 0 82 | except Exception as e: 83 | print(f"{Fore.RED}✕{Fore.RESET} 更新配置文件时出错:\n{Fore.RED}{e}{Fore.RESET}") 84 | exit_code = 1 85 | return 1 86 | 87 | config_file = os.path.join(os.path.dirname(os.path.abspath(sys.argv[0])), "config.json") 88 | if os.path.exists(config_file): 89 | try: 90 | with open(config_file, 'r') as file: 91 | config_data = json.load(file) 92 | auto_check_update = config_data['application']['run']['auto_check_update'] 93 | auto_get_notice = config_data['application']['run']['auto_get_notice'] 94 | except Exception as e: 95 | auto_check_update = True 96 | auto_get_notice = True 97 | print(f"{Fore.RED}✕{Fore.RESET} 读取配置文件时出错:\n{Fore.RED}{e}{Fore.RESET}\n{Fore.BLUE}[!]{Fore.RESET} 请检查配置文件是否正确,您可以先删除配置文件然后运行任意中文git的命令来重新生成默认配置文件。") 98 | exit_code = 1 99 | else: 100 | # 没有配置文件就默认都要 101 | auto_check_update = True 102 | auto_get_notice = True 103 | print(f"{Fore.YELLOW}⚠{Fore.RESET} 您的中文Git的安装目录下似乎{Fore.YELLOW}缺少配置文件{Fore.RESET},程序将尝试自动生成默认配置文件!") 104 | try: 105 | # 生成一个默认配置文件 106 | # 将数据结构转换为 JSON 格式的字符串 107 | json_str = { 108 | "information": { 109 | "version": "v3.0" 110 | }, 111 | "application": { 112 | "notice": { 113 | "time": "", 114 | "level": "", 115 | "content": "" 116 | }, 117 | "run": { 118 | "auto_check_update": "True", 119 | "auto_get_notice": "True" 120 | } 121 | } 122 | } 123 | 124 | json_str = json.dumps(json_str, indent=4) # indent 参数用于设置缩进(4空) 125 | 126 | # 将 JSON 字符串写入文件 127 | with open(config_file, 'w') as f: 128 | f.write(json_str) 129 | print(f"{Fore.GREEN}✓{Fore.RESET} 默认配置文件生成成功") 130 | except Exception as e: 131 | print(f"{Fore.RED}✕{Fore.RESET} 默认配置文件生成失败!请{Fore.YELLOW}手动添加{Fore.RESET}配置文件,否则将无法运行一些功能!") 132 | exit_code = 1 133 | print(f"{Fore.BLUE}[!]{Fore.RESET} 如果你觉得这不应该可以提交Issue") 134 | # ------------------- 135 | 136 | def always_check():# 每次执行命令都要检查的 137 | # ----------- 检查更新 ---------- 138 | current_version = VERSION 139 | try: 140 | response = requests.get(url) 141 | data = response.json() 142 | latest_version = data['tag_name'] # 从 GitHub 获取最新版本号 143 | 144 | if latest_version != current_version: 145 | print(f"{Fore.BLUE}[!]{Fore.RESET} 发现新版本 {Fore.RED}{current_version}{Fore.RESET} → {Fore.GREEN}{latest_version}{Fore.RESET}\n运行 {Fore.BLUE}中文git 更新{Fore.RESET} 命令以更新。") 146 | except: 147 | pass 148 | 149 | def check_for_updates(): 150 | global exit_code 151 | # 提取版本号 152 | current_version = VERSION.split('-')[0] # 分离可能的 '-pack' 后缀 153 | 154 | try: 155 | response = requests.get(url) 156 | data = response.json() 157 | latest_version = data['tag_name'] # 从 GitHub 获取最新版本号 158 | 159 | if latest_version != current_version: 160 | print(f"{Fore.BLUE}[!]{Fore.RESET} 发现新版本 {Fore.RED}{current_version}{Fore.RESET} → {Fore.GREEN}{latest_version}{Fore.RESET} 可用!") 161 | return latest_version 162 | else: 163 | print(f"{Fore.GREEN}✓{Fore.RESET} 您已安装最新版本 {Fore.BLUE}{current_version}{Fore.RESET}。") 164 | return None 165 | except Exception as e: 166 | print(f"{Fore.RED}✕{Fore.RESET} 检查更新时出错: {e}") 167 | exit_code = 1 168 | return None 169 | 170 | def download_update_file(version): 171 | global exit_code 172 | # 根据版本确定下载 URL 173 | download_url = f'https://github.com/DuckDuckStudio/Chinese_git/releases/download/{version}/Chinese_git.py' 174 | spare_download_url = 'https://duckduckstudio.github.io/yazicbs.github.io/Tools/chinese_git/Spare-Download/Chinese_git.py' 175 | spare_download_version_url = 'https://duckduckstudio.github.io/yazicbs.github.io/Tools/chinese_git/Spare-Download/info.json' 176 | 177 | try: 178 | response = requests.get(download_url) 179 | 180 | # 重命名下载的文件为"中文Git.exe" 或 "中文Git.py" 181 | new_filename = '中文Git.py' 182 | 183 | with open(new_filename, 'wb') as f: 184 | f.write(response.content) 185 | 186 | print(f"{Fore.GREEN}✓{Fore.RESET} 更新成功下载。") 187 | 188 | return new_filename 189 | except Exception as e: 190 | print(f"{Fore.RED}✕{Fore.RESET} 下载更新文件时出错: {e}") 191 | exit_code = 1 192 | choice = input(f"{Fore.BLUE}?{Fore.RESET} 是否切换备用下载路线(是/否): ").lower() 193 | if choice in ['是', 'y', 'yes']: 194 | try: 195 | spare_download_version = requests.get(spare_download_version_url) 196 | data = spare_download_version.json() 197 | spare_download_version = data['version']# 获取备用路线的程序的版本号 198 | except Exception as e: 199 | print(f"{Fore.RED}✕{Fore.RESET} 获取备用路线版本信息时出错: {Fore.RED}{e}{Fore.RESET}") 200 | exit_code = 1 201 | return None 202 | if spare_download_version == version: 203 | try: 204 | response = requests.get(spare_download_url) 205 | 206 | new_filename = '中文git.py' 207 | 208 | with open(new_filename, 'wb') as f: 209 | f.write(response.content) 210 | 211 | print(f"{Fore.GREEN}✓{Fore.RESET} 更新成功下载。") 212 | 213 | return new_filename 214 | except Exception as e: 215 | print(f"{Fore.RED}✕{Fore.RESET} 下载更新文件时出错: {e}") 216 | exit_code = 1 217 | return None 218 | else: 219 | print(f"{Fore.RED}✕{Fore.RESET} 备用路线{Fore.YELLOW}版本不一致{Fore.RESET}\n备用路线版本为{Fore.BLUE}{spare_download_version}{Fore.RESET},而GitHub Releases上的最新版为{Fore.BLUE}{version}{Fore.BLUE}\n{Fore.YELLOW}如果你遇到了这个错误,请前往GitHub提交Issue,感谢!{Fore.RESET}") 220 | exit_code = 1 221 | return None 222 | return None 223 | 224 | def replace_current_program(new_filename): 225 | global exit_code 226 | try: 227 | # 用下载的文件替换当前程序 228 | os.replace(new_filename, sys.argv[0]) 229 | if update_json() == 1: 230 | print(f"{Fore.YELLOW}⚠{Fore.RESET} 请手动更新配置文件并提交issue") 231 | print(f"{Fore.GREEN}✓{Fore.RESET} 程序已成功更新。") 232 | except Exception as e: 233 | print(f"{Fore.RED}✕{Fore.RESET} 替换当前程序时出错: {e}") 234 | exit_code = 1 235 | 236 | # 自动检查更新并提示用户安装 237 | def auto_update(): 238 | new_version = check_for_updates() 239 | 240 | if new_version: 241 | # 询问用户是否安装更新 242 | choice = input(f"{Fore.BLUE}?{Fore.RESET} 是否要安装此更新? (是/否): ").lower() 243 | if choice in ['是','y','yes']: 244 | new_filename = download_update_file(new_version) 245 | if new_filename: 246 | replace_current_program(new_filename) 247 | else: 248 | print(f"{Fore.BLUE}[!]{Fore.RESET} 已跳过更新。") 249 | 250 | # ---------- 版本更新 结束 ---------- 251 | 252 | def git_command(command, *args): 253 | global exit_code 254 | args = list(args) # 统一类型 255 | git_command_mapping = { 256 | "拉取": ["git", "pull"], 257 | "推送": ["git", "push"], 258 | "提交": ["git", "commit", "-m"], 259 | "新建分支": ["git", "checkout", "-b"], 260 | "合并": ["git", "merge"], 261 | "变基": ["git", "rebase"], 262 | "暂存": ["git", "add"], 263 | "状态": ["git", "status"], 264 | "日志": ["git", "log"], 265 | "删除分支": ["git", "branch", "-D"], 266 | "远程地址": ["git", "remote", "-v"], 267 | "远程更新": ["git", "remote", "update"], 268 | "远程分支": ["git", "branch", "-r"], 269 | "克隆": ["git", "clone"], 270 | "签出到": ["git", "checkout"], 271 | "图形化日志" :["git", "log", "--graph"], 272 | "是否忽略": ["git", "check-ignore", "-v"], 273 | "初始化": ["git", "init"], 274 | "本地分支": ["git", "branch"], 275 | "所有分支": ["git", "branch", "-a"], 276 | "强推": ["git", "push", "--force"], 277 | "更名分支": ["git", "branch", "-m"], 278 | # --- 特殊功能 --- 279 | "版本": ["git", "--version"], 280 | "更新": ["update"], # 没用到git 281 | # --- 结束 --- 282 | "还原": ["git", "revert"], 283 | "重置": ["git", "reset"], 284 | "差异": ["git", "diff"], 285 | "清理": ["git", "clean"], # TODO: 之后可以添加此命令的参数处理,例如 -n -f -df -xf 等 286 | "清理引用": ["git", "remote", "prune"], 287 | "配置": ["git", "config"], 288 | } 289 | if command == "帮助": 290 | print("使用方法:") 291 | print("中文git <中文指令> [参数]") 292 | print("即: 中文git <你想干什么> [具体要啥]") 293 | print("\n支持的中文命令请查看用户手册: https://github.com/DuckDuckStudio/Chinese_git/blob/main/USER_HANDBOOK.md#可用命令") 294 | return 295 | 296 | git_command = git_command_mapping.get(command) 297 | if git_command: 298 | try: 299 | if command == "提交": 300 | result = subprocess.run(['git', 'diff', '--cached', '--quiet'], stdout=subprocess.PIPE, stderr=subprocess.PIPE) 301 | if result.returncode == 0: # 0 代表没有修改, 1 代表有修改 302 | print(f"{Fore.YELLOW}⚠{Fore.RESET} 你似乎还没有暂存任何修改") 303 | choice = input(f"{Fore.BLUE}?{Fore.RESET} 是否要先暂存所有修改后直接提交: ").lower() 304 | if choice in ['是', 'y', 'yes']: 305 | subprocess.run(['git', 'add', '--all'], capture_output=True, text=True) 306 | else: 307 | exit_code = 1 308 | print(f"{Fore.RED}✕{Fore.RESET} 请先暂存修改后再提交") 309 | if not args and exit_code != 1: # 没有提交信息且前面没出错 310 | commit_message = input("请输入提交信息: ") 311 | if not commit_message: 312 | # 还不输提交信息? 玩我呢 313 | print(f"{Fore.RED}✕{Fore.RESET} 请提供提交信息") 314 | exit_code = 1 315 | result = subprocess.run(git_command + [commit_message], capture_output=True, text=True) 316 | else: 317 | # 有提交信息就直接提交 318 | result = subprocess.run(git_command + args, capture_output=True, text=True) 319 | elif command == "暂存": 320 | if args and args[0] == "所有": 321 | result = subprocess.run(git_command + ['--all'], capture_output=True, text=True) 322 | elif not args: 323 | print(f"{Fore.RED}✕{Fore.RESET} 你要暂存什么你没告诉我啊") 324 | exit_code = 1 325 | else: 326 | result = subprocess.run(git_command + args, capture_output=True, text=True) 327 | elif command == "签出到": 328 | if not args: 329 | branch = input("请输入需要切换的分支: ") 330 | result = subprocess.run(git_command + [branch], capture_output=True, text=True) 331 | elif len(args) == 1: 332 | result = subprocess.run(git_command + args, capture_output=True, text=True) 333 | else: 334 | print(f"{Fore.RED}✕{Fore.RESET} 多余的参数") 335 | exit_code = 1 336 | elif command == "新建分支": 337 | if not args: 338 | new_branch = input("请输入新分支名称: ") 339 | result = subprocess.run(git_command + [new_branch], capture_output=True, text=True) 340 | elif len(args) == 1: 341 | result = subprocess.run(git_command + args, capture_output=True, text=True) 342 | else: 343 | print(f"{Fore.RED}✕{Fore.RESET} 多余的参数") 344 | elif command == "删除分支": 345 | if not args: 346 | print(f"{Fore.RED}✕{Fore.RESET} 删除分支命令需要指定要删除的分支名称") 347 | exit_code = 1 348 | elif len(args) == 2: 349 | if args[1] == "+确认": 350 | git_command = ["git", "branch", "-d"] 351 | result = subprocess.run(git_command + args, capture_output=True, text=True) 352 | elif command == "版本": 353 | print("中文Git by 鸭鸭「カモ」") 354 | print(f"版本: {Fore.BLUE}{VERSION}{Fore.RESET}") 355 | print(f"安装在: {Fore.BLUE}{full_path}{Fore.RESET}") 356 | result = subprocess.run(git_command, capture_output=True, text=True) 357 | elif command == "还原": 358 | if not args: 359 | print(f"{Fore.RED}✕{Fore.RESET} 还原命令需要参数") 360 | exit_code = 1 361 | else: 362 | if args[0] == "最新提交": 363 | result = subprocess.run(git_command + ['HEAD'], capture_output=True, text=True) 364 | elif args[0].startswith("倒数第"): 365 | try: 366 | if args[0].endswith('个提交'): 367 | num = args[0] 368 | num = num[3:-3] 369 | else: 370 | num = int(args[0][3:]) 371 | result = subprocess.run(git_command + [f'HEAD~{num}'], capture_output=True, text=True) 372 | except ValueError: 373 | print(f"{Fore.RED}✕{Fore.RESET} 参数错误,请输入倒数第n个提交,n为正整数。") 374 | exit_code = 1 375 | else: 376 | result = subprocess.run(git_command + args, capture_output=True, text=True) 377 | elif command == "克隆": 378 | if not args: 379 | repository = input("请输入远程仓库链接: ") 380 | result = subprocess.run(git_command + [repository], capture_output=True, text=True) 381 | else: 382 | result = subprocess.run(git_command + args, capture_output=True, text=True) 383 | elif command == "是否忽略": 384 | if not args: 385 | file = input("请输入需要检查的文件/文件夹: ") 386 | if not file: 387 | print(f"{Fore.RED}✕{Fore.RESET} 文件/文件夹名不能为空") 388 | exit_code = 1 389 | result = subprocess.run(git_command + [file], capture_output=True, text=True) 390 | else: 391 | result = subprocess.run(git_command + args, capture_output=True, text=True) 392 | elif command == "本地分支": 393 | if len(args) > 2: 394 | print(f"{Fore.RED}✕{Fore.RESET} 多余的参数") 395 | exit_code = 1 396 | elif args[0] == "+最后提交": 397 | git_command.append("-v") 398 | elif (args[0] == "+最后提交" and args[1] == "+与上游分支关系") or (args[0] == "+与上游分支关系" and args[1] == "+最后提交"): 399 | git_command.append("-vv") 400 | else: 401 | print(f"{Fore.RED}✕{Fore.RESET} 无效的参数") 402 | exit_code = 1 403 | result = subprocess.run(git_command + args, capture_output=True, text=True) 404 | elif command == "合并": 405 | if not args: 406 | branch = input("请输入需要合并到当前分支的分支: ") 407 | result = subprocess.run(git_command + [branch], capture_output=True, text=True) 408 | else: 409 | result = subprocess.run(git_command + args, capture_output=True, text=True) 410 | elif command == "更名分支": 411 | if not args: 412 | old_branch = input("请输入旧分支名:") 413 | new_branch = input("请输入新分支名:") 414 | if old_branch == new_branch: 415 | print(f"{Fore.RED}✕{Fore.RESET} 新旧分支名称相同") 416 | exit_code = 1 417 | result = subprocess.run(git_command + [old_branch, new_branch], capture_output=True, text=True) 418 | if args < 2: 419 | print(f"{Fore.RED}✕{Fore.RESET} 缺少参数") 420 | exit_code = 1 421 | else: 422 | result = subprocess.run(git_command + args, capture_output=True, text=True) 423 | elif command == "更新": 424 | print("中文Git by 鸭鸭「カモ」") 425 | print(f"当前版本: {Fore.BLUE}{VERSION}{Fore.RESET}") 426 | print("正在检查更新...") 427 | auto_update() 428 | return 429 | elif command == "重置": 430 | if not args: 431 | print(f"{Fore.RED}✕{Fore.RESET} 重置指令需要具体的参数。") 432 | exit_code = 1 433 | elif len(args) > 2: 434 | print(f"{Fore.RED}✕{Fore.RESET} 多余的参数") 435 | exit_code = 1 436 | elif len(args) == 2: 437 | if args[1] == "+保留更改": # 默认 438 | git_command.append("--mixed") 439 | elif args[1] == "+删除更改": 440 | git_command.append("--hard") 441 | else: 442 | print(f"{Fore.RED}✕{Fore.RESET} 无效的附加参数") 443 | exit_code = 1 444 | 445 | if args[0] in ["最新提交", "HEAD"]: 446 | print(f"{Fore.YELLOW}⚠{Fore.RESET} 虽然您这样做不会出错,但这样做有意义吗(思考)") 447 | result = subprocess.run(git_command + ['HEAD'], capture_output=True, text=True) 448 | elif args[0].startswith("倒数第"): 449 | try: 450 | if args[0].endswith('个提交'): 451 | num = args[0] 452 | num = num[3:-3] 453 | else: 454 | num = int(args[0][3:]) 455 | result = subprocess.run(git_command + [f'HEAD~{num}'], capture_output=True, text=True) 456 | except ValueError: 457 | print(f"{Fore.RED}✕{Fore.RESET} 参数错误,请输入倒数第n个提交,n为正整数。") 458 | exit_code = 1 459 | else: 460 | result = subprocess.run(git_command + args, capture_output=True, text=True) 461 | elif command == "清理引用": 462 | if not args: 463 | # 默认 464 | git_command.append("origin") 465 | result = subprocess.run(git_command + args, capture_output=True, text=True) 466 | else: 467 | result = subprocess.run(git_command + args, capture_output=True, text=True) 468 | 469 | if result.returncode == 0 and exit_code == 0: 470 | print(result.stdout) 471 | elif exit_code != 1: # 已设置错误代码的都已输出错误信息 472 | print(f"{Fore.RED}✕{Fore.RESET} 错误: {result.stderr}") 473 | exit_code = 1 474 | 475 | if auto_check_update == "True": 476 | always_check() # 自动检查更新 477 | except Exception as e: 478 | print(f"{Fore.RED}✕{Fore.RESET} 执行命令时出错: {e}") 479 | if auto_check_update == "True": 480 | always_check() # 自动检查更新 481 | exit_code = 1 482 | else: 483 | print("不支持的命令:", command) 484 | if auto_check_update == "True": 485 | always_check() # 自动检查更新 486 | exit_code = 1 487 | 488 | if __name__ == "__main__": 489 | if len(sys.argv) > 1: 490 | git_command(sys.argv[1], *sys.argv[2:]) 491 | else: 492 | print("使用方法:") 493 | print("中文git <中文指令> [参数]") 494 | print("即: 中文git <你想干什么> [具体要啥]") 495 | if auto_check_update == "True": 496 | always_check() # 自动检查更新 497 | exit_code = 1 498 | sys.exit(exit_code) 499 | -------------------------------------------------------------------------------- /中文git更新程序.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DuckDuckStudio/Chinese_git/f6927361880c34d8de7a58ddc2e361fa56d80069/中文git更新程序.exe -------------------------------------------------------------------------------- /中文git更新程序.py: -------------------------------------------------------------------------------- 1 | import os 2 | import sys 3 | import requests 4 | import argparse 5 | from colorama import init, Fore 6 | 7 | init(autoreset=True) 8 | 9 | exit_code = 0 10 | 11 | def download_update_file(version): 12 | global exit_code 13 | # 根据版本确定下载 URL 14 | download_url = f'https://github.com/DuckDuckStudio/Chinese_git/releases/download/{version}/Chinese_git.exe' 15 | #spare_download_url = f'https://duckduckstudio.github.io/yazicbs.github.io/Tools/chinese_git/Spare-Download/Chinese_git.exe' 16 | 17 | try: 18 | response = requests.get(download_url) 19 | 20 | new_filename = '中文git.exe' 21 | 22 | with open(new_filename, 'wb') as f: 23 | f.write(response.content) 24 | 25 | print(f"{Fore.GREEN}✓{Fore.RESET} 更新成功下载。") 26 | 27 | return new_filename 28 | except Exception as e: 29 | print(f"{Fore.RED}✕{Fore.RESET} 下载更新文件时出错: {e}") 30 | #choice = input(f"{Fore.BLUE}?{Fore.RESET} 是否切换备用下载路线(是/否):").lower() 31 | #if choice in ['是', 'y']: 32 | # try: 33 | # response = requests.get(spare_download_url) 34 | # filename = response.headers['Content-Disposition'].split('=')[1] 35 | # 36 | # new_filename = '中文Git.exe' 37 | # 38 | # with open(new_filename, 'wb') as f: 39 | # f.write(response.content) 40 | # 41 | # print(f"{Fore.GREEN}✓{Fore.RESET} 更新成功下载。") 42 | # 43 | # return new_filename 44 | # except Exception as e: 45 | # print(f"{Fore.RED}✕{Fore.RESET} 下载更新文件时出错: {e}") 46 | # return None 47 | exit_code = 1 48 | return None 49 | 50 | def replace_current_program(new_filename): 51 | global exit_code 52 | try: 53 | # 用下载的文件替换当前程序 54 | os.replace(new_filename, os.path.join(os.path.dirname(sys.argv[0]), "中文git.exe")) 55 | print(f"{Fore.GREEN}✓{Fore.RESET} 程序已成功更新。") 56 | except Exception as e: 57 | print(f"{Fore.RED}✕{Fore.RESET} 替换当前程序时出错: {e}") 58 | exit_code = 1 59 | 60 | if __name__ == "__main__": 61 | parser = argparse.ArgumentParser(description="打包版中文Git的更新程序") 62 | parser.add_argument("--version", type=str, required=True, help="更新到的版本") 63 | args = parser.parse_args() 64 | 65 | new_filename = download_update_file(args.version) 66 | if new_filename: 67 | replace_current_program(new_filename) 68 | 69 | input(f"按{Fore.BLUE}Enter{Fore.RESET}键退出...") 70 | 71 | sys.exit(exit_code) 72 | --------------------------------------------------------------------------------