
前几天帮一个同事看代码他一脸委屈地说“我明明执行了git init也提交了怎么换台电脑代码就不见了”听他讲完我才发现他把“git init”当成了“保存项目”这件事的全部提交之后既没有推送远程也没有做任何备份。其实这种误会很常见尤其是刚接触Git的人总觉得git init执行完工作就结束了真正的问题恰恰出在初始化之后那几步。这篇文章就以“初始化Git仓库并保存项目”为主线把从git init到第一次提交、再到推送到远程仓库的完整流程拆开讲一遍。适合刚装好Git、准备把本地项目管起来的新手也适合那些已经会add和commit但从来没认真想过“初始化到底该注意什么”的人。我会尽量不绕弯子把每一步为什么要这么做、踩过什么坑、有哪些可以照抄的命令都讲清楚。1. 为什么要把“初始化仓库”这一步想清楚再动手1.1 先搞清楚git init到底做了什么很多教程只说“在项目目录里运行git init就完成了”但如果你不知道这行命令在干什么后面遇到问题就会抓瞎。简单说git init会在当前目录生成一个.git的隐藏文件夹Git的所有版本历史、分支指针、配置信息都装在里面。可以把它理解成项目的一个“账本”git add是在往账本上草稿区写条目git commit是把条目正式盖章入册git push则是把账本副本送到远程仓库。如果你的项目目录里没有.git文件夹那不管你写多少代码Git都不会“记得”它。很多“代码突然没了”的惨案本质就是账本不存在或者账本存在但没提交或者提交了但没推送。所以我想先强调一个观点初始化不是执行完就结束的动作它应该是“保存项目”这条流水线的起点只完成起点后面没有跟上提交和推送等于白干。1.2 初始化之前先回答四个问题在运行git init之前我建议你先花两分钟想清楚下面几件事想清楚再动手能省掉后面一堆麻烦。第一这个目录是不是真的适合作为一个独立仓库。如果你在D:\code根目录直接初始化然后把所有乱七八糟的工程装进去之后仓库会变得极其臃肿。我习惯先建一个清晰的项目文件夹比如shop-server、blog-frontend再进文件夹里初始化。每个项目独立仓库互不污染这是长期维护的基础。第二项目里哪些文件不应该被跟踪。比如依赖包目录、编译产物、本地配置文件、系统垃圾文件。这些必须在初始化之后第一时间写进.gitignore否则很容易把一堆没用的文件提交进去。我见过有人把node_modules提交进仓库几万个小文件后续每次克隆都慢得让人崩溃。第三默认分支名用什么。最新的Git已经支持创建自定义初始分支名建议从一开始就用main而不是老的master。分支名本身不影响功能但main在今天几乎是社区默认约定插件、文档、自动部署脚本都默认这个分支减少不必要的认知成本。第四远程仓库地址是什么。虽然初始化时可以没有远程地址但“保存项目”不应该只保存在本地。机械硬盘会坏电脑会丢只有推到远程仓库才算是真正有了备份。你需要提前想好用Gitee、GitHub还是公司内部的GitLab。这四个问题不需要一次全想明白但至少要在心里过一遍。你会发现真正费时间的不是git init这行命令而是命令前后的设计决策。2. 初始化Git仓库的标准流程与参数选择2.1 从空目录开始git init -b main如果你手上是一个全新的空目录流程非常简单mkdir my-project cd my-project git init -b main-b main是--initial-branchmain的简写意思是让Git直接创建名字为main的初始分支。如果你用的是比较旧的Git版本不支持这个参数可以先用git init再通过git branch -m main把当前分支改名或者用git symbolic-ref HEAD refs/heads/main来设置但说实话升级Git版本比折腾这些参数省心得多。执行完之后建议看一眼目录情况ls -la你会发现多了一个.git文件夹。不要手贱去改里面的内容除非你已经很熟悉Git内部结构。很多学习者一好奇就打开.git目录乱删结果仓库直接报废。我通常只通过命令行和Git客户端来操作它这样最稳妥。那么问题来了git init和git init --bare有什么区别如果你只是在本地开发用git init就够了仓库里包含工作区你可以直接编辑文件。但如果你要搭一个远程仓库的“中转站”供其他成员推送代码一般会用git init --bare初始化一个裸仓库。裸仓库没有工作区只有版本历史通常部署在服务器或者Git平台后端日常开发基本接触不到。初学者记住“本地开发用普通init服务器中转用bare”就够了。2.2 已有项目怎么办别上来就git add .如果你手上已经有一堆代码文件不是空目录初始化流程稍稍有点不同。我见过很多人的第一反应是“先init再add .”但这样容易把不该提交的东西一起带进来。我的建议是下面这样cd existing-project git init -b main然后先创建.gitignore把依赖目录、编译产物、敏感配置都排除掉具体的忽略规则后面会讲。再执行git status看清楚哪些文件会进入版本管理确认没有意外文件后再决定怎么暂存。如果项目文件特别多可以先只添加核心代码目录git add src docs README.md这样逐步确认比一股脑git add .安全得多。我早期吃过亏在某个项目里把包含数据库密码的application.yml直接提交进了历史后来改密码、清历史折腾了一整天才处理干净。从那以后我在初始化已有项目时第一件事永远是先看git status再写忽略规则最后才add。另外有一种常见情况你已经在某个目录里写了一段代码但之前没有Git这时候初始化后文件会显示为未跟踪状态。不要慌这是正常的。Git不会因为你初始化就自动改动文件内容所有文件都原样保留只是开始被纳入了版本管理。2.3 从远程仓库克隆git clone本身就包含初始化如果你不是从零开始而是要把远程已有的仓库拉下来那根本不需要手动执行git init。git clone会一次性完成几件事在本地创建目录、初始化仓库、添加远程地址、拉取所有分支历史、把当前默认分支检出到工作区。git clone gitgitee.com:someone/my-project.git cd my-project很多新手会搞混先git init再git clone结果出现“目标目录已存在”或者“远程地址冲突”其实是因为顺序反了。正确的顺序是好比“你已经下载好了压缩包就没必要再自己新建一个空文件夹来承接压缩包”直接用clone让它自己建目录就好。如果远程仓库已经存在你只是想在这个目录里重新关联一份拷贝也不建议把整个.git删掉再clone。更好的做法是保持原有目录换掉远程地址git remote remove origin git remote add origin gitgitee.com:someone/my-project.git这个操作本质上是把旧“账本”替换成新“账本”的地址而不是把本地代码重新初始化一遍。理解了这个逻辑你后面处理远程仓库问题时就不会慌。3. 保存项目的第一步提交信息、暂存区与忽略规则3.1.gitignore是我每次最先写的东西我强烈建议在初始化仓库后的第一份提交里就把.gitignore写好。原因很简单忽略规则写得越晚误提交的概率就越高。一旦文件已经被Git跟踪再往.gitignore里加规则并不会让它们自动消失需要额外执行git rm --cached才能从索引里移除。与其后面补不如一开始就堵住。下面是一个比较通用的示例适合大部分Web项目# 依赖目录 node_modules/ vendor/ # 构建产物 dist/ build/ target/ *.class # 环境配置与密钥 .env .env.* *.local config/application-local.yml # IDE与系统文件 .idea/ .vscode/ *.iml .DS_Store Thumbs.db # 日志与临时文件 *.log logs/ temp/node_modules/的尾部斜杠表示忽略整个目录.env则连文件带后缀一起忽略。一个容易忽略的细节是Git的忽略规则对已经跟踪的文件不生效。如果你之前已经提交过.env现在往.gitignore里加一行.envgit status里可能还是能看到它被更改。这时候要用git rm --cached .env--cached的意思是“只在Git索引中移除磁盘上的文件保留”。执行完再提交文件就从版本管理里退出了但本地开发还能继续用非常适合处理误提交的配置和密钥。3.2 第一次提交的信息怎么写提交信息是仓库的“历史注释”第一次提交尤其重要。我见过有人写“111”有人写“asdf”还有人干脆不写导致git commit直接弹出vi编辑器然后卡住。作为历史的第一条记录建议写得清晰、克制比如git add .gitignore README.md src/ git commit -m chore: 初始化项目结构与基础配置chore:是一个约定式提交的前缀表示不涉及功能增删的杂项维护。第一次提交用chore: init很合适。如果你从一开始就维护一个项目后续的功能提交可以分别用feat:、fix:、refactor:来区分。这种习惯不是形式主义它能让你三个月后翻git log时一眼看懂每个提交的意图。如果提交的时候提示没有用户信息说明你还没配置全局用户名和邮箱git config --global user.name Your Name git config --global user.email youexample.com用户名和邮箱会写进每次提交的作者信息里建议用真实姓名和工作邮箱方便团队协作时联系。注意这里配置的邮箱会出现在公开仓库的历史里如果在意隐私可以改用Git平台提供的隐私邮箱。3.3 提交前检查别让敏感信息混进来第一次提交是“仓库历史的第一页”一旦写错后面想改就麻烦。所以在执行git commit之前我会做三件小事。第一条检查git status确认暂存区里只有你想提交的文件所有临时文件、超大文件都不在列表里。第二条检查git diff --cached看看暂存区内文件的具体改动有没有输出密码、密钥、内网地址之类的敏感内容。第三条如果是配置文件用git check-ignore -v .env确认忽略规则真的生效了而不是凭感觉以为生效了。git check-ignore是个很好用的调试命令。如果它什么都没输出说明文件并没有被忽略该文件还是会被提交如果输出了一行匹配规则说明忽略生效。我经常在写完.gitignore后用这个命令逐条验证尤其是那些带!取反规则的场景。4. 把本地仓库送到远程新建仓库与首次推送实操4.1 在Gitee或GitHub上先建一个空仓库本地提交做完了接下来是“保存项目”的最后一步把本地仓库推送到远程。我以Gitee为例GitHub操作大同小异。进入网页后点“新建仓库”填写仓库名这里有一个关键选择初始化仓库时要不要勾选“初始化仓库”相关的选项比如自动生成README、.gitignore、许可证。我的建议是首次关联本地项目时远程端什么都不勾选创建一个完全空的仓库。这样本地仓库和远程仓库没有任何历史差异第一次推送会非常干净。如果你在远程端自动生成了README本地又没有这个文件推送时就会遇到“两边都有历史Git不知道谁先谁后”的冲突需要额外合并。我不是说不能用这种方式而是对新手来说先让两边一致能省掉不少麻烦。仓库建好之后网页会给你两个地址HTTPS地址和SSH地址。SSH地址以gitgitee.com:开头HTTPS地址以https://开头。如果还没有配置SSH密钥先用HTTPS也能正常用但要输入账号密码。我更推荐配置好SSH之后用SSH地址免去每次输密码的麻烦也更安全。4.2 关联远程地址并完成第一次推送回到本地执行git remote add origin gitgitee.com:yourname/my-project.git git push -u origin main第一行把远程仓库地址登记到本地配置里给它一个简短的别名origin这是社区约定的默认名称也可以改成别的但没有必要。第二行把当前main分支推送到远程的main分支-u是--set-upstream的简写意思是“这次推送之后本地main分支和远程main分支建立关联以后不带参数直接执行git push和git pull就能自动对应”。第一次推送成功后再去网页刷新就能看到代码了。到了这一步“初始化Git仓库并保存项目”这件事才算真正闭环。本地有账本远程有备份即使本地硬盘摔碎了代码依然可以随时恢复。这个安全感的提升比任何云盘备份都靠谱。4.3 分支名不一致怎么处理如果你初始化时不是用main或者远程端默认分支叫其他名字推送时可能会遇到“找不到main分支”或“分支已存在”的情况。处理方法其实很简单git branch -m main git push -u origin main第一条命令把当前分支强制改名为main第二条再推送。如果远程分支名是master你又不打算改名也可以直接推送对应分支git push -u origin master分支名并不是神圣不可改变的核心是统一。现代平台的默认新仓库多数叫main你本地和远程保持一致就行。万一你远程端不小心勾选了自动生成README本地推送会遇到这样的提示因为当前分支和远程分支没有共同历史导致被拒绝。解决办法是保留远程文件然后合并git pull origin main --allow-unrelated-histories--allow-unrelated-histories允许两段没有关联的历史进行合并。合并时可能会产生冲突手动解决后再提交推送。这种路径我不推荐新手主动触发但真遇到了知道有这么个参数能救命。5. 初始化过程中最常见的报错与排查方法5.1 “fatal: not a git repository”这是新手最容易遇到的报错场景通常是你在某个文件夹里执行git statusGit告诉你“这根本不是一个仓库”。原因无非两种当前目录不是Git仓库或者.git文件夹被别人删了。排查方式很直接pwd ls -la先确认你确实站在项目目录里再确认里面有没有.git。如果目录里没有.git直接执行git init -b main重新初始化但要小心这样会丢失原有的版本历史如果历史本身就已经丢了那就没办法挽回。我还遇到过一种情况用户在子目录里操作比如src文件夹Git沿父目录向上找仓库如果父目录没有任何.git就会报这个错。解决方法是退到项目根目录再操作。5.2 “remote origin already exists”或推送被拒绝“远程地址已经存在”这个提示多半是因为你之前已经执行过git remote add origin又执行了一次同样的命令。先看看当前远程地址git remote -v如果地址不对可以改。常用命令有两个git remote set-url origin gitgitee.com:yourname/my-project.git或者彻底删掉重新加git remote remove origin git remote add origin gitgitee.com:yourname/my-project.git如果是推送被拒绝提示类似“failed to push some refs”原因多半是远程分支上有本地没有的提交。先用git pull origin main --rebase把远程变更拉下来并重放到本地提交之上再重新推送。我特别想说一句不要遇到推送被拒绝就直接git push -f强推。强推会覆盖远程历史如果是多人协作你这一下可能把别人的代码清空。强推只适合确定自己就是仓库唯一操作者且远程内容全部可以丢弃的场景。5.3 误把node_modules或其他大目录提交了这个坑我前面提到过这里说具体解决办法。假设你已经把node_modules提交进去了现在想让它退出版本管理但磁盘文件保留git rm -r --cached node_modules然后把node_modules/写进.gitignore再执行提交git commit -m chore: 移除依赖目录并加入忽略规则 git push--cached只是移除索引不删本地文件所以这个操作不会破坏开发环境。但是如果这个大目录已经在历史提交中存在远程仓库里依然能看到历史中的文件除非做历史重写。对于普通项目我建议不要轻易重写历史只是从当前提交开始停止跟踪即可。真要彻底清理需要专业的工具那又是另一个话题而且操作前务必备份。5.4 SSH认证失败或反复要求输入密码用git push时报“Permission denied (publickey)”说明SSH密钥没有配对成功。这个过程不复杂但很多人卡在“密钥搞混了”。你只需要做三件事第一确认本地有公钥和私钥通常在用户主目录的.ssh文件夹下ls -la ~/.ssh如果没有id_ed25519或id_rsa生成一个ssh-keygen -t ed25519 -C youexample.com一路回车即可。第二把公钥内容复制到Gitee或GitHub的“SSH公钥”设置页。公钥文件是.pub后缀别把私钥发出去。私钥等于你的身份谁拿到谁就能以你的名义推送代码。第三测试连接ssh -T gitgitee.com看到欢迎提示就说明通了。如果还是失败重点检查平台账号邮箱和公钥是否复制完整。还有一个小技巧如果公司电脑上存在多个密钥可以通过~/.ssh/config为不同平台指定不同密钥文件但新手阶段通常不涉及先确保一对默认密钥能用即可。6. 让“保存项目”这件事形成肌肉记忆6.1 每次顺手保存的一套动作代码写到一个阶段比如实现了某个小功能、修完一个bug或者只是要下班了我会按固定节奏走一遍git status git add src/ docs/ git commit -m feat: 完善用户登录接口 git push这套动作看起来很朴素但价值在于“频率”。宁可提交得小一点、勤一点也不要憋一个大版本才提交。小提交之间差异小出问题时很容易定位到具体是哪一次改动引起的大提交动不动成百上千行改动出了问题连排查的欲望都没有。我个人的经验是每次提交之前问自己一句这个提交信息三个月后的我能看懂吗如果答案是“看得懂”就提交如果信息里只有“aaa”或“update”赶紧改掉。6.2 用别名降低操作成本如果你发现每天要敲很多次git status和git log完全可以给Git配置别名。比如git config --global alias.st status git config --global alias.lg log --oneline --graph --all --decorate之后直接使用git st git lg还有一个非常实用的命令组合用于查看最近提交的简要信息git config --global alias.last log -1 --stat这些别名不会改变Git的实际功能只是让你少敲几个字符。习惯之后版本管理的操作成本会低到让你下意识去用而不是觉得“太麻烦不想提交”。真正能把项目保存好的从来不是某一次完美的初始化而是高频且稳定的提交习惯。6.3 从“保存项目”到“可回溯的项目历史”初始化Git仓库的最终目的不只是备份而是获得一种随时能回溯的能力。有了完整提交历史你可以在git log里看到每个阶段做了什么改动可以在git diff里对比两个版本之间的差异可以在出问题时用一个干净的旧提交临时恢复服务而不用在代码里翻找“以前到底是哪段逻辑”。我从一开始混乱保存“最终版V3”“最终版V4.2”到真正让Git成为项目的唯一历史来源中间最大的变化不是学会了更多命令而是想明白了一件事Git是一个工具工具的价值取决于你给它喂什么。只要你认真初始化、及时提交、定期推送它就会回馈给你极大的安全感如果你只执行一个git init就再也不管它和一张没写字的废纸没什么区别。我个人最后再分享一个习惯每次新建项目我不会急着写业务代码而是先把仓库初始化好、.gitignore写好、README写上、第一次提交完成然后再开始写功能。这个顺序看起来多花了几分钟但后面几周甚至几个月里它一直在帮我省时间。项目的安全感就是从这安静的一次提交开始积累的。