☰
Git常用命令实战:从安装配置到分支合并与冲突排查
2026/10/1 11:01:18 网站建设 项目流程

1. Git简单命令到底解决什么问题

我最早接触Git的时候,完全是被“分布式版本控制”这几个字唬住的。那时候我连提交代码都要小心翼翼,生怕一个push把同事的代码冲掉。折腾了一段时间之后才发现,Git真正高频使用的命令其实就那么十几个,日常开发里90%的操作都在围绕“本地改代码、记录改动、推到远端、拉取更新”这一条主线转。把这十几个命令吃透,你就能非常舒服地完成个人项目管理和团队协作。

这篇笔记不是拿来背的,更像是一个“随查随用”的手册。你可以把它当作从零开始、但又不至于被各种底层概念淹没的实战指南。内容会覆盖Git安装与配置、最常用的基础命令、分支合并、撤销与修复、常见报错排查,以及几个我实际踩过的坑。无论你是刚装好Git的新手,还是已经在命令行里挣扎过一阵子的半新手,都应该能从中找到对自己有用的东西。

有人会问,现在各种IDE和图形客户端那么方便,为什么还要学命令行?我的看法是:图形界面帮你隐藏了细节,但一旦遇到冲突、分支错乱、历史改写这类问题,你还是得回来理解命令行。而且很多服务器、容器环境里只有命令行,你不可能每次都在本地用GUI操作完再上传。最关键的是,命令行里你能看到每个操作到底做了什么,心里有数,就不会慌。

2. 先把环境准备好:Git安装与配置

2.1 Windows、macOS、Linux安装Git

Git安装这件事本身不难,但不同系统略有差别。Windows下最省事的方式是下载官方安装包,一直点Next就行。我建议安装时把“Git Bash Here”和“Git GUI Here”这两个右键菜单选项勾上,后面很多操作在Git Bash里做要比在CMD里舒服得多。

在macOS上,可以直接用Homebrew来装,执行brew install git;不想装Homebrew也可以下载官方pkg安装包。Linux上则用系统自带的包管理器,Debian/Ubuntu用apt install git,CentOS/RHEL用yum install git。装完之后在终端里确认版本:

git --version

只要是能看到类似git version 2.39.2这样的输出,就说明装好了。顺便提一句,版本不是越新越好,能稳定用、和团队保持一致就行。有些老项目的脚本对太新的Git版本反而不兼容。

2.2 初始化配置:user.name和user.email

很多人装完Git就急着git init,结果第一次提交就报错,提示Please tell me who you are。原因很简单,Git需要知道每次提交的作者是谁。虽然这看起来只是两个字符串,但提交记录里会永久保留这些信息,所以不要随手填个乱七八糟的名字。

git config --global user.name "你的名字" git config --global user.email "你的邮箱"

这里用--global是全局配置,意思是这台机器上所有仓库默认都用它。如果你某个项目想用不同的身份,可以去掉--global,在仓库目录里单独设置。需要说明的是,个人项目无所谓,但在公司协作时,最好把用户名和邮箱设置成和公司账号一致,否则代码评审系统里很难定位到你的提交。

还有一个经常被忽略的配置:换行符处理。Windows和Linux的换行符不一样,如果不配置,团队协作时经常出现“整篇文章都被diff标记为修改”的诡异现象。我的建议很简单:Windows下执行下面两条命令,能避免大部分换行符问题。

git config --global core.autocrlf true git config --global core.safecrlf true

2.3 配置SSH密钥,实现免密推送

用HTTPS协议推代码,每次都要输用户名密码或Token,非常烦。所以我强烈建议配好SSH密钥,一次配置,长期省心。首先生成密钥:

ssh-keygen -t rsa -b 4096 -C "你的邮箱"

执行后会让你确认保存路径和密码,直接回车默认保存到~/.ssh/id_rsa,密码可以留空,也可以设置。然后把公钥内容复制出来,去GitHub的Settings里找到SSH and GPG keys,或者Gitee的安全设置里,新建一个SSH Key粘贴进去。

