Git 命令速查表
Git 是目前最流行的分布式版本控制系统,被广泛应用于软件开发和项目管理中。本文提供了常用 Git 命令的速查表,帮助开发者快速查找和使用所需的 Git 命令。
提示
本速查表按照 Git 工作流程的不同阶段进行分类,方便查找和使用。
创建命令 (Create)
命令 | 说明 | 注意点 |
---|---|---|
git init | 初始化本地 Git 仓库 | 会在当前目录创建 .git 隐藏文件夹,包含版本库信息 |
git clone <url> | 克隆远程仓库到本地 | 默认会克隆所有分支,但只会检出主分支 |
git clone --depth=1 <url> | 浅克隆,只获取最近一次提交 | 可减少下载时间和磁盘空间,但历史记录不完整 |
git clone -b <branch> <url> | 克隆特定分支 | 直接检出指定的分支,而非默认分支 |
本地更改 (Local Changes)
命令 | 说明 | 注意点 |
---|---|---|
git status | 查看当前分支状态 | 显示工作区、暂存区的状态,包括未跟踪、已修改、已暂存的文件 |
git diff | 查看未暂存的文件更改 | 比较工作区和暂存区的差异 |
git diff --staged | 查看已暂存的文件更改 | 比较暂存区和最后一次提交的差异 |
git add <file> | 将指定文件添加到暂存区 | 可以使用通配符,如 git add *.js |
git add . | 将所有更改添加到暂存区 | 包括新文件、修改和删除,但不包括 .gitignore 中的文件 |
git add -p | 交互式添加文件的部分内容 | 允许选择文件的特定更改进行暂存,而非整个文件 |
git commit -m "message" | 提交暂存区的更改 | 提交信息应简洁明了,描述本次更改的内容 |
git commit -am "message" | 添加所有更改并提交 | 结合了 git add . 和 git commit -m 的功能,但不包括未跟踪的文件 |
git commit --amend -m "message" | 修改最近一次提交 | 会替换上一次提交,不要用于已推送到远程的提交 |
git commit --no-verify | 跳过钩子函数直接提交 | 忽略 pre-commit 等钩子检查,如 ESLint 验证 |
提交历史 (Commit History)
命令 | 说明 | 注意点 |
---|---|---|
git log | 查看提交历史 | 按时间倒序显示提交记录 |
git log -n <number> | 查看最近 n 次提交 | 限制输出数量,提高查看效率 |
git log --oneline | 以简洁模式查看提交历史 | 每个提交只显示一行,包含简短哈希值和提交信息 |
git log --graph | 以图形方式查看分支合并历史 | 直观展示分支和合并情况 |
git log --stat | 查看提交历史及文件变更统计 | 显示每次提交中修改的文件及行数变化 |
git show <commit> | 查看特定提交的详细信息 | 显示提交的元数据和内容变化 |
git blame <file> | 查看文件的每一行是谁修改的 | 显示每行代码的最后修改者和提交信息,有助于追踪问题 |
分支和标签 (Branches & Tags)
命令 | 说明 | 注意点 |
---|---|---|
git branch | 列出本地分支 | 当前分支会用星号标记 |
git branch -r | 列出远程分支 | 显示远程仓库的分支 |
git branch -a | 列出所有分支 | 包括本地和远程分支 |
git branch <branch-name> | 创建新分支 | 基于当前 HEAD 创建,但不会自动切换 |
git checkout <branch-name> | 切换到指定分支 | 会更新工作区文件为该分支的状态 |
git checkout -b <branch-name> | 创建并切换到新分支 | 结合了 branch 和 checkout 命令 |
git switch <branch-name> | 切换到指定分支 (Git 2.23+) | 比 checkout 更直观的分支切换命令 |
git switch -c <branch-name> | 创建并切换到新分支 (Git 2.23+) | 新版本的 checkout -b 替代命令 |
git branch -d <branch-name> | 删除已合并的分支 | 如果分支未合并,会拒绝删除 |
git branch -D <branch-name> | 强制删除分支 | 即使分支未合并也会删除,谨慎使用 |
git branch -m <new-name> | 重命名当前分支 | 如果新名称已存在,会拒绝重命名 |
git branch -M <new-name> | 强制重命名当前分支 | 即使新名称已存在也会重命名 |
git tag <tag-name> | 创建标签 | 在当前 HEAD 创建轻量级标签 |
git tag -a <tag-name> -m "message" | 创建带注释的标签 | 创建附注标签,包含创建者信息和日期 |
git tag -d <tag-name> | 删除标签 | 只删除本地标签,不影响远程 |
更新与发布 (Update & Publish)
命令 | 说明 | 注意点 |
---|---|---|
git remote -v | 查看远程仓库 | 显示远程仓库的 URL |
git remote add <name> <url> | 添加远程仓库 | 通常主远程仓库命名为 origin |
git fetch <remote> | 从远程获取最新代码 | 不会自动合并或修改当前工作 |
git pull <remote> <branch> | 获取并合并远程分支 | 相当于 git fetch 后跟 git merge |
git pull --rebase <remote> <branch> | 获取并变基远程分支 | 使用变基而非合并,保持线性历史 |
git push <remote> <branch> | 推送本地分支到远程 | 如果远程分支不存在,需要使用 -u 参数 |
git push -u <remote> <branch> | 推送并设置上游分支 | 设置本地分支跟踪远程分支 |
git push <remote> --tags | 推送所有标签到远程 | 默认情况下,git push 不会传送标签 |
git push <remote> --force | 强制推送 | 会覆盖远程分支,可能导致其他人的工作丢失,谨慎使用 |
git push <remote> --force-with-lease | 安全的强制推送 | 只有当远程分支没有其他人的新提交时才强制推送 |
合并与衍合 (Merge & Rebase)
命令 | 说明 | 注意点 |
---|---|---|
git merge <branch> | 合并指定分支到当前分支 | 创建一个新的合并提交 |
git merge --no-ff <branch> | 禁用快进模式合并 | 即使可以快进,也创建一个新的合并提交 |
git merge --squash <branch> | 压缩合并 | 将目标分支的所有更改作为一个提交应用 |
git rebase <branch> | 变基到指定分支 | 重放当前分支的提交到目标分支之上,创建线性历史 |
git rebase -i <commit> | 交互式变基 | 可以重新排序、合并、修改、删除提交 |
git rebase --abort | 终止变基操作 | 恢复到变基前的状态 |
git rebase --continue | 解决冲突后继续变基 | 在解决冲突并 git add 后使用 |
git cherry-pick <commit> | 应用特定提交 | 将其他分支的特定提交应用到当前分支 |
撤销操作 (Undo)
命令 | 说明 | 注意点 |
---|---|---|
git restore <file> | 丢弃工作区的修改 (Git 2.23+) | 恢复文件到上次提交的状态 |
git restore --staged <file> | 取消暂存文件 (Git 2.23+) | 将文件从暂存区移回工作区 |
git checkout -- <file> | 丢弃工作区的修改 (旧版) | 与 git restore <file> 功能相同 |
git reset <file> | 取消暂存文件 (旧版) | 与 git restore --staged <file> 功能相同 |
git reset --soft HEAD~1 | 撤销最近一次提交,保留更改 | 将提交的更改放回暂存区 |
git reset --hard HEAD~1 | 撤销最近一次提交,丢弃更改 | 完全删除最近的提交和相关更改,谨慎使用 |
git reset --hard <commit> | 重置到指定提交 | 会丢失该提交之后的所有更改,谨慎使用 |
git revert <commit> | 撤销指定提交 | 创建一个新的提交来撤销之前的更改,适合已推送的提交 |
git clean -n | 列出将被删除的未跟踪文件 | 预览模式,不会实际删除文件 |
git clean -f | 删除未跟踪的文件 | 不会删除 .gitignore 中的文件 |
git clean -fd | 删除未跟踪的文件和目录 | 包括空目录 |
暂存操作 (Stash)
命令 | 说明 | 注意点 |
---|---|---|
git stash | 暂存当前工作区的修改 | 将修改保存到一个临时区域,并恢复工作区到干净状态 |
git stash save "message" | 添加说明并暂存修改 | 便于后续识别不同的暂存内容 |
git stash list | 查看所有暂存 | 显示所有暂存的列表及其标识 |
git stash apply | 应用最近的暂存,但不删除 | 可以多次应用同一个暂存 |
git stash apply stash@{n} | 应用指定的暂存 | n 是 stash list 命令显示的索引 |
git stash pop | 应用并删除最近的暂存 | 应用后会从暂存列表中删除 |
git stash drop | 删除最近的暂存 | 不应用,直接删除 |
git stash drop stash@{n} | 删除指定的暂存 | 根据索引删除特定暂存 |
git stash clear | 删除所有暂存 | 清空整个暂存列表,谨慎使用 |
配置命令 (Configuration)
命令 | 说明 | 注意点 |
---|---|---|
git config --list | 列出所有配置 | 显示当前所有的 Git 配置项 |
git config --global user.name "Name" | 设置全局用户名 | 对所有仓库生效 |
git config --global user.email "email" | 设置全局邮箱 | 对所有仓库生效 |
git config --local user.name "Name" | 设置当前仓库用户名 | 只对当前仓库生效,优先级高于全局配置 |
git config --global core.editor "editor" | 设置默认编辑器 | 如 vim、nano、VSCode 等 |
git config --global alias.<alias> <command> | 创建命令别名 | 例如 git config --global alias.st status 设置 git st 等同于 git status |
git config --global core.autocrlf true | 自动处理行尾 | Windows 用户推荐设置为 true,Linux/Mac 用户设置为 input |
git config --global pull.rebase false | 设置 pull 策略 | 可选值:false (merge)、true (rebase)、only (fast-forward only) |
git config --global init.defaultBranch main | 设置默认分支名 | 新仓库的默认分支名,替代传统的 master |
高级操作 (Advanced)
命令 | 说明 | 注意点 |
---|---|---|
git bisect start | 开始二分查找 | 用于查找引入 bug 的提交 |
git bisect good <commit> | 标记正常的提交 | 指定一个已知正常工作的提交 |
git bisect bad <commit> | 标记有问题的提交 | 指定一个已知有问题的提交 |
git bisect reset | 结束二分查找 | 恢复到开始二分查找前的状态 |
git worktree add <path> <branch> | 添加工作树 | 在不切换分支的情况下,在另一个目录中检出不同分支 |
git worktree list | 列出所有工作树 | 显示当前仓库的所有工作树 |
git worktree remove <path> | 删除工作树 | 移除指定的工作树 |
git submodule add <url> <path> | 添加子模块 | 将其他 Git 仓库作为子目录添加到当前仓库 |
git submodule update --init --recursive | 初始化并更新所有子模块 | 克隆仓库后需要运行此命令获取子模块内容 |
git reflog | 查看引用日志 | 记录了 HEAD 和分支引用的历史变化,可用于恢复误操作 |
不常用但有用的命令 (Uncommon but Useful)
命令 | 说明 | 注意点 |
---|---|---|
git archive --format=zip HEAD -o <file.zip> | 将当前 HEAD 打包为 zip 文件 | 不包含 .git 目录,只包含文件内容 |
git shortlog -sn | 显示提交数量排名 | 按作者名字排序,显示每人的提交次数 |
git shortlog -sn --no-merges | 显示非合并提交的数量排名 | 不计算合并提交 |
git rev-parse --show-toplevel | 显示 Git 仓库的根目录 | 在子目录中执行也能正确显示项目根目录 |
git check-ignore -v <file> | 检查文件是否被 gitignore 忽略 | 显示是哪条规则导致文件被忽略 |
git update-index --assume-unchanged <file> | 忽略对已跟踪文件的更改 | 适用于本地配置文件,不希望提交更改 |
git update-index --no-assume-unchanged <file> | 恢复对文件更改的跟踪 | 取消上一个命令的效果 |
git ls-files --others --ignored --exclude-standard | 列出所有被忽略的文件 | 显示 .gitignore 中定义的被忽略文件 |
git maintenance start | 启用后台维护 | 定期优化仓库性能(Git 2.30+) |
git count-objects -v | 显示仓库中的对象数量和大小 | 用于检查仓库大小和垃圾收集状态 |
git fsck | 检查仓库完整性 | 验证对象存储的一致性 |
git gc | 垃圾收集,优化仓库 | 清理不必要的文件并优化本地仓库 |
git prune | 删除所有不可达的对象 | 通常由 git gc 自动调用 |
git verify-pack -v .git/objects/pack/pack-*.idx | 查看打包的对象 | 分析仓库中最大的文件 |
git diff-tree --no-commit-id --name-only -r <commit> | 列出提交中更改的文件 | 不显示具体更改内容,只列出文件名 |
git show-ref | 显示本地引用 | 列出所有分支和标签的 SHA-1 值 |
git grep -n "pattern" | 在代码中搜索模式 | 显示匹配行号,支持正则表达式 |
git grep --count "pattern" | 统计模式出现次数 | 按文件显示匹配次数 |
git rerere | 重用已记录的冲突解决方案 | 自动解决之前已解决过的冲突 |
git filter-branch | 重写历史 | 可以从历史中删除大文件或敏感信息,但推荐使用 git-filter-repo 替代 |
git notes add -m "note" <commit> | 为提交添加注释 | 不改变提交本身,但添加额外信息 |
git notes show <commit> | 显示提交的注释 | 查看之前添加的注释 |
git bundle create <file> <git-rev-list-args> | 创建仓库的捆绑包 | 用于在没有网络连接的情况下传输 Git 数据 |
git bundle verify <file> | 验证捆绑包的有效性 | 检查捆绑包是否完整可用 |
git instaweb | 启动基于 web 的 Git 仓库浏览器 | 在本地启动一个 web 服务器来浏览仓库 |
git credential-cache exit | 清除凭证缓存 | 强制 Git 在下次操作时重新请求凭证 |
git interpret-trailers | 操作提交消息尾部 | 用于添加或解析结构化信息 |
git range-diff <old-range> <new-range> | 比较两个提交范围的差异 | 用于查看变基前后的变化 |
git column | 以列格式显示数据 | 用于格式化输出 |
git merge-base <commit1> <commit2> | 查找两个提交的共同祖先 | 确定分支分叉点 |
更多专业命令 (More Advanced Commands)
命令 | 说明 | 注意点 |
---|---|---|
git symbolic-ref HEAD | 显示当前分支的引用 | 通常用于脚本中检测当前分支 |
git rev-list --count HEAD | 计算当前分支的提交数量 | 可用于生成版本号 |
git rev-list --all --objects | 列出所有对象 | 查看仓库中的所有对象,包括文件内容 |
git diff-index --quiet HEAD -- | 检查工作区是否干净 | 常用于脚本中,返回值表示是否有更改 |
git for-each-ref --sort=-committerdate refs/heads/ | 按提交日期排序显示分支 | 查看最近活跃的分支 |
git for-each-ref --format='%(refname:short)' refs/heads/ | 以简短格式列出所有分支 | 用于脚本处理分支名称 |
git log --follow <file> | 查看文件的历史,包括重命名 | 跟踪文件的完整历史记录 |
git log -S"<string>" | 搜索提交历史中的字符串 | 查找添加或删除特定代码的提交 |
git log -G"<regex>" | 使用正则表达式搜索提交历史 | 比 -S 更灵活的搜索方式 |
git log --first-parent | 只显示第一父提交的历史 | 在使用合并策略的项目中查看主线历史 |
git log --merges | 只显示合并提交 | 查看所有合并操作的历史 |
git log --no-merges | 不显示合并提交 | 只查看实际的代码变更提交 |
git log --cherry-pick --right-only <branch1>...<branch2> | 显示在 branch2 中但不在 branch1 中的提交 | 查看分支间的独有提交 |
git cat-file -p <object> | 显示 Git 对象的内容 | 查看 blob、树或提交对象的内容 |
git cat-file -t <object> | 显示 Git 对象的类型 | 确定对象是 blob、树还是提交 |
git ls-tree -r HEAD | 列出当前提交中的所有文件 | 显示 Git 仓库中的文件结构 |
git hash-object <file> | 计算文件的 Git 对象 ID | 不将对象存储到仓库中 |
git write-tree | 将当前索引写入树对象 | 创建一个树对象而不创建提交 |
git commit-tree <tree> -p <parent> -m "<message>" | 从树对象创建提交 | 手动创建提交对象 |
git update-ref refs/heads/<branch> <commit> | 更新分支引用 | 手动修改分支指向的提交 |
git show-branch | 显示分支及其提交 | 比较多个分支的历史 |
git name-rev --name-only <commit> | 查找提交在哪个分支或标签中 | 将 SHA-1 转换为更易读的名称 |
git describe --tags | 生成最近标签的描述 | 常用于版本号生成 |
git verify-commit <commit> | 验证提交的 GPG 签名 | 检查提交是否经过签名验证 |
git annotate <file> | 显示文件的每一行的作者和修改时间 | 类似 git blame 但格式不同 |
git difftool | 使用外部工具查看差异 | 需要先配置 difftool |
git mergetool | 使用外部工具解决合并冲突 | 需要先配置 mergetool |
git daemon | 启动一个 Git 服务器 | 用于临时共享仓库 |
git send-email | 通过电子邮件发送补丁 | 用于没有 Pull Request 的工作流 |
git am <mbox> | 应用邮件格式的补丁 | 配合 git format-patch 使用 |
git format-patch <range> | 生成邮件格式的补丁文件 | 用于通过电子邮件共享更改 |
git request-pull <start> <url> [<end>] | 生成拉取请求摘要 | 用于没有 GitHub/GitLab 的环境 |
git svn | Git 与 Subversion 仓库交互 | 用于迁移或与 SVN 协作 |
git p4 | Git 与 Perforce 仓库交互 | 用于迁移或与 Perforce 协作 |
git fast-export | 导出仓库为快速导入格式 | 用于仓库迁移 |
git fast-import | 从快速导入格式导入仓库 | 用于仓库迁移 |
git filter-repo | 重写仓库历史 | 比 filter-branch 更高效,需要单独安装 |
git replace <object> <replacement> | 替换一个对象 | 不改变历史的情况下修改提交 |
git quiltimport | 从 quilt 补丁系列导入 | 用于将补丁系列转换为 Git 提交 |
git subtree | 管理项目中的子项目 | 子模块的替代方案 |
git worktree prune | 清理过期的工作树 | 删除不再存在的工作树记录 |
git repack | 重新打包仓库对象 | 优化仓库存储 |
git pack-refs | 打包引用 | 提高引用访问性能 |
git multi-pack-index | 创建多包索引 | 提高大型仓库性能 (Git 2.21+) |
Git 术语参考
术语 | 说明 |
---|---|
repository | 仓库,包含项目的所有文件和完整历史记录 |
commit | 提交,Git 中的基本单位,代表项目在某个时间点的快照 |
branch | 分支,指向特定提交的可移动指针 |
tag | 标签,指向特定提交的固定指针,通常用于标记版本 |
HEAD | 指向当前工作区所基于的提交,通常是当前分支的最新提交 |
working directory | 工作区,实际的文件目录 |
staging area | 暂存区,准备提交的文件集合 |
remote | 远程仓库,托管在服务器上的 Git 仓库 |
fork | 复刻,创建远程仓库的副本到自己的账户下 |
pull request | 拉取请求,请求原始仓库接受你的更改 |
merge | 合并,将一个分支的更改整合到另一个分支 |
rebase | 变基,将一系列提交移动或结合到新的基础提交上 |
cherry-pick | 挑选,将特定提交应用到当前分支 |
conflict | 冲突,当两个分支对同一文件的同一部分进行不同的修改时发生 |
注意
Git 是一个强大的工具,某些命令(如 reset --hard
、push --force
)可能会导致数据丢失。在执行这些命令前,请确保理解其影响,并考虑先备份重要数据。
常见工作流程
基本工作流
- 克隆仓库:
git clone <url>
- 创建功能分支:
git checkout -b feature/new-feature
- 修改代码并提交:
sh
git add .
git commit -m "Add new feature"
- 推送到远程:
git push -u origin feature/new-feature
- 创建 Pull Request(在 GitHub/GitLab 等平台上操作)
- 合并后删除分支:
sh
git checkout main
git pull
git branch -d feature/new-feature
修复紧急问题
- 从主分支创建修复分支:
sh
git checkout main
git checkout -b hotfix/critical-bug
- 修复问题并提交:
sh
git add .
git commit -m "Fix critical bug"
- 推送到远程并创建 Pull Request:
git push -u origin hotfix/critical-bug
- 合并到主分支后,同步到开发分支:
sh
git checkout develop
git merge main
git push
Git Flow 工作流
适用于有计划发布周期的大型项目,包含五种类型的分支:
- 主分支 (main/master):存储官方发布历史
- 开发分支 (develop):集成功能分支的最新开发变更
- 功能分支 (feature/):开发新功能
- 发布分支 (release/):准备新的生产发布
- 修复分支 (hotfix/):快速修复生产问题
Git Flow 工作流模型: Git Flow 工作流模型 Git Flow 命令速查表: Git Flow 命令速查表
基本流程:
shell
# 创建开发分支
git checkout -b develop main
# 创建功能分支
git checkout -b feature/new-feature develop
# 完成功能开发后合并回开发分支
git checkout develop
git merge --no-ff feature/new-feature
git branch -d feature/new-feature
git push origin develop
# 创建发布分支
git checkout -b release/1.0.0 develop
# 发布准备完成后合并到主分支和开发分支
git checkout main
git merge --no-ff release/1.0.0
git tag -a v1.0.0 -m "Version 1.0.0"
git checkout develop
git merge --no-ff release/1.0.0
git branch -d release/1.0.0
# 创建热修复分支
git checkout -b hotfix/1.0.1 main
# 修复完成后合并到主分支和开发分支
git checkout main
git merge --no-ff hotfix/1.0.1
git tag -a v1.0.1 -m "Version 1.0.1"
git checkout develop
git merge --no-ff hotfix/1.0.1
git branch -d hotfix/1.0.1
GitHub Flow 工作流
简化版的工作流,适合持续部署的项目:
GitHub Flow 官方文档: GitHub Flow 官方文档
- 从主分支创建功能分支
- 提交更改并推送到远程
- 创建 Pull Request 并讨论更改
- 部署到测试环境验证
- 合并到主分支并部署
shell
# 创建功能分支
git checkout -b feature/new-feature main
# 提交更改
git add .
git commit -m "Add new feature"
# 推送到远程
git push -u origin feature/new-feature
# 创建 Pull Request (在 GitHub 上操作)
# 合并后删除分支
git checkout main
git pull
git branch -d feature/new-feature
GitLab Flow 工作流
结合了 Git Flow 和 GitHub Flow 的优点,增加了环境分支:
GitLab Flow 官方文档: GitLab Flow 官方文档
- 主分支 (main):包含可部署到生产的代码
- 环境分支 (production, staging):反映部署状态
- 功能分支:从主分支创建,完成后合并回主分支
shell
# 创建功能分支
git checkout -b feature/new-feature main
# 提交更改
git add .
git commit -m "Add new feature"
# 推送到远程
git push -u origin feature/new-feature
# 创建 Merge Request (在 GitLab 上操作)
# 合并到主分支后,再合并到环境分支
git checkout production
git merge --no-ff main
git push origin production
变基工作流 (Rebase Workflow)
保持线性历史记录的工作流:
- 从主分支创建功能分支
- 提交更改到功能分支
- 在推送前先变基到最新的主分支
- 创建 Pull Request 并合并(通常使用快进合并)
shell
# 创建功能分支
git checkout -b feature/new-feature main
# 提交更改
git add .
git commit -m "Add new feature"
# 获取最新的主分支
git fetch origin main
# 变基到最新的主分支
git rebase origin/main
# 解决冲突(如果有)
git add .
git rebase --continue
# 推送到远程(可能需要强制推送)
git push -u origin feature/new-feature --force-with-lease
# 合并到主分支(快进合并)
git checkout main
git merge feature/new-feature
git push origin main
中心化工作流 (Centralized Workflow)
最简单的工作流,适合小团队:
- 所有开发者直接在主分支上工作
- 提交前先拉取最新更改
- 解决冲突后推送更改
shell
# 拉取最新更改
git pull origin main
# 修改代码并提交
git add .
git commit -m "Make changes"
# 再次拉取(可能需要解决冲突)
git pull origin main
# 推送更改
git push origin main
分叉工作流 (Forking Workflow)
适合开源项目和大型团队:
- 开发者 fork 主仓库
- 克隆自己的 fork 到本地
- 添加原始仓库为远程上游
- 创建功能分支并开发
- 推送到自己的 fork
- 创建 Pull Request 到原始仓库
shell
# 克隆自己的 fork
git clone https://github.com/your-username/project.git
# 添加上游仓库
git remote add upstream https://github.com/original-owner/project.git
# 创建功能分支
git checkout -b feature/new-feature
# 提交更改
git add .
git commit -m "Add new feature"
# 推送到自己的 fork
git push -u origin feature/new-feature
# 创建 Pull Request (在 GitHub 上操作)
# 同步上游更改
git fetch upstream
git checkout main
git merge upstream/main
git push origin main