一、为什么Git这么火?
学Git之前,我一直以为它只是个“保存代码历史”的工具。后来才发现,Git之所以能成为程序员必备技能,是因为它解决了团队协作中一个很现实的问题——很多人同时改同一份代码,怎么保证不乱?
Git的诞生本身就挺传奇的。Linux系统的创始人Linus Torvalds,在2005年之前一直靠手工合并全世界志愿者发来的代码。想想就知道有多痛苦——几千人给你发diff文件,你手动一个个合并。后来用了商业工具BitKeeper,结果因为有人破解协议,对方收回了免费使用权。Linus一怒之下,两周时间自己写了个Git出来。一个月后,整个Linux源码就切到了Git上。
从那时起,Git就成了开源社区的事实标准,GitHub上线后更是彻底点燃了它的普及。
二、集中式VS分布式:彻底搞懂区别
刚开始学Git时,我总搞不清它和SVN到底差在哪。后来自己用了一次SVN才明白。
集中式(SVN、CVS这类)就像一个公共图书馆。所有人都只能去这一个图书馆借书、还书、修改书的内容。如果你网络不好或者图书馆关门了,你什么都干不了。最要命的是,如果图书馆着火了(服务器挂了),所有书就都没了。
分布式(Git)则是每个人家里都有完整的图书馆副本。你可以随时在家看书、改书、记录修改。哪天想同步了,再和总馆对一下就行。哪怕总馆没了,随便找一个人家里的副本就能恢复全部内容。
这个区别带来的实际体验是:用Git时,git log、git diff、git branch这些操作都是秒回的,因为全在本地。而用SVN,每次查日志都要连服务器,等得心焦。
三、Git的设计理念:快照,不是差异
SVN记录的是“每次改了什么”——比如第3行从A改成B了,第7行新增了C。它存的是一系列差异补丁。
Git记录的是“每次提交时,所有文件的完整快照”。就像拍照一样,每次提交都拍一张“全家福”,把所有文件此刻的状态都记录下来。如果某个文件没变,Git不会重复存,只指向上一次的快照。
用久了就会发现,Git这种设计更符合直觉:我想回到某个版本,就是直接把那次快照还原出来,而不是“从当前版本往前算,把100个补丁一个个打回去”。
四、Git的安装与初次配置
安装Git直接去官网(git-scm.com)下载对应系统的安装包就行。Windows用户建议安装时勾选“Git Bash Here”选项,这样在任何文件夹右键都能打开Git命令行。
安装完第一件事是配置用户名和邮箱。这一步很重要,因为每次提交都会记录这两个信息:
git config --global user.name "你的名字"
git config --global user.email "你的邮箱"
git config的配置分三个级别:仓库级别(--local,只对当前仓库生效)、用户级别(--global,对你所有仓库生效)、系统级别(--system,对整台电脑所有用户生效)。优先级是local > global > system。日常用global就够了。
五、理解Git的三大区域:工作区、暂存区、版本库
这可能是Git新手最容易晕的地方。我用一个比喻来帮你记住:
工作区就是你正在写代码的文件夹。相当于你的草稿纸,随意写随意改。
暂存区是git add之后文件待的地方。相当于你把写好的内容放到了一个“待提交区”,还没正式归档。
版本库是git commit之后文件真正存进去的地方。相当于正式归档入库了。
为什么要分三步(修改 → add → commit)?因为有时候你改了5个文件,但只想提交其中2个作为一次独立的修改,这时候就可以先add这2个,commit一次,再处理剩下的。如果所有修改必须一次性提交,反而不灵活。
六、Git最常用的几个命令
(一)初始化仓库和查看状态
在项目文件夹里执行 git init,会生成一个.git隐藏文件夹。这就是版本库的核心,所有提交记录都存这里。
任何时候想看看当前仓库的状态,敲 git status。这个命令会告诉你:哪些文件有改动没add,哪些已经add了没commit,以及当前在哪个分支。基本上,git status是我用得最频繁的命令。
(二)添加和提交
git add 文件名 把指定文件加入暂存区。git add . 是把当前目录所有改动都加入暂存区,日常开发最常用。
git commit -m "提交说明" 把暂存区的内容提交到版本库。提交说明一定要写清楚这次改了什么,方便以后查日志。
(三)查看历史
git log 显示所有提交历史。加 --pretty=oneline 可以让每条记录只显示一行,看着更清爽。
(四)版本回退
写代码难免改错想回到过去。Git提供了几种方式:
git reset --hard HEAD^ 回退到上一个版本。HEAD^^是上上个版本。HEAD~100是回退100个版本。
如果记不住回退了几个版本,用 git reflog 可以看到所有操作历史(包括reset操作),找到你想回去的那个版本的commit号,用 git reset --hard 版本号 就能跳回去。
七、分支:Git最强大的特性
刚开始用Git时,我一直以为master就是“主分支”,其他分支都是“次要”的。后来才明白,所有分支都是平等的,master只是Git默认创建的第一个分支而已。
分支的本质是什么?是一个指向某个提交的指针。创建分支就是创建一个新的指针,切换分支就是把HEAD指针指向另一个分支。所以Git创建分支极快,只是改了个指针而已。
(一)常用分支命令
git branch 查看所有分支,当前分支前面会有个*号。
git branch dev 创建一个叫dev的新分支。
git checkout dev 切换到dev分支。
git checkout -b dev 创建并切换到dev分支,这是最常用的快捷方式。
(二)合并分支
切回到master分支后,执行 git merge dev,就把dev的内容合并到master了。Git会自动进行三方合并,如果没有冲突就直接合并成功。
(三)冲突解决
当两个分支修改了同一个文件的同一行时,合并就会冲突。Git会在冲突的文件里标出:
<<<<<<< HEAD
我当前分支的修改
=======
对方分支的修改
>>>>>>> dev
你需要手动编辑这个文件,删掉那些标记符号,保留你想要的内容,然后重新add和commit。
第一次遇到冲突时我慌得不行,后来发现其实很简单——Git只是告诉你“两边都改了同一处,我猜不到你要哪个,你自己决定”。
(四)分支删除
合并完成后,可以删除分支:git branch -d dev。如果分支有未合并的内容,git会阻止删除,可以用 -D 强制删除。
八、Git Stash:临时藏起你的修改
这功能救过我很多次。有时候正在写一个功能,突然来了个紧急bug要处理。但代码才写一半,还没到可以提交的程度。这时候 git stash 就派上用场了。
git stash 会把工作区和暂存区的所有修改保存到一个栈里,让你的工作区恢复到干净状态。然后你可以放心切分支修bug。修完之后切回来,执行 git stash pop,之前的修改就全部恢复了。
git stash list 可以查看栈里保存了哪些修改。如果有多个stash,每次pop都会恢复最近的那个。
九、实际开发中常用的分支策略
学完基本命令后,我最大的困惑是:到底该怎么用分支?
后来看了很多团队的分支模型,总结出一套最常用的:
master(或main)分支:线上环境运行的代码,永远保持稳定可发布。
develop分支:日常开发的主线,所有新功能最终都会合到这里。
feature分支:每个新功能单独开一个分支,开发完合并到develop后删除。
release分支:准备发布时从develop拉出来,只修bug不做新功能,测试通过后合并到master。
hotfix分支:线上出了紧急bug,从master拉分支修,修完同时合并到master和develop。
这套策略的核心理念是:master永远稳定,develop持续集成,feature各玩各的互不影响。
十、总结一下
Git刚学时确实容易晕,因为概念比SVN多。但只要理解了几个核心点,后面就顺了:
第一,分布式意味着本地操作飞快,不需要时刻联网。
第二,三个区(工作区、暂存区、版本库)的流转是add → commit。
第三,分支就是指针,创建和切换都极快。
第四,多用git status和git log,不会迷路。
这学了一篇,但离精通还远。下一篇文章准备写.gitignore配置和远程仓库协作(push、pull、解决冲突)。先到这,我得去跑几个命令消化一下。