验证是否配置成功可以执行:

ssh -T git@github.com

如果返回Hi 用户名! You've successfully authenticated,说明配置成功。这时候你克隆仓库时用git@github.com:用户名/仓库名.git这种SSH地址,推送就不会再反复要密码了。

这里我想特别提醒:公钥是可以随意公开的,但私钥文件id_rsa绝不能泄露。如果你在云服务器上使用Git,不要把私钥上传到公开仓库,否则别人拿到后就能以你的身份操作代码仓库,这是非常危险的事情。

3. 每天都要用的核心命令:从clone到push

3.1 建立仓库:git init和git clone

git init是在本地目录里初始化一个全新的Git仓库,常见于你有一个已有项目,想把它纳入版本管理。执行后目录下会多出一个隐藏的.git文件夹,这就是Git的“数据库”,里面记录着所有历史版本和配置。注意不要手动去改.git里的文件,除非你真的知道自己在干什么。

git clone是从远程仓库复制一份代码到本地,和我们平时理解的“下载项目”类似,但它不只是把源码拉下来,还会把整个提交历史、所有分支引用都复制过来。用法很简单:

git clone git@github.com:用户名/仓库名.git

如果你只想克隆某个分支,可以加上-b参数。如果项目特别大,历史版本很多,觉得下载太慢,可以加--depth 1做浅克隆,只拉取最新一次提交。这个技巧在克隆大型仓库时非常实用,我实测过,有些全量克隆要好几分钟甚至更久,浅克隆可能只需要十几秒。

3.2 查看状态:git status

git status应该是我使用频率最高的命令。它能清楚地告诉你当前工作区是否干净,哪些文件被修改过,哪些文件还没被跟踪。我建议在每次执行提交之前都先看一下状态,避免把不该提交的临时文件一起推上去。

输出里通常有两类内容:Changes not staged for commit表示修改过的文件还没加入暂存区;Untracked files表示新文件还没被Git跟踪。前者用git add加入暂存,后者同样要先git add才会被跟踪。如果看到输出是nothing to commit, working tree clean,就说明当前没有任何改动,这种状态非常舒服。

3.3 把改动加入暂存区:git add

git add是Git操作里最容易让人困惑的一步,因为它的作用对象是一个叫“暂存区”的中间区域。你可以把它理解成“购物车”:先把你想要的东西放进去,最后统一结账。工作区里的文件改动是分散的,git add则是挑选哪些改动参与下一次提交。

常用写法有:

git add . # 添加当前目录下所有改动(新文件、修改、删除) git add filename # 只添加某个文件 git add -u # 只添加已跟踪文件的修改和删除,不添加新文件

这里我想多唠叨一句:git add .虽然方便,但有时候会误把日志文件、编译产物、IDE配置这些不该入库的东西加进去。所以项目里最好像样地维护一份.gitignore文件,把node_modules、dist、target、*.log这类内容排除掉。这样git add .才能用得放心。

3.4 记录一次改动:git commit

git commit是把暂存区的内容固化成一个新的版本节点。每次提交都应该有一个清晰的说明,否则回头看历史记录时,你根本不知道某次改动做了什么。基本命令是:

git commit -m "提交说明"

如果提交时忘了git add某些文件,你会看到提示no changes added to commit。这时候不要把git commit改成git commit -a草率处理,因为-a会把所有已跟踪文件的改动都提交进去,可能会带进你不想提交的内容。正确做法是回到git add,把该加的都加进来,再重新提交。

好的提交说明应该像一条短信:简明扼要,又能说清楚动机。比如修复登录页面在移动端显示错位的问题就比update强一百倍。如果团队有commit规范,比如要求带类型前缀feat:、fix:,就在-m里按照规范写。

3.5 推送到远程:git push

本地提交完成后,代码还只在你自己机器上,别人看不到。要想同步到远程仓库,需要执行git push。最简单的形式:

git push

Git会根据当前分支的“上游追踪关系”自动决定推送到哪个远程分支。如果是第一次推送一个新建的本地分支,需要加上-u参数:

