从Windows换到Mac之后我第一件头疼的事就是把本地代码推到码云上去。之前习惯了图形界面突然面对终端里的git命令确实有点手足无措。这篇博客就是我在macOS上折腾Git上传代码到码云的完整记录从环境准备、SSH配置到建仓库、推送、解决冲突再到日常更新维护每一步都写得非常详细希望能帮你少走弯路。其实在Mac上用git上传代码到码云核心就三件事配好环境、配好SSH密钥、搞清楚push和pull的顺序。只要把这三件事理顺了后面就是一马平川。我尽量把每个步骤都写得让人看得懂、能跟着操作遇到报错也知道怎么处理。1. 开始在Mac上准备Git环境——检查、安装与SSH配置很多新手上来就急着建仓库结果连Git都没装好后面各种报错。第一步一定要沉住气先把环境检查完。1.1 检查Git是否安装以及用Homebrew安装的完整步骤Mac系统自带Git的情况很特殊我用过的几台Mac情况都不一样。有的新机器自带了有的是个旧版本还有的压根儿没装。所以最稳妥的办法就是打开终端按Command 空格输入Terminal敲一行命令看看git --version有版本号输出比如git version 2.39.2 (Apple Git-XXX)说明系统自带的Git能直接用。不过我建议你用brew装一个新版本尤其是后面处理大文件、多分支时新版本要稳定得多。如果你还没装Homebrew先在终端里执行这行命令/bin/bash -c $(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)装完之后接着用它来装Gitbrew install gitbrew install git和系统自带的Apple Git在路径上是有区别的。你最好验一下当前用的是哪个which git如果显示的是/usr/bin/git说明走的是系统自带版本如果是/usr/local/bin/git或/opt/homebrew/bin/git说明已经切换到Homebrew的版本了。建议确保用的是Homebrew的避免后面出现版本行为不一致的奇怪问题。装完之后配置你的身份信息。这一步很重要做不好会导致推到远程仓库时被拒收。终端里执行两行命令git config --global user.name 你的用户名 git config --global user.email 你的邮箱这两行配置会写进~/.gitconfig文件提交到码云以后历史记录里面显示的就是这个身份信息。如果你想对某个具体的仓库用不一样的账号进到对应的项目目录里把--global去掉再执行一遍就行。1.2 生成SSH密钥并加到码云账户避免每次输密码这一步是Mac端上传代码到码云时最容易出问题的地方也是最容易被忽略的。我当初第一次用git噼里啪啦敲完push结果提示要输账号密码输了又老是弹窗麻烦得要命。后来配好SSH密钥上传代码就变成一条命令的事清爽多了。在终端里执行ssh-keygen -t ed25519 -C 你的邮箱或者备注文字回车后它会问保存路径默认是~/.ssh/id_ed25519我一般直接按回车。接着它会让你设置一个phrase相当于私钥密码我建议留空直接回车。设了密码虽然更安全但每次push都要输一遍对日常使用来说很烦。密钥生成之后在终端执行cat ~/.ssh/id_ed25519.pub输出的那一长串ssh-ed25519开头的内容就是公钥。复制它然后登录你的码云账户找到“私人设置”或“安全设置”里的“SSH公钥”页面把内容粘贴进去。保存时名称随便写比如macbook-pro-2024这样的备注就行。配好后验证一下是否通ssh -T gitgitee.com如果看到Hi xxx! Youve successfully authenticated...一类的提示就说明通了。这里有一个我最初没搞明白的概念生成密钥的时候邮件地址只是一个备注标签它可以和你真实邮箱不匹配不过我更倾向于直接用真实的方便识别是谁的机器。整个SSH的机制就是你的电脑留私钥码云上存你上传的公钥两把钥匙对上之后就能免密操作了。相当于你给自己的账号配了一张长期有效的门禁卡而不是每次进小区都按门铃让保安来开门。注意私钥文件~/.ssh/id_ed25519一定要保护好别拿到陌生机器上随便用。公钥是给人看的私钥泄露相当于你账号的后门被人打开了。2. 两种上手路径从零推送项目与克隆已有仓库环境配好之后就进入正题了。我推荐把所有操作都放在一个专门的目录里别散落在桌面或者下载文件夹。我自己在用户目录下建了一个dev文件夹mkdir ~/dev cd ~/dev后面所有项目都统一放在这个目录下面找起来方便路径也干净。2.1 全新项目从零推送到码云的官方路径假设你现在本地没有任何代码想从头开始写一个项目然后把代码推送到码云。先在码云的网页上点击“新建仓库”填一个仓库名比如hello-mac。务必注意如果本地初始化的时候不打算先勾选任何文件就千万别在网页上选“初始化仓库”也就是不要勾选“使用Readme文件初始化”。否则会出现两边仓库内容完全不相关的问题后续会多一些合并步骤。创建好远程空仓库后回到终端进入你的项目目录cd ~/dev/hello-mac git init git add . git commit -m first commit然后添加远程仓库地址。这里有两种协议git remote add origin gitgitee.com:你的用户名/hello-mac.git或者走HTTPS协议git remote add origin https://gitee.com/你的用户名/hello-mac.git强烈建议你用第一种SSH地址因为已经配好了密钥推送时不用输密码。HTTPS协议虽然也有缓存密码的办法但配置起来更绕SSH一次配好长期免密长远来看更省心。第一次推送的时候要带上-u参数意思是把这个远程分支设置成默认上游git push -u origin master如果你新建仓库的时候默认分支名是main就把命令里的master换成main保持一致。你可以在本地通过git branch看一下当前默认分支的名字再决定用哪个。推送成功之后再修改代码时就不再需要带分支名了只要执行git add . git commit -m 修改了某些内容 git push这三条命令就成了Mac上日常最常用的循环。2.2 克隆码云上的已有仓库到本地开发另一种情况是你已经在码云上有一个仓库可能是你自己之前建好的也可能是团队项目现在换到Mac上要用。这时候不需要在网页上建高分仓库直接把它克隆到本地cd ~/dev git clone gitgitee.com:你的用户名/hello-mac.git克隆会把整个仓库的提交历史、所有分支的引用信息都带下来。本地会多出一个hello-mac文件夹进入它cd hello-mac git branch -a这个命令会列出所有远程分支和本地分支。通常克隆完成后本地会有一个master或main分支和远程的对应分支建立跟踪关系。很多人都纠结“到底该选HTTP还是SSH”我给你的建议是如果你只是偶尔给开源项目提个PR用HTTPS就行如果你是日常主力开发、天天都要push必须用SSH。SSH少一次输入凭证的步骤体验好太多也符合自动化操作的习惯。3. 提交规范的建立——add、commit与.gitignore的细节很多初学者搞不清楚为什么每次都要先git add再git commit感觉很冗余。实际上这两步的职责完全不同理解之后你会觉得非常合理。3.1 git add到底加的是什么如何科学地把文件加入暂存区git add是把改动从工作区放进暂存区Stage相当于你先清点一下哪些文件要打包带走。如果你在电脑上新建了一个文件比如notes.txt它现在是未跟踪状态git add notes.txt后就变成已暂存状态会被包含到下一次提交里。你可以用git status随时查看当前状态git status它会清清楚楚告诉你哪些文件已暂存用git add加入的哪些文件有修改但还没暂存哪些文件完全没有被跟踪实际项目开发中我不建议动不动就git add .尤其是项目大了以后很危险。比如node_modules、.DS_Store、编译产物这些东西如果被git add .带进去你以后每次提交都会把一堆没用的依赖包推到远程仓库仓库会越来越臃肿别人clone下来也特别慢。更好的习惯是明确加哪些文件git add src/ utils/ package.json如果你确实想一次加全部也要注意先看一眼git status里到底有什么确认没有垃圾文件。对于遗漏的文件可以用git add -u这个命令会把所有已跟踪文件的修改加入暂存区但不会把新文件加进去非常实用。3.2 写好commit message其他人包括未来的你都会感谢你git commit是把暂存区的内容固化成一次提交记录。提交消息写得好不好直接决定项目历史是否可读。我见过太多“update”“fix”“认真修改”这种无意义的提交过了两周自己看着都发懵。我的经验是提交消息尽量说明“为什么”。推荐格式是git commit -m feat: 新增登录页面的表单校验逻辑 git commit -m fix: 修复在Safari下日期选择器无法弹出的问题 git commit -m docs: 更新README中的部署步骤前缀用feat、fix、docs、refactor、style、test这类动词一眼就能看出这次提交属于什么性质。如果你改动比较大可以用多行提交信息git commit -m feat: 增加用户积分系统 -m 包含签到、积分流水、排行榜三个模块后续排行榜需要单独优化性能git log --oneline能让你快速浏览提交历史。每次提交记录的说明清晰将来排查问题或回退版本都轻松很多。如果你发现上一次提交写错了比如文件漏了或者信息改错了在推送前可以用git commit --amend -m 更正确的提交信息这会把上一次提交替换掉而不是额外生成一条新的记录。记住--amend是把提交历史改掉只适合在自己还没推送的情况下用。如果已经push到远程了再amend就需要强推来覆盖很可能影响协作者慎用。3.3 .gitignore的真正用法macOS下必须排除的文件在Mac上开发有个文件特别容易出现在项目文件夹里——.DS_Store。这是macOS给每个文件夹生成的桌面元数据文件根本没有提交到代码仓库的必要。解决办法不是每次手动删而是创建一个.gitignore文件把这些文件统统列进去。在项目根目录新建.gitignoretouch .gitignore然后写入以下内容# macOS .DS_Store # Node node_modules/ dist/ build/ # 日志 *.log # 编辑器比如WebStorm或VSCode .idea/ .vscode/做完之后你再执行git status这些文件就不会出现了。如果你的项目已经把这些文件推过一版需要先彻底移除跟踪git rm -r --cached .DS_Store git rm -r --cached node_modules加了--cached的意思是仅仅从Git的索引里移掉记录不会动你本地硬盘上的真实文件。删完重新提交一次仓库就干净了。缓存里保留历史版本的记录也不用担心之前的数据丢失的问题。写.gitignore的时候我习惯遵循“具体优先”的原则。比如你确定不要dist目录可以直接写dist/如果你担心某个目录下有些文件要保留就写dist/*再加!dist/important.json这样的反排除规则非常灵活。4. 必须掌握的push流程绑定远程仓库、解决冲突与强制推送前面几节把本地提交讲清楚了现在来说推送环节。这里面的坑其实不比前面的少。4.1 第一次push时如何绑定远程仓库并设置默认上游如果你是先git init再推送的新项目在执行git remote add origin之前实际上本地仓库和远程仓库还没有建立任何连接。你可以用git remote -v查看当前已经关联了哪些远程地址git remote -v如果什么都没有输出说明还没关联。执行一次git remote add origin gitgitee.com:你的用户名/hello-mac.git这里origin只是一个约定俗成的名字不是关键字。你完全可以叫myremote不过大家都用origin处于习惯我建议你保持默认。推送之前先查看一下本地当前唯一的分支名因为不同初始化环境下分支名可能不同git branch然后推送git push -u origin master-u参数做的事情我在前面提过就是把这个远程分支记为默认上游。之后你再执行git pull和git push时就可以不带参数Git会自动知道该跟哪个远程分支打交道。如果你发现本地分支名和远程分支名不一致比如本地叫main远程叫master可以用git branch -m main master把本地分支重命名让两边对齐避免后面出现混乱的歧义。4.2 推送失败、代码冲突时如何应对推送时最常见的报错是! [rejected] master - master (fetch first) error: failed to push some refs to gitgitee.com:...这个提示的本质含义是远程仓库里有你本地没有的提交两边仓库的历史出现了分叉。Git为了安全起见不会让你直接推上去覆盖别人的提交。解决办法有两个思路思路一把远程的最新代码拉下来合并git pull --rebase origin master--rebase是我个人比较推荐的用法。它会把你在本地的提交先临时收起来拉到远程最新提交作为新的基线再把你自己的提交逐个重放到这条最新基线上。这样做出来的提交历史是线性的很干净。如果遇到冲突Git会提示那些文件有冲突你需要打开文件手动解决解决完再执行git add 冲突文件 git rebase --continue这个循环在团队里几乎每天都会遇到。刚开始会觉得很麻烦但我强烈建议你每一行都读懂等操作熟练之后你就能体会到rebase的好处——你的提交永远在最新的代码之上到后面push时被拒的概率大大降低。思路二如果你一个人开发且非常确定远程版本不需要可以把本地提交强制覆盖上去git push -f origin master-f就是--force意思是强制推送这会直接让远程仓库的历史变成跟本地一致。这个操作风险极大尤其在多人协作的仓库里会把别人的提交给抹掉。即使是我个人项目也只在极其罕见的情况下用。如果你感觉必须强推先看一眼git log确认远程上的提交你真的不需要。4.3 pull操作的区别与理解fetch和merge的关系很多新手会把git pull理解成“下载最新的代码到本地”但实际上git pull是两步操作的组合先git fetch把远程最新的提交记录和改动拉到本地的一个隐藏分支上再git merge或者git rebase把这些改动合并到当前工作分支。git fetch本身不会改变你本地的工作内容它只是下载数据。你可以随时用git fetch origin把远程的最新状态取下来然后检查差异git fetch origin git log HEAD..origin/master --oneline这样就可以很清楚地看到远程有哪些提交是你本地缺少的再决定要怎么合并。这种习惯比直接git pull更加严谨因为你提前知道了正在发生的变化。我遇到过几次这种事故直接git pull以为只是同步代码结果远程刚好有一条大重构提交合并的时候把本地改了一半的逻辑搅得乱七八糟。所以现在我对有大量未提交修改或者正在改重要功能时都会先git fetch看看情况再决定怎么合。5. macOS上真实踩过的坑从git.io.credentials到HostKeyAlgorithms这一节我想专门整理我在Mac上使用Git过程中遇到的几个奇葩问题。这些问题如果你不提前知道网上搜出来的答案五花八门有的给你安装一堆插件有的让你重新生成密钥看了半天浪费不少时间。5.1 “git.io.credentials”错误频发是什么原因Mac上如果刷屏出现git.io.credentials相关的弹窗或者报错多半是因为macOS钥匙串Keychain没有正确管理Git凭证。使用HTTPS协议时Git会默认通过osxkeychain帮助程序存取账号密码但如果你系统里配置了多个Git账户或者凭证过期了就会出现反复要求你输入密码、输入完又继续报错的情况。解决办法有两种。一种是把凭证助手切换一下git config --global credential.helper osxkeychain这个命令会让Git把凭证写入钥匙串。如果问题还在清理掉旧缓存git credential-osxkeychain erase它会提示输入host、protocol、username等输入完毕后回车密码就被清掉了。之后再推一次它会重新弹出输入框让你存新的凭证。说实话我用自己的经验告诉你这个坑最彻底的办法就是不碰它。直接用SSH协议压根不走凭证管理器后面所有苦恼烟消云散。所以我在开头就强调SSH配置就是为了让你绕开这一整套麻烦。5.2 SSH连接失败与HostKeyAlgorithms报错有一种很奇怪的场景刚配好SSH还能用过了一段时间突然连接失败提示Unable to negotiate with ... port 22: no matching key exchange method found.这个问题的本质是本机Git版本使用的SSH密钥交换算法过于老旧而远程服务器的安全策略已经禁用了这些老算法。常见于系统自带的Git版本比较老或者SSH版本号偏旧。解决办法是升级工具链或者说调低本地算法要求。用Homebrew重装Git之后老问题往往就没了因为新版OpenSSH默认支持更新的算法。如果你不想重装也可以在~/.ssh/config里临时加一行Host gitee.com HostKeyAlgorithms ssh-rsa PubkeyAcceptedKeyTypes ssh-rsa注意这个改动只是放宽了本地的算法限制实际效果取决于服务器端是否还允许这些旧算法。现在绝大多数云服务商已经逐渐淘汰旧算法了所以最根本的办法还是升级到新版Git。5.3 为什么明明按下push却卡住不动新手的Mac上执行git push后什么都没有输出或者卡在Enumerating objects...半天。这个问题大概率是你的网络到远程服务器之间不够顺畅也可能是仓库的http/2协议或代理配置出了问题。可以尝试慢速调试模式GIT_TRACE1 git push origin master GIT_CURL_VERBOSE1 git push origin master这两条命令会输出非常详细的网络调试信息。如果发现是SSL握手时间过长可以试试临时关闭部分校验git config --global http.sslVerify false但真的不建议长期关闭这是把安全评级降级了。我更推荐调整代理策略。如果你使用了系统级代理确保终端里的环境变量一致export http_proxyhttp://127.0.0.1:端口 export https_proxyhttp://127.0.0.1:端口终端里的代理和浏览器里的代理是两个世界。你的浏览器能打开网页不代表终端里Git就能正常走代理。这个知识点我这几年反复注意到很多人不知道。5.4 推送大文件时出现RPC failed错误如果你把一个很大的文件比如超过几百MB的模型文件、视频剪辑直接git push很可能出现error: RPC failed; HTTP 413 curl 22 The requested URL returned error: 413 fatal: the remote end hung up unexpectedly这个报错说明远程服务器不接受过大的HTTP请求体常见的原因是服务端对单次请求体积有限制或者本地http.postBuffer默认值太小。可以试着把这个缓冲值调大git config --global http.postBuffer 524288000这是把缓冲调到500MB左右。但如果文件实在太大这样做只是临时缓解根本解法还是用Git LFS来管理大文件。码云平台本身是支持LFS的在仓库根目录执行git lfs install后把大文件后缀用git lfs track命令跟踪一下再提交推送就不会再走普通的git协议去传大文件了。可以说我后来做涉及模型或素材文件的项目一律是先配LFS再开工的不然等推到一半卡住那种心情是真的崩溃。6. 如果再往前一步专业分支管理与发布流程当你把“上传代码到码云”这条链路彻底跑通之后项目的复杂度会逐渐上升。为了不让你停留在一个单纯“能传上去”的阶段我把分支管理和发布标签这一层也讲一下。这部分属于工程化习惯和标题关系非常紧密因为分支推不上去、打标签找不到位置也是实际发生的核心痛点。6.1 为什么“不要直接在master上开发”是真理单人开发时可能在master/main分支上直接提交几十次感觉没啥问题。但一旦有两个人协作或者你想给项目加新功能同时修线上bug直接在主干上做开发就是灾难。两个功能同时改同一文件提交历史相互交错过两天你自己都分不清哪个代码对应哪次功能。推荐的最小可用分支模型是这样的master/main分支始终是稳定可发布的。每次开发新功能从master切一个分支出来git checkout -b feature/login在功能分支上做开发、提交、推送git push -u origin feature/login功能开发完成并测试通过后合并回master:git checkout master git pull git merge feature/login git push origin master分支名字用feature/前缀代表功能fix/前缀代表修复docs/前缀代表文档。这套命名规范加上前缀体系任何人在看项目分支列表时都能快速理解每一条分支的用途。我在各种项目里都用这套规则几年下来几乎没出现过分不清分支的情况。6.2 用tag给每个版本打上不可移动的锚点分支是随着开发动态变化的但版本号不能跟着变。码云上的Release功能往往和tag绑定所以需要本地方便有规律地打标签git tag v1.0.0 git push origin v1.0.0这条命令会给当前提交打上一个静态标签并在推送之后同步到远程。之后你想精确回退到这个版本直接git checkout v1.0.0标签的意义就像是一条河流边上的木桩。水流一直在走但打着标签的提交不会再移动。每次发布测试通过后打一个标签之后无论是排查线上问题还是给客户做交付都有据可依。如果你想一次推送多个标签或者所有标签git push origin --tags注意--tags会把所有本地标签都推上去。在推荐流程里打标签前先确保master分支已经是最新状态不然标签打在一个旧提交上后面看版本历史就凌乱了。6.3 隐性问题项目的README与License代码推到码云只是第一步一个仓库的长期价值取决于它是否容易理解。如果你连README都不写别人包括未来的你看到这个仓库根本不知道这个项目是用来干嘛的、怎么跑起来、有哪些坑。我喜欢在项目根目录放一个README.md内容包含项目简介这个项目做什么一句话说明白环境要求比如macOS版本、Node版本、Python版本快速开始精确到从克隆到跑起来需要执行哪些命令目录结构说明各个主要目录的职责常见问题记录本项目的特殊坑点README.md是你在仓库里最值得维护的文件它和LICENSE一起构成了一个项目是否专业的第一印象。如果你是给别人用的开源项目选择好合适的开源协议再用几句话说明贡献方式整个仓库就上升了一个档次。6.4 日常开发的一个高效循环最后总结一套我用得非常顺手的循环流程你可以直接抄写代码之前先拉最新git checkout master git pull origin master git checkout -b feature/我的新功能写代码过程中分小步提交git add 具体文件 git commit -m feat: 完成A模块的接口对接 git push -u origin feature/我的新功能功能写完了合回主干git checkout master git pull origin master git merge feature/我的新功能 git push origin master这套循环可以保证你永远在稳定的主干上工作功能代码独立在分支里演进出现问题时随时回退。它比在master上直接改要安全得多绝对是值得养成的好习惯。我在Mac上第一次成功把代码推到码云的那一刻其实只花了十分钟不到。但真正踩完上面这些坑、摸索出适合自己的工作流大概用了将近一周。回头想想环境中绝大多数问题都出在SSH配置和网络链路其余的都是操作习惯的问题。希望这篇文章能让你在Mac上完成从“本地代码”到“码云仓库”的完整闭环而且是一次性少走太多弯路。