记得我第一次在一台刚装好系统的 Linux 机器上折腾 git 推送,以为就是 git add、git commit、git push 三连,结果整整卡了一个下午。先后踩了"密码输错""远程仓库有文件导致推送被拒""每次都要输入账号密码"三个坑,最后还被 Gitee 的单文件大小限制教育了一回。后来仔细梳理了一遍整套流程,才发现这些坑背后其实都有非常明确的原理,搞懂了之后,Linux 上向 Gitee 推送代码这件事,就变成了再简单不过的日常操作。
这篇文章我按照从零到一的顺序,把整个链路拆开讲清楚:git 怎么装、配置怎么填、仓库怎么建、第一次推送怎么走通、日常推送怎么规范操作、免密怎么配置,以及最常见的报错怎么排查。内容不深,但足够全,新手上路看这一篇基本够用;老手也可以直接跳到最后两章,看看有没有自己还没踩过的坑。
1. 环境准备:git 安装、基础配置与 Gitee 仓库创建
1.1 检查系统里有没有 git,没有就装
Linux 发行版众多,但大部分系统在最小化安装时并不会预装 git。第一步先确认一下:
bash复制git --version
如果返回类似 git version 2.40.1 的信息,说明已经装好了。如果提示 command not found,那就需要安装。
安装方式根据你的发行版选:
bash复制# Ubuntu / Debian 系列
sudo apt update
sudo apt install git -y
# CentOS / RHEL / Rocky Linux 系列
sudo yum install git -y
# Fedora
sudo dnf install git -y
# Arch Linux
sudo pacman -S git
这里有个小建议:如果你的系统是 CentOS 7 这类老旧版本,默认源里的 git 版本可能比较老(甚至停留在 1.8.x),部分新特性用不了。遇到这种情况,可以考虑用 softwarecollections(SCL)或者直接源码编译新版本,但如果只是日常推送代码,老版本其实也够用,不必强求。
1.2 配置用户名和邮箱,这一步不能省
git 的每一次提交都会记录作者信息,这个信息就来自全局配置。如果不配置,提交时会提示你补全,而且很多 CI/CD 工具、Gitee 的提交统计也会依赖这个信息。
bash复制git config --global user.name "你的名字"
git config --global user.email "你的邮箱"
这里有一个容易忽略的细节:邮箱建议使用注册 Gitee 时使用的邮箱,这样 Gitee 后台才能把提交记录正确关联到你的账号。如果你用的是其他邮箱,提交能成功,但 GitHub 或 Gitee 上可能不会显示你的头像,也不会计入你的贡献图。
验证配置是否生效:
bash复制git config --global --list
如果你是第一次在 Linux 上使用 git,可能还会遇到换行符、文件权限之类的问题。这里推荐在全局配置里加上一行,避免日后跨平台协作时出现无意义的 diff:
bash复制git config --global core.autocrlf input
这是让 git 在提交时把 CRLF 自动转为 LF,适合 Linux 上使用、同时可能跟 Windows 同事协作的场景。
1.3 在 Gitee 上创建远程仓库
这一步是图形化操作,直接在浏览器里完成。登录 Gitee 后,点击右上角的"+"号,选择"新建仓库"。
创建仓库时有几个选项需要你决策:
| 配置项 | 建议值 | 原因 |
|---|---|---|
| 仓库名称 | 英文小写,用连字符分隔 | 会和仓库地址直接挂钩,尽量别用中文 |
| 开源许可证 | 根据需求选,不知道怎么选就暂不选择 | 这里有个常见误区,见下文 |
| 初始化仓库 | 建议勾选"初始化仓库",但要配合阅读 README 使用 | 如果你是先有本地代码再建远程仓库,就不要勾选 |
| 选择分支模型 | 默认 master 或 main 均可 | 现代项目建议 main |
关于开源许可证,热搜词里也有"gitee开源许可证选什么"。这里简单说一下:MIT 是最宽松的,允许别人任意使用、修改、商用,只要保留版权声明;GPL-3.0 是"传染性"协议,用了它就必须开源;Apache-2.0 介于两者之间,附带专利授权条款。如果你的项目只是个人练习或者不想管这些事,先不选许可证完全没问题。
如果你已经有本地代码仓库,建议创建远程仓库时不要勾选"使用 Readme 文件初始化这个仓库"。原因后面会专门讲——远程仓库如果有提交记录,第一次推送时大概率会遇到 failed to push some refs 的错误。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 第一次推送:完整走通本地到 Gitee 的整个过程
2.1 场景不同,起步方式就不同
第一次推送要分两种场景来看。第一种是你要在 Gitee 上新建一个仓库来存放已有代码;第二种是你要把 Gitee 上已经存在的仓库拉到本地。
这里重点讲第一种,因为这是最常遇到的情况,而且坑最多。
假设你本地已经有一个项目目录,比如 /home/user/myproject:
bash复制cd /home/user/myproject
git init
此时 git 会把这个目录变成仓库,并生成一个隐藏的 .git 目录。注意:git init 只会创建本地仓库,它跟远程仓库还没有任何关系。
接着把项目文件加入暂存区并提交:
bash复制git add .
git commit -m "init project"
这里解释一下 add 和 commit 的关系。git add 是把文件加入"暂存区"(staging area),相当于告诉 git"这些文件我要纳入版本管理了";git commit 则是把暂存区的内容真正提交到本地仓库,形成一个不可变的版本快照。
首次提交遇到的问题往往是:新机器上没配置用户信息,或者 .gitignore 文件没有提前写好,把不该提交的 node_modules、编译产出物、密钥文件都加进去了。这虽然不会导致推送失败,但会让仓库变得臃肿,后面清理起来非常麻烦。所以 git init 之后的第一件事,应该是先写一份 .gitignore 再 add。
一个最简单的 Java 项目 .gitignore 示例:
gitignore复制target/
*.class
*.log
.idea/
*.iml
.vscode/
.DS_Store
2.2 关联远程仓库
现在去 Gitee 上把仓库建好(不要勾选初始化 README),创建完成后页面会显示远程仓库地址,一般长这样:
code复制https://gitee.com/你的用户名/myproject.git
在本地执行关联操作:
bash复制git remote add origin https://gitee.com/你的用户名/myproject.git
origin 是这个远程仓库在本地的一个别名,完全可以用其他名字,但业界惯例就是叫 origin,不建议特立独行。关联完之后可以用 git remote -v 查看是否成功。
如果你创建远程仓库时不小心勾选了"初始化仓库",此时本地和远程都有各自的提交历史,git 会认为它们是两个不相关的仓库。这种情况下推送会被拒绝,解决办法是用 pull --rebase 把远程历史合并下来,然后才能推送。这个场景我放在第 5 章展开讲。
2.3 第一次 push,注意凭证问题
关联好远程仓库之后,执行:
bash复制git push -u origin master
参数 -u 的意思是设置上游分支。设置了之后,以后直接执行 git push、git pull 就能自动关联到当前分支对应的远程分支,不用再写全命令。
第一次推送到 Gitee 时,大概率会遇到这样的界面提示:
code复制Username for 'https://gitee.com': 你的用户名
Password for 'https://你的用户名@gitee.com':
这里有一个很重要的坑:这个 Password 不是你的登录密码,而是私人令牌(Private Token)。Gitee 出于安全考虑,已经不再支持在命令行里直接使用账号密码进行 git 操作,你必须先在 Gitee 网页端生成一个私人令牌。路径是:Gitee 右上角头像 -> 设置 -> 安全设置 -> 私人令牌 -> 生成新令牌。
生成令牌的时候可以设置过期时间和权限范围。如果只是用来推送代码,勾选 projects 相关的权限就行。生成之后要立刻复制保存,因为页面刷新后就不再显示完整内容。
复制令牌后,在刚才的 Password 提示处粘贴进去,回车就能推送成功。
这一步成功之后,你的代码就第一次进入 Gitee 了。打开 Gitee 仓库页面,就能看到刚才提交的文件。这个"第一次"的里程碑很重要,后面的所有操作都基于这条已经打通的链路。
3. 日常推送操作:分支、提交规范与拉取合并
3.1 一套日常推送的完整指令节奏
第一次推送走通之后,日常的推送节奏会稳定成下面这样:
bash复制# 看看当前改动了什么
git status
# 把文件加入暂存区,可以用文件名替代 . 实现精确控制
git add .
# 提交,附上清晰的提交信息
git commit -m "feat: 添加用户注册功能"
# 推送到远程
git push
这里建议在 commit 之前先执行 git diff --cached 看一下即将提交的改动内容,避免把调试代码、print 输出、敏感信息一起提交上去。我见过太多人直接 git add . 然后 git commit,结果把 .env 文件里的数据库密码直接推到公开仓库,这种事故在 Gitee 上一点也不罕见。
:q! 这种按键组合则是另一个极端——有人一执行 git commit(不带 -m)就不知道该怎样退出编辑器。git 默认打开的编辑器是 vi,如果你不熟悉它,建议先把默认编辑器改成 nano 或者其他你熟悉的:
bash复制git config --global core.editor nano
3.2 分支操作:不要直接在主分支上裸奔
很多新手在自己的项目上一直是"一条 master 走天下",这当然可以,但一旦涉及协作,或者你想在 Gitee 上做 Pull Request(PR)流程,分支就必不可少。
bash复制# 基于当前分支创建新分支并切换过去
git checkout -b feature/login
# 开发完成后推送到远程
git push -u origin feature/login
# 切回主分支
git checkout master
# 把功能分支合并进来
git merge feature/login
# 推送合并结果
git push
这个流程在团队协作中非常常见。合并后功能分支如果没有保留的必要,可以删除本地分支和远程分支:
bash复制git branch -d feature/login
git push origin --delete feature/login
需要注意的是,-d 只在分支被完全合并时才会安全删除。如果你在分支上还有未合并的提交,git 会拒绝删除并提示你使用 -D 强制删除。这里我强烈建议在确认不需要之后再用 -D,因为被删掉的分支上的提交会逐步被垃圾回收机制回收,很难找回。
3.3 推送前先拉取,避免覆盖别人的改动
单人使用仓库时,pull 和 push 之间没什么矛盾。但一旦多人协作,或者你同时在另一台电脑上提交了代码,就必须面对本地和远程历史不一致的情况。
正确节奏是:
bash复制# 推送前先拉取远程最新内容
git pull
# 如果 pull 时发生了冲突,解决冲突后再提交推送
git push
git pull 本质上是 git fetch 加上 git merge 的组合。fetch 只是把远程的提交记录下载下来,不会改动你的工作区;merge 才会把远程分支合并进你当前的分支。
如果在 pull 时两个人都修改了同一个文件的同一行,git 会提示冲突。此时冲突区域会以 <<<<<<< HEAD 和 >>>>>>> 的标记形式显示在文件里,你需要手动决定保留哪份改动,或者融合两份改动。解决完成后:
bash复制git add 冲突文件
git commit
这段冲突处理流程很多人第一次遇到时都会慌,其实原理很简单:git 只是把决定权还给你了,你编辑文件、标记为已解决、提交,就完事了。
3.4 提交信息怎么写,才能让历史可读
git 的提交历史本身就是项目文档。我看到过太多 update、aaa、111 这类毫无信息量的提交信息,到了需要回溯问题时痛苦万分。
推荐采用"约定式提交"的写法,格式如下:
code复制<type>[optional scope]: <description>
常见的 type 包括:
feat: 新功能fix: 修复 Bugdocs: 文档变更style: 格式调整(不影响代码运行的变动)refactor: 重构(既不是修 Bug 也不是加功能)test: 添加或修改测试chore: 构建过程或辅助工具的变更
举例:
bash复制git commit -m "fix: 修复用户登录时验证码过期未提示的问题"
git commit -m "feat: 新增文章导出为 PDF 功能"
git commit -m "docs: 更新 README 部署说明"
养成写规范提交信息的习惯之后,后续用 git log --oneline 查看历史、用 git blame 定位问题、生成 changelog,都会顺畅很多。
4. 免密推送:从每次输令牌到配置 SSH Key
4.1 为什么需要免密配置
第一次推送时,你输了一次用户名和令牌。如果你以为以后每次都这么输,那用不了多久就会觉得很烦。尤其是推送到一半,终端提示输入密码,你手边没有令牌文本,还得去网页重新生成——这种体验实在糟糕。
其实 git 支持两种免密方案:HTTPS 凭据存储和 SSH 公钥认证。我在生产环境中两种都用过,各有利弊,下面分别说。
4.2 方案一:HTTPS 加凭据存储
如果你的远程仓库地址是 https:// 开头的,可以启用凭据存储模块,让 git 自己记住令牌:
bash复制git config --global credential.helper store
这条命令的意思是:第一次输入用户名和令牌后,git 会把凭据明文保存在 ~/.git-credentials 文件里,之后推送就不用再输入了。
还有一个更安全的变体是 cache,它会在一段时间内把凭据保存在内存中:
bash复制git config --global credential.helper 'cache --timeout=3600'
这样设置后,一小时内的推送不需要重复输入。
对比一下:store 最方便但最不安全,因为令牌是明文存在的;cache 相对安全一些,但过期后要重新输入。如果你只是在自己的个人电脑上使用,store 完全可以接受;如果是多人共用的服务器,强烈建议用 cache 或者直接上 SSH Key。
4.3 方案二:SSH Key,更推荐的长期方案
SSH 方式的核心是"公钥放在 Gitee 上,私钥留在本地",推送时通过密钥对完成身份认证,不需要密码,也不需要令牌。
先在本地生成密钥对:
bash复制ssh-keygen -t ed25519 -C "你的邮箱"
这里推荐使用 ed25519 算法,比传统的 rsa 更安全、更短。如果你的系统版本较老,不支持 ed25519,可以用:
bash复制ssh-keygen -t rsa -b 4096 -C "你的邮箱"
生成过程中会询问你保存路径和 passphrase,路径保持默认(~/.ssh/id_ed25519)即可。passphrase 可以直接回车跳过,但如果追求安全,可以设置一个短语来保护私钥。
然后查看公钥内容:
bash复制cat ~/.ssh/id_ed25519.pub
复制输出的全部内容,去 Gitee 的设置页面 -> SSH 公钥 -> 添加公钥,粘贴保存。
接下来,把远程仓库地址从 HTTPS 改成 SSH:
bash复制git remote set-url origin git@gitee.com:你的用户名/myproject.git
验证一下配置:
bash复制ssh -T git@gitee.com
出现类似"Hi 用户名! You've successfully authenticated"的提示,说明 SSH 配置成功。此时再执行推送:
bash复制git push
全程无需输入任何密码和令牌,清爽得很。
4.4 两种免密方案的适用场景对比
| 对比维度 | HTTPS + credential helper | SSH Key |
|---|---|---|
| 配置难度 | 低,一条命令搞定 | 中等,需要生成密钥并配置公钥 |
| 安全性 | token 明文存储在本地 | 私钥文件受本地文件权限保护 |
| 多设备支持 | 每台设备都要输一次 token | 每台设备单独生成密钥对 |
| 公司内网代理环境 | 兼容性好 | 可能受代理限制 |
| 建议场景 | 个人电脑、快速上手 | 长期使用、服务器部署、多人协作 |
从我的实践体验来说,个人电脑上直接用 SSH 方式一劳永逸;如果公司网络有代理,SSH 的 22 端口被限制,那就只能走 HTTPS 加凭据存储。
5. 推送失败排查手册:这些报错我都替你踩过了
5.1 Authentication failed:用户名或令牌不对
推送时报:
code复制remote: Authentication failed. If you use basic authentication, the password should be a Private Token instead of the account password.
fatal: Authentication failed for 'https://gitee.com/xxx.git/'
这个报错的唯一原因就是身份认证没通过。先确认用户名没错(注意不是邮箱),再确认使用的是私人令牌而不是登录密码。如果令牌过期了,重新生成一个再推。
如果你确认用户名和令牌都没问题,但仍然报这个错,检查一下全局配置里有没有历史遗留的代理或凭据冲突:
bash复制git config --global --list | grep -i credential
把冲突的配置清掉再试。
5.2 failed to push some refs:远程有本地没有的记录
这个报错是新手遇到最多的:
code复制 ! [rejected] master -> master (fetch first)
error: failed to push some refs to 'https://gitee.com/xxx.git'
hint: Updates were rejected because the remote contains work that you do
hint: not have locally.
原因就是远程仓库存在你的本地仓库没有的提交。最典型的情况就是创建 Gitee 仓库时勾选了"初始化仓库",远程生成了 README 或 LICENSE 文件。
解决办法:
bash复制git pull --rebase origin master
git push
--rebase 的作用是把本地提交"重新播放"到远程提交的后面,让提交历史变成一条直线,不会产生多余的 merge commit。如果你不介意历史里多一条 merge 记录,直接用 git pull 也行。
有些人担心 rebase 会不会丢代码,其实不会,它只是重新整理提交的顺序。真正会丢代码的操作是 git push --force,所以强推要非常谨慎,除非你明确知道自己在干什么。
5.3 文件太大被拒绝:Gitee 单文件限制
Gitee 对单文件大小有上限(单文件 100MB,仓库总大小 1GB 左右)。推送超过限制的文件会报:
code复制remote: error: File xxx.zip is 152.00 MB; this exceeds Gitee's file size limit of 100 MB
这类问题很常见,尤其是做多媒体项目、游戏素材、设计源文件时。
处理思路:
- 如果该文件不应该放进仓库,从 git 历史里彻底移除,可以使用
git filter-branch或者 BFG Repo-Cleaner; - 如果文件确实需要用,可以考虑 Git LFS(Large File Storage)。
这里特别提醒一句:不要以为把文件从目录里删掉重新 commit 就没事了,之前的历史提交里还躺着那个大文件,仓库大小不会真正变小。要彻底解决必须重写历史,这会让所有 clone 过这个仓库的人需要重新同步,所以操作前一定要和协作者沟通。
5.4 Connection refused 或超时:网络链路问题
如果推送时报:
code复制fatal: unable to access 'https://gitee.com/xxx.git/': Failed to connect to gitee.com port 443: Connection refused
大概率是网络问题。检查思路:
bash复制# 测试域名能否解析
ping gitee.com
# 测试端口能否连通
telnet gitee.com 443
如果 ping 通但 telnet 不通,说明 443 端口被限制,常见于公司内网、校园网。如果域名解析都有问题,检查 DNS 配置:
bash复制cat /etc/resolv.conf
一个我经常遇到的情况是:在 Linux 服务器上配置了 http_proxy 环境变量,但代理服务已经挂了,导致 git 走代理访问失败。排查时可以临时关掉代理试试:
bash复制unset http_proxy
unset https_proxy
git push
5.5 明明推上去了,Gitee 上怎么看不到
推送成功后去 Gitee 网页上看,却发现文件不对或提交记录缺失。这种情况大概率是你推送的不是默认分支。
检查本地当前分支:
bash复制git branch
git branch -a
如果你推的是 feature/login 分支,去 Gitee 仓库页面需要手动切换到对应分支才能看到。如果希望这个分支成为默认分支,需要在 Gitee 仓库设置里修改默认分支。
还有一种情况是推送到了别的远程仓库地址。检查一下:
bash复制git remote -v
看看 origin 是否指向你预期的那一个仓库。
5.6 子模块或符号链接引发的奇怪问题
如果你在仓库里添加了一个 git 子模块(submodule),推送父仓库时子模块的内容不会自动推送。如果协作者 clone 后拉不下来子模块,会报各种奇怪的错误。正确做法是先推送子模块,再推送父仓库,并确保子模块的远程仓库地址对协作者可访问。
另外,Linux 上的符号链接在 git 里保存的是链接本身,而不是链接指向的文件内容。如果你把一个 /root/important.txt 的软链接 add 进仓库,其他人 clone 后打开这个链接会发现目标不存在。这类问题排查起来极其耗时,所以最好在项目规范里明确规定不要提交符号链接。
6. 效率提升:几个让推送更顺手的小配置
6.1 给常用命令设置别名
Linux 终端里全拼命令输入其实不慢,但有些组合命令每次都要输入一串,还是容易烦。配置别名是个性价比很高的习惯:
bash复制git config --global alias.st status
git config --global alias.co checkout
git config --global alias.cm "commit -m"
git config --global alias.lg "log --oneline --graph --decorate -10"
git config --global alias.last "log -1 --stat"
配置之后,git cm "fix: xxx" 和 git lg 就都能用了。
6.2 用 .gitignore 省掉没必要的提交
在项目目录里维护一份合理的 .gitignore,能避免很多无意义的 diff 和误提交。除了前面提到的编译产物,下面这些类型也应该考虑加进去:
gitignore复制# 环境配置文件
.env
.env.local
*.pem
*.key
# 打包产物
dist/
build/
*.tar.gz
*.zip
# 日志
*.log
logs/
# 本地编辑器配置
.idea/
.vscode/
*.swp
注意 .gitignore 只对"未被追踪"的文件生效。如果你之前已经把某个文件提交进仓库了,后来才把它加进 .gitignore,它是不会自动被忽略的。你需要把该文件从 git 追踪中移除:
bash复制git rm --cached .env
git commit -m "chore: 停止追踪 .env 文件"
--cached 参数的意思是只从 git 的追踪列表里移除,保留本地文件。
6.3 一次提交只做一个逻辑改动
这个建议不涉及任何配置,但对维护体验影响巨大。我见过有人提交信息写 fix: 修复登录问题,实际改动里却混入了无关联的重命名、格式调整、依赖变更。三个月之后你回来看这次提交,根本没法定位真正改了哪一行。
正确的做法是:每个提交尽量只包含"一个逻辑变更"。比如修复了 Bug A,就只提交和 Bug A 相关的文件;开发了功能 B,就只提交功能 B 的改动。如果工作区很混乱,可以用 git add <具体文件> 而不是 git add . 来精确控制。
6.4 远程仓库的选择:Gitee、GitHub 还是自建
这个问题经常有人问。在 Gitee 上托管,优势是国内的访问速度快、中文界面、无需过多网络层面的折腾;如果是开源国际项目,GitHub 生态更丰富。实际工作中最常见的形态是:代码在 GitHub 上开源,Gitee 上做同步镜像,这样两边都能访问。同步操作也很简单:
bash复制# 添加一个额外的远程仓库
git remote add gitee https://gitee.com/你的用户名/myproject.git
# 推送代码到 Gitee
git push gitee master
我个人在实际使用中的体会是,工具本身并不是瓶颈,真正影响开发和协作效率的是提交习惯、分支意识以及对报错信息的理解能力。这套流程跑熟之后,你会发现 git 推送其实完全没有想象中的复杂——每一条报错背后都有明确的原因,每一个原因都有对应的解决方案。希望这篇整理能帮你少走一些我当年走过的弯路。