git push -u origin branch-name

-u的含义是建立当前本地分支和远程分支的关联关系。这个关联非常有用,以后在这个分支上直接执行git push和git pull,就不需要再带远程分支名了。

3.6 拉取更新:git pull和git fetch

团队成员提交了代码,你本地需要同步,就要用到git pull。它实际上是git fetch加git merge的组合操作。先说一下git fetch,它会把远程的新提交下载到本地,但不会自动合并到当前工作区。执行后你需要手动决定是git merge还是git rebase。而git pull则一步到位,默认自动合并。

如果你不想本地落后太多、或者不想让每次合并都生成一个额外“Merge commit”,可以用git pull --rebase。它会把本地未推送的提交“挪”到最新代码之上,让历史看起来像一条直线。这个细节刚开始很难理解,用多了就能体会到:团队开发时保持线性历史,能显著减少写review时的心智负担。

这里提醒一下:在执行`git pull --rebase`之前,如果本地有未提交的改动,最好先把它们提交掉或暂存起来,否则很可能因为工作区冲突而中断。

4. 分支操作:并行开发的关键

4.1 查看与创建分支

分支是Git最具代表性的功能。它让我们可以在同一个人仓库里同时维护多个版本的代码。查看分支用:

git branch

默认只会显示本地分支,当前分支前面会带一个星号。加上-a参数会显示远程分支,格式类似remotes/origin/main。新建分支用:

git branch feature-new

这只是创建了分支,并没有切过去。切换到新分支需要执行git checkout feature-new,或者用更现代一点的写法git switch feature-new。git switch是后来新增的命令,语义上比checkout清晰,不容易误用。不过很多旧教程还是习惯用checkout,所以两种写法都要认识。

4.2 切换分支与工作区保护

切换分支时有一个很容易踩的坑:当前工作区有未提交的修改,切换分支后这些修改会被“带”过去。因为Git默认不允许在切换分支时丢失本地改动,它会把未提交的修改尝试应用到目标分支上。如果两个分支对同一个文件有不同改动,就会报错:Your local changes would be overwritten by checkout。解决办法是先把改动git add和git commit,或者先用git stash暂存起来。

git stash是另一个实用命令,它能把当前未提交的改动临时藏起来,让工作区回到干净状态,等切完分支再恢复。恢复时用git stash pop。我自己的习惯是:如果改动比较完整,就直接提交;如果只是临时切换分支看个东西,就stash。总之不要带着半成品切换分支,很容易把自己搞糊涂。

4.3 分支合并:git merge

分支合并是整个Git里最容易出现“事故”的地方。git merge的逻辑是:把另一个分支的改动合并到当前分支。比如你在dev分支开发完,想把dev合并回main,先切换到main,然后执行:

git checkout main git merge dev

如果两个分支没有冲突,Git会自动完成合并,生成一个新的提交或者fast-forward。fast-forward是指当前分支可以直接向前推进到目标分支的位置,不会产生额外合并节点。但如果两个分支都改动了同一个文件的同一段内容,就会出现冲突。Git会在冲突文件里插入类似下面这样的标记:

<<<<<<< HEAD 这是当前分支的内容 ======= 这是被合并分支的内容 >>>>>>> dev

冲突不是程序错误,它只是Git无法替你决定保留哪份代码。你需要手动打开文件,把不想要的内容删掉,保留正确内容,然后去掉<<<<<<<、=======、>>>>>>>这些标记,最后保存并git add,再提交。

4.4 删掉不要的分支

分支用完后要及时清理,否则分支列表会越来越乱。删除本地分支:

git branch -d branch-name

如果分支上有未合并的提交,Git会拒绝删除,并提示你使用-D强制删除。这个设计是为了防止你误删还没并入主干的工作。删除远程分支则用:

git push origin --delete branch-name

我见过不少新手把-d和-D当成一回事,结果辛辛苦苦写的一整段功能因为强制删除而彻底丢掉。所以遇到拒绝删除时,先想一想是不是还有未合并的代码,别上来就-D。

