☰
Git上传代码全流程指南:从SSH认证到分支合并一次打通
2026/10/7 3:15:50 网站建设 项目流程

作为一个常年帮团队处理代码提交问题的老鸟,我见过太多人在“git上传代码”这一步卡住:要么是装完 git 不知道从哪下手,要么是明明照着教程敲了命令却报 SSH 认证失败,还有的是代码传上去了结果把别人的提交顶掉了。最近我接了个小游戏项目,平台审核打回,要求“必须接入侧边栏复访能力,否则将被平台审核拒绝,请接入该能力后重新上传代码”。这里说的“重新上传代码”,可不是你在网页端把文件拖进去那么简单——它背后是一整套 git 流程:拉最新代码、开分支、改代码、提交、推送、合并。这篇文章我就把从 git 安装配置到最终把代码推送到 Gitee/GitHub 仓库的全过程拆开讲,重点解决 SSH 认证失败、分支合并这几个高频痛点。不管你是刚开始学 git 的新手,还是被“git 上传”折磨过几次的进阶用户,按这个流程走下来基本能一次打通。

1. 装好 git 只是开始:安装、初始化与仓库目录的正确理解

很多教程把 git 安装一笔带过,但据我观察,不少人其实卡在最开始:版本装错了、系统 PATH 没生效、甚至不知道自己把 git 装到哪去了。先把这一步走稳,后面的操作才有意义。

1.1 跨平台安装方式与版本检查

Windows 用户直接去官网下载安装包,安装时有一个容易忽略的选择项——调整 PATH 环境变量,选“Git from the command line and also from 3rd-party software”那项,保证你在 CMD 和 PowerShell 里都能直接敲git命令。macOS 用户我建议先装 Homebrew,然后执行brew install git,比去官网下 pkg 方便后续升级。Linux 用户直接用包管理器,Debian/Ubuntu 系是apt install git,CentOS/RHEL 系是yum install git。

装完别急着干活,先验证一下:

git --version

如果输出类似git version 2.39.2,说明安装成功。如果提示“command not found”,多半是 PATH 没配好,Windows 用户检查系统环境变量里有没有 git 的安装路径,macOS/Linux 检查/usr/local/bin或/usr/bin。

提示:我见过有人装了 1.8 时代的老版本,很多新命令(比如git switch、git restore)都不支持,建议至少用 2.30 以上的版本。版本太老,后面照着教程敲命令会莫名报错。

1.2 全局配置:为什么user.name和user.email必须设

git 的每次提交都会记录作者信息,这个信息不是从系统用户名自动读取的,而是从 git 配置里读。不配置的话,提交时会报“Please tell me who you are”之类的错误,然后卡住。配置命令很简单:

git config --global user.name "你的名字" git config --global user.email "你的邮箱"

--global表示对当前系统用户全局生效,一般一台机器配一次就行。这里有个细节:邮箱建议填你在 GitHub/Gitee 平台注册时用的邮箱,这样提交记录能正确关联到你的账号,不然你在平台上看到的提交者头像是个默认图形,后期统计贡献也不方便。

注意:这个配置不是用来登录平台的,它只写进提交记录里。真正的认证走的是下一章要讲的 SSH 密钥或 HTTPS 账号密码。

1.3 初始化项目:三层目录结构与日常操作流

进入项目目录执行git init,你就把当前文件夹变成了一个 git 仓库。刚 init 完你会产生一个.git隐藏目录,这里面装着版本历史、分支指针、对象数据库,别手贱去删,删了等于把整段历史都抹了。

git 把文件分成三个区域,理解这三个区域,后面所有命令都不懵:

  • 工作区:你正在编辑的普通文件夹。
  • 暂存区:git add之后文件进入的区域,相当于“候选名单”。
  • 版本库:git commit之后提交记录落库,相当于“正式存档”。

