Git 版本控制从入门到实战:一篇讲透仓库、分支、远程协作与 GitLab
Git 版本控制从入门到实战一篇讲透仓库、分支、远程协作与 GitLab适合人群刚开始学 Java / 后端开发 / 前端开发、第一次接触 Git、想系统补齐 Git 命令和团队协作流程的同学。关键词Git 教程、Git 命令大全、Git 分支管理、GitHub、GitLab、多人协作、冲突解决、.gitignore。一、为什么开发者一定要学 Git写代码最怕的不是 bug而是这几件事改了半天突然想回到昨天的版本。多个人同时改代码不知道谁覆盖了谁。线上出了问题想快速找到是哪一次提交引入的。新功能开发到一半突然要先修一个紧急 bug。代码在自己电脑上能跑团队其他人却拿不到最新版本。Git 就是为了解决这些问题而出现的版本控制系统。它可以记录项目每一次变化让你能随时查看历史、回退版本、创建分支、合并代码、和团队成员协作开发。一句话理解 GitGit 是一个分布式版本控制系统它把项目的每一次提交都保存成快照并允许每个开发者在本地拥有完整仓库历史。Git 最早由 Linux 作者 Linus Torvalds 开发。Linux 内核项目参与者众多靠人工合并补丁已经无法支撑协作效率于是 Git 诞生并逐渐成为目前最主流的版本控制工具。后来 GitHub、GitLab、Gitee 等平台兴起Git 也成为程序员的基础技能。二、集中式版本控制 VS 分布式版本控制学习 Git 之前先弄清楚它和 SVN、CVS 这类集中式版本控制系统的区别。1. 集中式版本控制集中式版本控制系统把所有版本历史都放在一台中央服务器上开发者通过客户端连接服务器获取代码、提交修改。典型代表CVSSVNPerforce它的优点是模型简单所有代码都在一个中心位置管理。但缺点也很明显中央服务器宕机时大家很难提交或拉取代码。如果中央仓库损坏且备份不完整历史记录可能丢失。很多操作依赖网络离线开发体验差。2. 分布式版本控制Git 属于分布式版本控制系统。每个开发者克隆项目时拿到的不只是最新代码而是整个仓库历史。这意味着本地就能提交代码。本地就能查看日志、比较差异、回退版本。远程仓库出问题时其他人的本地仓库仍然保存了完整历史。没网时也能开发有网后再推送。可以把 Git 的协作关系理解成开发者 A 本地仓库 ---- 远程仓库 ---- 开发者 B 本地仓库 | | 工作区 工作区Git 的强大之处在于它不是简单记录文件差异而是按提交保存项目快照。文件没变时Git 不会重复保存文件内容而是通过引用复用之前的对象所以速度快、空间利用率也高。三、Git 安装与首次配置Git 支持 Windows、macOS 和 Linux。安装完成后建议先配置用户名和邮箱。它们会写入每一次提交记录中用来标识是谁提交了代码。gitconfig--globaluser.nameyour_namegitconfig--globaluser.emailyour_emailexample.com查看配置gitconfig--global-lGit 配置分为三个级别级别命令参数配置文件位置作用范围仓库级--local当前仓库.git/config只对当前项目生效用户级--global用户目录~/.gitconfig对当前用户所有项目生效系统级--systemGit 安装目录下的配置文件对系统所有用户生效优先级local global system注意配置邮箱时是user.email不是user.mail。四、Git 仓库的四个核心区域初学 Git 最容易混乱的地方就是工作区、暂存区、本地仓库、远程仓库之间的关系。区域英文说明工作区Workspace项目目录里你能直接看到和编辑的文件暂存区Stage / Indexgit add后临时保存改动的位置本地仓库Repository.git目录保存提交历史和版本信息远程仓库RemoteGitHub、GitLab、Gitee 上的代码仓库最常见的提交流程是修改文件 ↓ git add ↓ 暂存区 ↓ git commit ↓ 本地仓库 ↓ git push ↓ 远程仓库对应命令gitstatusgitadd.gitcommit-m提交说明gitpush如果从远程同步别人的代码流程通常是gitpull或者拆成两步gitfetchgitmerge五、创建本地仓库git init进入项目目录后执行gitinit执行后当前目录会多出一个隐藏目录.git。这个目录非常重要里面保存着 Git 管理版本所需的所有数据包括对象、分支、HEAD 指针、暂存区索引等。不要手动乱改.git目录否则仓库可能损坏。查看当前仓库状态gitstatus如果看到Untracked files说明文件还没有被 Git 跟踪。六、添加与提交文件add和commit假设新建了一个readme.txtechohello gitreadme.txtgitstatus把文件加入暂存区gitaddreadme.txt一次添加多个文件gitadda.txt b.txt c.txt添加当前目录全部改动gitadd.提交到本地仓库gitcommit-mfirst commit提交说明一定要写清楚不要只写update、fix、aa。推荐写成gitcommit-mfeat: add user login pagegitcommit-mfix: resolve order amount calculation buggitcommit-mdocs: update git learning notes这样团队成员看日志时能快速知道这次提交做了什么。七、查看日志与版本历史查看提交历史gitlog简洁显示gitlog--prettyoneline更常用的图形化日志gitlog--oneline--graph--decorate--all输出大概长这样* 9fceb02 (HEAD - dev) feat: add order module * 61a3b21 fix: repair login bug * 35cc0f4 (main) first commit其中HEAD表示当前所在位置。HEAD^表示上一次提交。HEAD~3表示往前数第 3 次提交。一串哈希值比如9fceb02是提交版本号的简写。八、查看文件差异git diffgit diff用来查看改动内容是排查问题和提交前自查的高频命令。1. 工作区 VS 暂存区查看工作区中还没有add的修改gitdiffgitdiffreadme.txt2. 暂存区 VS 最近一次提交查看已经add但还没有commit的内容gitdiff--cachedgitdiff--cachedreadme.txt3. 工作区 VS 指定提交gitdiffHEADgitdiffHEAD readme.txtgitdiffcommit_idreadme.txt4. 两个提交之间比较gitdiffcommit_id_1commit_id_2建议每次提交前执行gitstatusgitdiff--cached这样可以确认自己即将提交的内容是否符合预期。九、撤销修改与版本回退Git 的撤销命令很多新手最容易用错。可以按场景记。场景命令说明撤销工作区某个文件的修改git restore file.txt文件回到暂存区或最近提交的状态取消暂存git restore --staged file.txt文件从暂存区退回工作区回退到上一个提交git reset --hard HEAD^工作区、暂存区、本地仓库一起回退回退到指定提交git reset --hard commit_id直接回到某个版本查看操作历史git reflog找回被 reset 掉的提交示例gitreset--hardHEAD^回退到上上个版本gitreset--hardHEAD^^回退到前 100 个版本gitreset--hardHEAD~100回到指定提交gitreset--hard8d95a43如果回退后又后悔了可以用gitreflog找到之前的提交号再执行gitreset--hardcommit_id重点提醒git reset --hard会丢弃工作区未提交的修改执行前一定要确认没有重要代码。十、删除文件如果要从 Git 仓库中删除文件gitrmtest.txtgitcommit-mremove test file如果只是手动删除了文件也可以用rmtest.txtgitaddtest.txtgitcommit-mremove test file如果删除后想撤销gitrestore test.txt如果文件已经进入暂存区想取消暂存gitrestore--stagedtest.txt老版本 Git 也常见这些写法gitcheckout -- test.txtgitreset HEAD test.txtcheckout还能用但新版本 Git 更推荐用restore和switch来区分“恢复文件”和“切换分支”。十一、.gitignore哪些文件不应该提交项目里并不是所有文件都应该交给 Git 管理。通常不提交编译产物比如.class、target/、build/日志文件比如*.log临时文件比如*.tmpIDE 配置比如.idea/操作系统文件比如.DS_Store、Thumbs.db密码、密钥、生产配置等敏感文件在项目根目录创建.gitignoretouch.gitignore常见规则# 忽略所有 .class 文件 *.class # 忽略 target 目录 target/ # 忽略所有 log 文件 *.log # 不忽略某个指定文件 !important.log # 忽略任意层级下的 foo 目录或文件 **/fooJava 项目常用模板# Java *.class *.war *.ear *.jar # Maven / Gradle target/ build/ .gradle/ # IntelliJ IDEA .idea/ *.iml *.ipr *.iws # Eclipse .settings/ .project .classpath # Logs *.log # Temp *.tmp *.cache *.diff *.patch # System .DS_Store Thumbs.db全局.gitignoregitconfig--globalcore.excludesfile ~/.gitignore.gitignore不生效的常见原因文件已经被 Git 跟踪了。.gitignore只能忽略未被跟踪的新文件。解决办法gitrm--cachedfile.txtgitcommit-mremove tracked ignored file如果是目录gitrm-r--cachedtarget/gitcommit-mremove target from git tracking十二、分支管理Git 的灵魂分支是 Git 最重要的能力之一。它可以让你在不影响主线代码的情况下开发新功能、修复 bug、验证想法。查看分支gitbranch创建分支gitbranch dev切换分支gitswitch dev老写法gitcheckout dev创建并切换分支gitswitch-cdev老写法gitcheckout-bdev删除已经合并的分支gitbranch-ddev强制删除未合并分支gitbranch-DdevGit 的分支本质上是指向提交对象的指针。HEAD指向当前分支当前分支再指向最新提交。HEAD - main - commit3 - commit2 - commit1创建新分支时Git 并不会复制一份完整代码而是创建一个新的指针。所以 Git 分支非常轻量创建和切换都很快。十三、分支合并与冲突解决假设你在dev分支开发完功能要合并回maingitswitch maingitmerge dev如果两个分支修改了不同文件通常会自动合并。如果两个分支修改了同一个文件的同一位置就可能出现冲突。冲突文件里会出现类似内容 HEAD main 分支上的内容 dev 分支上的内容 dev解决步骤打开冲突文件。手动选择保留哪部分内容或整合两边内容。删除、、标记。重新添加并提交。gitaddconflict-file.txtgitcommit-mfix: resolve merge conflict查看分支合并图gitlog--oneline--graph--decorate--all冲突不可怕可怕的是不知道自己保留了什么。解决冲突后一定要重新运行项目或测试。十四、git stash临时保存未完成代码stash适合两个典型场景正在开发新功能突然要切分支修紧急 bug但当前代码还不想提交。不小心在错误分支上开发了需要先把改动临时存起来再切到正确分支恢复。保存当前工作区和暂存区修改gitstash查看 stash 列表gitstash list恢复最近一次 stash并从列表删除gitstash pop恢复但不删除 stashgitstash apply删除某条 stashgitstash drop stash{0}清空所有 stashgitstashclear建议给 stash 加说明gitstash push-mhalf-done order export feature这样以后看git stash list时不会一头雾水。十五、推荐的团队分支管理策略实际团队开发中常见分支可以这样设计分支作用main/master主分支保存稳定代码develop日常开发分支集成新功能feature/*功能分支从develop拉出完成后合并回developrelease/*预发布分支用于测试和发布准备bugfix/*普通 bug 修复分支hotfix/*线上紧急修复分支通常从稳定分支拉出现在很多平台新仓库默认主分支叫main旧教程里常见master。两者本质都是普通分支使用时以自己仓库实际分支名为准。一个常见开发流程# 从 develop 创建功能分支gitswitch developgitpullgitswitch-cfeature/user-login# 开发、提交gitadd.gitcommit-mfeat: add user login# 推送远程gitpush-uorigin feature/user-login# 提交合并请求代码评审后合并到 develop线上 bug 修复流程gitswitch maingitpullgitswitch-chotfix/login-error# 修复后提交gitadd.gitcommit-mfix: repair login error# 合并回 main 和 develop十六、关联远程仓库并推送代码本地仓库创建完成后如果想推送到 GitHub / GitLab / Gitee需要先关联远程仓库。gitremoteaddorigin https://github.com/yourname/your-repo.git查看远程仓库gitremote-vgitremote show origin第一次推送并建立上游关联gitpush-uorigin main如果你的主分支叫mastergitpush-uorigin master之后再推送gitpush或者明确指定gitpush origin main-u的作用是建立本地分支和远程分支的追踪关系。建立后当前分支直接执行git pull和git push就知道对应哪个远程分支。十七、克隆远程仓库与多人协作克隆远程仓库gitclone https://github.com/yourname/your-repo.git指定本地目录名gitclone https://github.com/yourname/your-repo.git my-project多人协作时最常见的日常流程gitpull# 修改代码gitstatusgitadd.gitcommit-mfeat: add payment callbackgitpush如果推送失败提示远程有别人提交的新内容一般先拉取gitpull如果发生冲突就按前面冲突解决流程处理然后再gitadd.gitcommit-mfix: resolve pull conflictgitpush更稳的做法是先抓取远程信息gitfetch origin查看本地和远程差异后再决定是否合并。十八、远程分支管理查看所有本地分支gitbranch查看本地和远程分支gitbranch-a查看分支最后一次提交gitbranch-av把本地分支推送到远程并建立追踪gitpush-uorigin develop基于远程分支创建本地分支gitswitch-cdevelop origin/develop老写法gitcheckout-bdevelop origin/develop直接追踪远程分支gitcheckout--trackorigin/feature删除远程分支gitpush origin--deletefeature清理本地已经失效的远程分支引用gitremote prune origin十九、标签管理给版本打标记标签通常用来标记发布版本比如v1.0.0、v2.3.1。创建轻量标签gittag v1.0.0创建带说明的标签gittag-av1.0.0-mrelease version 1.0.0查看标签gittag删除本地标签gittag-dv1.0.0推送指定标签gitpush origin v1.0.0推送所有标签gitpush origin--tags删除远程标签gitpush origin :refs/tags/v1.0.0或者gitpush origin--deletetag v1.0.0基于标签检出一个新分支gitcheckout-bhotfix-v1.0.0 v1.0.0标签和分支的区别分支会随着提交继续向前移动。标签固定指向某一次提交通常用于版本发布。二十、GitHub、GitLab 和 Gitee 的关系Git 是版本控制工具GitHub、GitLab、Gitee 是基于 Git 的代码托管平台。平台特点GitHub全球最大开源代码托管平台开源项目多GitLab支持私有化部署企业内部常用Gitee国内访问速度较友好中文生态好无论使用哪个平台核心 Git 命令基本一致gitclonegitpullgitaddgitcommitgitpushgitbranchgitmerge区别主要在账号、权限、仓库地址、合并请求流程、CI/CD 配置等平台能力上。二十一、配置 SSH 免密推送HTTPS 地址可以直接使用账号认证但团队开发更常见的是配置 SSH。生成 SSH 密钥ssh-keygen-trsa-Cyour_emailexample.com一路回车后会在用户目录下生成~/.ssh/id_rsa ~/.ssh/id_rsa.pub其中id_rsa是私钥不能泄露。id_rsa.pub是公钥可以添加到 GitHub / GitLab / Gitee。查看公钥cat~/.ssh/id_rsa.pub把公钥内容复制到平台的 SSH Keys 设置中。之后远程地址可以使用gitgithub.com:yourname/your-repo.git测试连接ssh-Tgitgithub.com二十二、IDEA 中集成 Git在 IntelliJ IDEA 中配置 Git打开Settings。进入Version Control - Git。配置Path to Git executable选择本机 Git 安装目录下的git.exe。点击Test看到 Git 版本号说明配置成功。常见操作Commit提交到本地仓库。Push推送到远程仓库。Pull拉取远程代码。Branches创建、切换、合并分支。Resolve Conflicts图形化解决冲突。建议初学者先掌握命令行再使用 IDEA 图形界面。因为图形界面只是把命令包装起来真正出问题时命令行能力更可靠。二十三、Git 图形工具gitk和git guiGit 自带两个图形工具。查看提交历史gitk打开图形化提交界面gitgui这些工具可以直观看到提交链路、分支合并、标签等信息。对于理解 Git 分支指针很有帮助。二十四、GitLab 常用管理命令如果是企业内部自建 GitLab常见管理命令如下# 启动所有 GitLab 组件gitlab-ctl start# 停止所有 GitLab 组件gitlab-ctl stop# 重启所有 GitLab 组件gitlab-ctl restart# 查看服务状态gitlab-ctl status# 重新加载配置gitlab-ctl reconfigure# 查看日志gitlab-ctltail# 检查 GitLabgitlab-rake gitlab:checkSANITIZEtrue--trace修改配置文件vim/etc/gitlab/gitlab.rb修改后通常需要gitlab-ctl reconfigure gitlab-ctl restart如果只是普通开发者不需要掌握 GitLab 安装部署细节重点掌握建仓库、加成员、配置 SSH、克隆、推送、提交合并请求即可。二十五、Git 常见问题速查1.git add .、git add -A、git add -u有什么区别命令作用git add .添加当前目录下的新文件和修改文件新版 Git 也会处理删除git add -A添加所有变化包括新增、修改、删除git add -u添加已跟踪文件的修改和删除不包括新文件日常开发中最常用gitadd.更严谨时使用gitadd-A2. 为什么.gitignore配了还是会提交因为文件已经被 Git 跟踪。先取消跟踪gitrm--cachedfile.txt目录则使用gitrm-r--cachedtarget/3. 推送时提示 rejected 怎么办通常是远程有新提交本地落后了。gitpullgitpush如果有冲突先解决冲突再推送。4. 不小心提交错了分支怎么办如果还没推送可以先记录提交号再切到正确分支 cherry-pickgitlog--onelinegitswitch correct-branchgitcherry-pickcommit_id然后回到错误分支回退gitswitch wrong-branchgitreset--hardHEAD^如果已经推送到公共分支不要随便reset --hard后强推先和团队沟通。5. 代码写到一半需要切分支怎么办gitstash push-munfinished featuregitswitch other-branch回来后gitswitch original-branchgitstash pop二十六、Git 高频命令速查表目标命令初始化仓库git init查看状态git status添加文件git add file.txt添加全部改动git add .提交git commit -m message查看日志git log --oneline --graph --decorate --all查看差异git diff查看暂存区差异git diff --cached撤销工作区修改git restore file.txt取消暂存git restore --staged file.txt回退版本git reset --hard commit_id查看历史操作git reflog查看分支git branch创建分支git branch dev切换分支git switch dev创建并切换分支git switch -c dev合并分支git merge dev删除分支git branch -d dev强制删除分支git branch -D dev临时保存修改git stash push -m message查看 stashgit stash list恢复 stashgit stash pop添加远程仓库git remote add origin url查看远程仓库git remote -v克隆仓库git clone url拉取远程代码git pull推送代码git push第一次推送分支git push -u origin main查看远程分支git branch -a删除远程分支git push origin --delete branch创建标签git tag v1.0.0创建附注标签git tag -a v1.0.0 -m release推送标签git push origin v1.0.0推送所有标签git push origin --tags删除本地标签git tag -d v1.0.0删除远程标签git push origin :refs/tags/v1.0.0二十七、建议的新手学习路线如果你是第一次学 Git不建议一上来就背所有命令。可以按这个顺序学先理解工作区、暂存区、本地仓库、远程仓库。掌握init、status、add、commit。学会log、diff、restore、reset。学会创建、切换、合并、删除分支。学会解决冲突。学会remote、clone、pull、push。学会stash和tag。最后再学 GitHub / GitLab 的团队协作流程。把 Git 学透后你会发现它不是一个“上传代码工具”而是一个完整的版本管理和团队协作系统。总结Git 的核心可以浓缩成三句话本地开发靠工作区、暂存区、本地仓库完成版本记录。团队协作靠远程仓库、分支、合并和冲突解决完成代码同步。项目发布靠标签、稳定分支和规范提交保证版本可追踪。真正掌握 Git不是记住所有命令而是理解每条命令在“哪个区域之间移动代码”。只要搞清楚工作区、暂存区、本地仓库、远程仓库之间的流转关系再复杂的分支协作和冲突处理都会变得清晰。建议收藏本文后续遇到 Git 问题时直接按场景查命令。等你能熟练使用status、diff、log、branch、merge、pull、push、stash日常开发中的大多数 Git 问题基本都能自己解决。