5. 撤销与历史修复:犯错之后怎么补救

5.1 工作区撤销:git restore

在git restore命令出现之前,我们习惯用git checkout -- filename来丢弃工作区某个文件的修改。现在更推荐的做法是:

git restore filename

这个操作会把文件恢复到最近一次提交时的状态。注意,这里恢复的是工作区文件,一旦执行,之前未提交的修改就真的没了。如果只是想撤销暂存区,不想动工作区,可以加--staged参数:

git restore --staged filename

它的作用是把文件从暂存区“移出来”,变成未暂存状态。常见场景是:你一时手快git add了一个不想提交的文件,用这个命令就能反悔,非常实用。

5.2 改写上一次提交:git commit --amend

如果你发现自己上一个提交写错了说明,或者漏提交了一个文件,不需要慌张。git commit --amend可以修改最近一次提交。很多人担心这个命令会“改写历史”,进一步产生混乱,但从实际使用看,只要还没推送,--amend是非常安全且高效的。

用法是:先把漏掉的文件git add,然后执行:

git commit --amend -m "新的提交说明"

执行后,上一次提交会被新提交替换,不会生成额外的“修正提交”。这也是热词里git commit --amend怎么使用这个问题的答案。需要特别注意:如果上一次提交已经推送到远程,并且有其他同事基于它拉了分支,那就不要再amend了。改写公共历史会让大家的分支对不上,让协作变得很痛苦。

5.3 回退历史版本:git reset和git revert

要回退到历史某个版本,常用的是git reset。它有三种模式,我用一张表来说明:

参数工作区暂存区历史记录
git reset --soft不变不变回退
git reset --mixed(默认)不变回退回退
git reset --hard回退回退回退

--soft适合你想重新整理提交,但不丢改动。--mixed适合撤销提交且保留工作区修改。--hard则是彻底回到某个版本,所有未提交和已提交的改动都可能丢失,使用前必须确认。我几乎只在本地分支回退时用--hard,一旦代码推送到远程共享分支,我更愿意用git revert。

git revert的思路不是删除提交,而是创建一个“反向提交”,把那次变更撤销掉。这样做的好处是保留历史记录,远程分支上其他人的工作也不会受影响。用法很简单:

git revert <commit-id>

它会自动打开编辑器让你填提交说明。这个命令适用于已经推送过的提交。记住一条原则:未推送的本地历史随便改,已推送的共享历史尽量用revert。

5.4 查看历史:git log

git log本身就是一条很基础的命令,但里面有不少实用技巧。最简洁的用法是:

git log --oneline --graph --all

加上--oneline可以让每条提交只显示一行摘要,--graph显示分支拓扑图,--all显示所有分支。这样你能很直观地看到整个项目的演进脉络。如果想要更详细的信息,直接执行git log,会显示提交人、时间、提交说明和完整哈希。

想找某个文件的历史,用git log -- 文件名;想找某个人提交的内容,用git log --author="名字"。这些组合不一定会用到,但知道会有帮助。我在排查“这段代码是谁改的”这类问题时,经常用git log -p来查看每次提交的具体改动内容。

6. 高频疑难杂症:报错排查与实用技巧

6.1 fatal: not a git repository

这个报错非常高频,很多新手在项目目录里执行Git命令时都会遇到。完整提示是:

fatal: not a git repository (or any of the parent directories): .git

核心意思是:当前目录或者它的父目录里没有.git文件夹,所以Git认为这不算一个仓库。解决办法很简单:要么在正确仓库目录下执行命令,要么先执行git init初始化仓库。还需要确认你确实进入了项目文件夹,有时候在终端里停留在别的目录,也会触发同样报错。检查方法是用pwd看当前路径,再用ls -a确认是否存在.git目录。

6.2 SSH认证失败与Permission denied