用打包寄快递来类比:工作区是你堆在地上的货,git add是把货放进纸箱,git commit是封箱贴单号,git push才是把箱子交给快递员送往远程仓库。很多人一上来就git push报错,就是因为没走完 add 和 commit,本地根本没有可推送的提交。

日常操作流就是这三板斧:改代码、git add、git commit,攒了几个提交后再git push。远程仓库没配置或 SSH 没搞定之前,本地提交是畅通无阻的,这也是 git 分布式设计的好处——离线照样能写提交。

2. SSH 认证失败这件事,九成是密钥配置的路径问题

GitHub 上传代码、Gitee 上传代码到仓库,这几年最建议的方式都是走 SSH。之所以不用 HTTPS 账号密码,是因为 SSH 密钥一次性配置好之后,每天 push/pull 都不用再输账号密码,而且密钥本身的安全性比密码强得多。但反过来说,SSH 配置环节的坑也最多,“ssh认证失败 git”这个搜索词常年挂在热榜上,说明大家普遍栽在这。

2.1 生成密钥:算法、注释与路径选择

先检查你是否已经有密钥,别重复生成覆盖掉旧密钥(覆盖后旧机器上的访问就全失效了):

ls -al ~/.ssh

如果看到id_rsa和id_rsa.pub这类文件,说明已有密钥。如果没有,生成一个新的:

ssh-keygen -t ed25519 -C "你的邮箱"

我推荐用 ed25519 算法,密钥短、安全强度够、生成快。老教程里常见的-t rsa -b 4096也能用,但 ed25519 是当前更稳的选择。-C只是加个注释标识,方便你区分这是哪台机器的密钥。

生成过程中会问保存路径和 passphrase。路径直接回车用默认的~/.ssh/id_ed25519就行。passphrase 是对私钥文件的额外加密口令,我建议设置一个,避免私钥文件被别人拷走就能直接冒用。设置之后每次用 SSH 可能要输一次口令,可以在第 2.3 节配 ssh-agent 来免输。

2.2 公钥上平台:GitHub 与 Gitee 的添加位置

密钥是成对的:私钥留在本机,公钥匙贴到平台。查看公钥内容:

cat ~/.ssh/id_ed25519.pub

把输出的整段ssh-ed25519 AAAA... 你的邮箱复制下来。GitHub 的路径是 Settings → SSH and GPG keys → New SSH key。Gitee 的路径是设置 → 安全设置 → SSH 公钥 → 添加公钥。标题随便填,比如“我的办公电脑”,公钥框粘贴刚才复制的内容。

这一步最大的坑是:复制的时候把换行、空格截断了,或者复制成了私钥(私钥是-----BEGIN OPENSSH PRIVATE KEY-----开头,带这个的千万别贴出去)。贴公钥就是贴.pub结尾那个文件的内容。

2.3 多平台多密钥管理与本地校验

如果你同时要用 GitHub 和 Gitee,或者公司内网 GitLab 和个人的 GitHub,一把密钥走天下其实有点风险。更稳的做法是给不同平台生成不同密钥,然后用~/.ssh/config文件做域名路由。比如:

# 生成 GitHub 专用密钥 ssh-keygen -t ed25519 -C "github" -f ~/.ssh/id_ed25519_github # 生成 Gitee 专用密钥 ssh-keygen -t ed25519 -C "gitee" -f ~/.ssh/id_ed25519_gitee

然后在~/.ssh/config里写:

Host github.com HostName github.com User git IdentityFile ~/.ssh/id_ed25519_github Host gitee.com HostName gitee.com User git IdentityFile ~/.ssh/id_ed25519_gitee

这样 git 连接时就会根据域名自动选择对应的密钥。想立即验证 SSH 是否配通,执行:

ssh -T git@github.com ssh -T git@gitee.com

GitHub 会返回Hi xxx! You've successfully authenticated, but GitHub does not provide shell access.;Gitee 会返回类似Hi 用户名的欢迎语。看到这个输出,SSH 认证就是通了。