推送代码时如果你看到Permission denied (publickey),基本可以判断是SSH密钥没有正确配置。先用ssh -T git@github.com验证一下认证是否通过。如果提示权限错误,按下面的顺序排查:

  1. 检查本机是否存在~/.ssh目录,以及里面有id_rsa.pub。
  2. 确认公钥已经添加到平台账号的SSH Key配置里。
  3. 使用ssh-add ~/.ssh/id_rsa把私钥加到代理里,有些系统重启后需要重新添加。
  4. 检查远程地址是不是SSH格式,HTTPS地址和SSH地址要区分清楚。

还需要注意,如果你配置过多个平台的SSH密钥,或者在公司电脑上切换过Git账号,~/.ssh/config文件里的配置可能导致认证使用错误的密钥。我遇到过一次这种情况,排查了很久才发现是Host别名配置把请求导到了错误的服务器上。处理办法是在~/.ssh/config里为主机名和密钥路径指定明确的对应关系。

6.3 git push冲突和pull冲突

当远程分支已经有人提交了新代码,而你本地也提交了不同改动时,直接git push会被拒绝,提示failed to push some refs。正确的流程是:先git pull拉取远程更新,解决可能的冲突,再重新推送。

这里的核心原则是“先同步,再推送”,不要想着强行推送覆盖远端。如果明确知道自己就是要用本地版本覆盖远程,可以执行git push --force。但--force是一个非常危险的操作,它会覆盖远程历史,导致其他同事的本地分支丢失引用。除非是修复刚推送的错误提交,并且团队已经确认没问题,否则不要随手使用。更温和的方式是--force-with-lease,它会在推送前检查远程分支是否与你预期一致,降低误覆盖的风险。

6.4 Git LFS是什么,什么时候用

热词里出现了git lfs使用,这里顺带解释一下。Git本身更适合管理文本文件,因为每次改动都能按行比较和压缩存储。但如果仓库里有大量二进制大文件,比如设计稿、模型文件、音频视频,Git仓库会迅速膨胀,克隆和拉取都会变得极慢。Git LFS(Large File Storage)则是把这些大文件替换成一个轻量引用,真正的文件内容存放到远程LFS存储中。

安装LFS后,在每个需要它的仓库里执行一次:

git lfs install git lfs track "*.psd" git add .gitattributes

配置完成后,再提交.psd文件,Git会自动走LFS流程。注意.gitattributes文件记录了哪些文件类型走LFS,需要提交到仓库里。不然其他人克隆时不会触发LFS规则。

6.5 分支合并冲突处理流程

分支合并出现冲突时,不要慌,其实处理流程比较固定:

  1. 用git status查看哪些文件出现了冲突。
  2. 打开冲突文件,找到冲突标记,手动保留正确内容。
  3. 删除标记符号,保存文件。
  4. 使用git add标记冲突已解决。
  5. 使用git merge --continue完成合并提交。

如果你合并到一半突然发现方向不对,想回到合并前状态,可以执行git merge --abort。它会撤销本次合并带来的改动,让分支回到执行合并之前的样子。个人建议:新手第一次遇到冲突时,先读完标记中的两边内容,千万不要靠“感觉”删。如果是两个人改同一个方法,我一般先和对方确认需求,再删代码。

6.6 Git命令查询与学习建议

很多人问我,命令记不住怎么办。我的回答是:不用全记住,把最常用的十几条用熟练,剩下的靠git help和git <command> -h查参数就行。比如想查git commit的参数,直接输入:

git commit -h

Git会把所有选项解释列出来。中文环境可能显示英文,配合翻译工具看完全没有障碍。我更建议的是一种“场景化学习”方式:不要孤立地背命令,而是给自己设计几个场景,比如“模拟给开源项目贡献代码”,完整走一遍fork、clone、branch、commit、push、pull request的流程。这样一套走下来,命令之间的关系自然就清楚了。

最后再分享一个我自己的习惯:每学到一个新的Git命令,我都会单独建一个小仓库反复试验,随便写点文件、建几个分支、改改历史,看看到底会有什么结果。反正是测试仓库,怎么折腾都不心疼。很多关于Git的理解,我都是这样“试”出来的,而不是看文档看懂的。如果你也遇到过“命令看了很多遍,一用就错”的情况,不妨试试这个方法。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询