如果返回Permission denied (publickey),按这条链路排查:密钥是否生成 → 公钥是否复制完整 → 私钥是否放在默认路径或 config 是否指对了IdentityFile→ssh-agent是否加载了密钥。最后一步可以执行ssh-add ~/.ssh/id_ed25519_github手动加载,再执行ssh-add -l能看到已加载的密钥列表。

3. 先有仓库再有提交:关联远程仓库与首次推送的完整动作

SSH 认证通了,等于你有了进入远程仓库的“门禁卡”。但很多人的困惑是:本地项目和远程仓库到底怎么建立联系?远程仓库里已经有的文件怎么处理?这一章我把首次推送的完整动作拆开讲。

3.1 在平台创建空仓库与远程地址的构成

以 Gitee 为例,点击“新建仓库”,填写仓库名、选择公开或私有。最关键的一步:初始化仓库时,建议先不要勾选“初始化仓库”里的那些 README、.gitignore、开源许可证选项。为什么?因为一旦平台帮你创建了这些文件,远程仓库就有了一套不属于你本地的提交历史,你本地又是干净的初始状态,第一次 push 就会撞车报“failed to push some refs”。最省心的方式:先创建一个完全空的远程仓库,等首次推送成功后,后续要加 README 或 .gitignore 再在本地补。

创建好之后,仓库页会显示一个远程地址,如果语言环境选的是 Python、Node 等,平台默认给你展示 HTTPS 地址。不要直接复制那个 HTTPS,去切换成 SSH 地址再复制,形如git@gitee.com:你的用户名/仓库名.git。如果你和我一样配了多密钥,尤其要注意复制的是 SSH 格式,不是https://gitee.com/...。

3.2 remote add、add、commit、push 一条龙

假设你已经在本地项目目录里git init过了,并且提交过几次本地 commit,现在把远程地址关联进来:

git remote add origin git@gitee.com:你的用户名/仓库名.git

origin是远程仓库的默认别名,相当于“远端主仓库”这个引用的名字。之后所有针对这个远程的操作都通过origin指代。如果提示fatal: remote origin already exists,说明你已经关联过,先执行git remote -v查看当前关联的地址,再用git remote set-url origin 新地址修正。

接着就是经典三连:

git add . git commit -m "初始化项目:接入侧边栏复访能力" git push -u origin master

第一行git add .是把当前目录所有改动放进暂存区。注意如果你在项目根目录执行,.代表当前目录,别在子目录里执行然后奇怪为什么文件没全进去。第二行git commit是把暂存区的内容固化成一次提交记录,-m后面是提交信息,这条信息要写清楚这次改了什么,方便后续回溯。第三行git push -u origin master是整个流程的临门一脚:把本地master分支推送到origin远程,-u的意思是“记住这次关联”,之后在本地master分支上直接敲git push就能推送,不用再带参数。

3.3 分支名不匹配与首次撞库的两种处理手法

如果你在 2020 年之后初始化的仓库,本地默认分支可能是main而不是master;而平台上新建仓库的默认分支可能也是main。推送时方向不对就会报error: src refspec master does not match any,意思是本地根本不存在master这个分支。用git branch -M main把本地分支重命名为main再推(-M是强制重命名,哪怕已存在的分支名也直接顶掉)。我自己习惯统一用main,因为新平台默认分支都是它,省得每次都要加-u origin指定。

如果首次推送时远程仓库已经有了提交(比如你创建仓库时勾了 README),本地会拒绝推送,提示你先 pull。两个方案:

方案一(推荐):先拉取合并,再推送。

git pull origin main --rebase git push -u origin main

--rebase意思是把你本地的提交“搬到”远程已有提交的顶端,保持历史线性,没有多余的 merge 提交。初次使用感觉有点抽象,你可以理解成:远程已经有了一本书的前言,你要把你写的内容接在后边,而不是另起一本新书把前言丢掉。

方案二(慎用):强制覆盖远程。

git push -u origin main --force

这个操作会把远程历史整个覆盖成你本地的历史,如果远程有别人的提交,会全部丢光。只在两种情况下用:远程是你个人刚建的空仓库且没被别人用、或者你明确知道自己要抛弃远程那套初始提交。团队协作时千万别用--force推公共分支。

3.4 提交信息规范与 .gitignore 的必要性

推送之前有件事容易被忽略:把该忽略的文件忽略掉。比如 Python 项目的__pycache__、Node 项目的node_modules、IDE 的.idea,这些都不该进仓库。在项目根目录创建.gitignore文件,写清楚哪些忽略:

node_modules/ dist/ .idea/ *.log

如果你把这些文件推上去了,后续团队成员 clone 下来就会看到一堆无关文件,拉取速度也被拖慢。.gitignore只对“尚未被 git 跟踪”的文件生效,如果你之前已经git add过某个文件,它就不会被忽略规则管住,得先git rm --cached 文件名把它从暂存区移除再改。

提交信息这块,建议遵守一个简单约定:类型(范围): 描述。比如fix(侧边栏): 修复复访按钮在低版本安卓上不显示、feat(登录): 增加微信一键登录。这么写的好处是后续翻git log的时候,一眼能看出每个提交改了哪块功能,做分支合并时冲突的定位也会快很多。

4. 分支合并与日常提交:团队协作场景下的 git 用法

单人项目里,一条 main 分支直推到底没啥问题。但一旦多个人协作,或者像我做小游戏这种需求有明确的“平台审核打回 → 改代码 → 重新上传”流程,分支管理就特别重要。说实话,“git分支合并”这个热搜词背后,是不少人在用最原始的方式处理多版本代码——直接在 main 上改,改坏了就回滚不了。我建议哪怕只有一个开发者,也至少养成开分支的习惯。

4.1 为什么要开分支:保护主干的完整可运行性

分支说白了就是一条独立的提交时间线。你在feature/xxx分支上改动,不影响main上其他人正在用的代码;等改动验证没问题了,再合回main。这就像你写文章时候不会在正式发布的那稿上直接修改,而是先开一个新文档写草稿,定稿后再替换进去。

创建并切换分支一步到位:

git checkout -b feature/sidebar-revisit

-b表示创建新分支并切换过去。分支名最好语义化,用/分隔类型和内容,比如feature/、fix/、docs/。切换到已有分支用git checkout 分支名,查看所有分支用git branch -a。

4.2 合并与冲突:<<<<<<< HEAD到底是什么意思

功能开发完,要在本地把feature分支合并回main:

git checkout main git pull origin main git merge feature/sidebar-revisit

git merge会把 feature 分支的提交记录“缝合”到当前分支上。如果两个分支都没有改同一个文件的同一行,git 会自动完成合并,你只需要写个合并提交信息。但如果两边同时改了同一个文件的同一区域,就会产生冲突,git 会在文件里插入冲突标记:

<<<<<<< HEAD 这里是你当前分支(main)上的内容 ======= 这里是你要合并进来的分支(feature)上的内容 >>>>>>> feature/sidebar-revisit

处理方式很直接:打开文件,这两段内容依据需求保留其一、或都保留、或手写出最终版本,然后删掉<<<<<<< HEAD、=======、>>>>>>> feature/sidebar-revisit这三行标记。最后执行git add 冲突文件再git commit,冲突就算解决完。新手第一次看到这堆符号容易慌,其实不用怕——标记只是告诉你“谁和谁冲突了”,不是代码坏了。

4.3 git pull 与 merge 的配合:避免“推送被拒”的日常操作

多人协作时,你改完代码git push,最怕的就是提示failed to push some refs,原因是远程 main 已经被别人推了新提交,而你的本地 main 落后于远程。这时候不要硬推,先拉取整合:

git pull origin main --rebase git push origin main

git pull等于git fetch加git merge;加--rebase是把你的提交重新放到远程最新提交之后,历史是一条直线。我这里有个建议:团队里固定一套约定,比如公共分支永远走 rebase 而不是 merge,这样git log --graph看下来不会出现一团乱麻。

合并完成、确认无误之后,可以删掉已经没用的分支:

git branch -d feature/sidebar-revisit git push origin --delete feature/sidebar-revisit

第一条删本地分支,第二条删远程分支。养成“功能合完就删分支”的习惯,仓库列表不会越积越乱。

4.4 平台审核打回“重新上传代码”时的标准操作流

回到文章开头那个场景。平台提示:小游戏必须接入侧边栏复访能力,否则将被平台审核拒绝,请接入该能力后重新上传代码。这里“重新上传代码”到底怎么操作?我梳理一遍我实际跑过的流程:

  1. 本地先切回主干并拉到最新:
    git checkout main git pull origin main
  2. 按需求开一个分支:
    git checkout -b feature/sidebar-revisit
  3. 在这个分支上实现侧边栏复访能力,自测通过。
  4. 提交:
    git add . git commit -m "feat(侧边栏): 接入复访能力以通过平台审核"
  5. 推到远程:
    git push -u origin feature/sidebar-revisit
  6. 在 Gitee/GitHub 上发起 Pull Request / 合并申请,或本地自行合并到 main 后推送:
    git checkout main git pull origin main git merge feature/sidebar-revisit git push origin main
  7. 回到小游戏平台的后台,用新版本代码包提交审核。

这套流程最关键的一点:不要在 main 上直接改完后推,而是走分支。为什么?因为平台审核期间你的 main 可能还挂着上一版,或者同事还在 main 上改别的需求,你在 main 上直接改会造成远程提交历史混乱。走分支可以随时切换、随时回滚,审核打回来再改也方便。

5. 上传代码报错速查表:我踩过并且帮别人排查过的问题

文章最后,我把这几年真正在“git上传代码”过程中高频出现的报错整理成一张速查表,每个错误后面附一句最可能的根因和解决方案。建议你收藏,遇到问题先来对表。

报错信息根因解决方案
fatal: not a git repository当前目录不是 git 仓库确认在项目根目录执行git init或切换到仓库目录
Permission denied (publickey)SSH 认证没通过检查密钥生成、公钥上传平台、config 文件、ssh-agent
failed to push some refs远程有本地没有的提交git pull --rebase origin main后重新 push
src refspec master does not match any本地没有 master 分支用git branch -M main改名或指定正确分支名
fatal: remote origin already exists远程 origin 已关联git remote -v查看,git remote set-url origin 新地址修正
The requested URL returned error: 403推送权限不足确认你有该仓库的写权限,检查 SSH 密钥是否属于该仓库协作者
error: failed to push some refs to ...远程仓库有 push 钩子拒绝或权限问题检查仓库保护规则,必要时联系仓库管理员
warning: LF will be replaced by CRLF换行符差异,Windows 与 Linux 混用按团队约定统一.gitattributes或git config core.autocrlf

再补一个容易被忽略的问题:git 对文件大小有限制。Gitee 单个文件超过 100MB 会直接拒绝推送,GitHub 单个文件超过 100MB 会警告、超 2GB 直接断。如果你的仓库里有大体积二进制(比如游戏打包产物、美术资源),用git lfs管理,别硬推。

最后从我自己的经验说一个小习惯:每次推送前先执行git status和git log --oneline -3,看一眼哪些文件被改、最近的提交长什么样。这两条命令不花时间,却能避免把调试代码、临时密钥文件误提交上去的尴尬。git 这东西不要怕敲命令,错误信息其实都挺直白,看懂它在抱怨什么,九成问题都能自己解决。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询