ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

Git自用手册:从安装配置到分支管理与远程协作

Git自用手册:从安装配置到分支管理与远程协作 1. 为什么你需要一份自己的Git手册Git这个东西只要你写代码迟早要跟它打交道。我自己刚开始用Git的时候也是靠到处搜命令、复制粘贴过来的时间一长就发现一个问题今天搜过的命令下周又忘了。网上教程倒是多但要么讲得太浅只告诉你“敲这个命令就能提交”要么又厚又全几百个命令塞进来看得人头晕。后来我干脆自己动手整理了一份“自用手册”——只记录我平时真正用到的命令每一条都写清楚它是干什么的、在什么场景下用、容易踩什么坑。这份手册从Git安装配置一直整理到日常提交、分支操作、远程仓库和免密设置用了好几年越用越顺手。今天把这份手册的内容分享出来你可以直接照着抄也可以根据自己的使用习惯改成你自己的版本。这份手册适合谁如果你是刚接触Git的新手它能帮你绕过很多弯路避免被网上那些互相矛盾的教程绕晕如果你已经用了一段时间但总记不住命令这份整理好的手册可以当个快捷参考就算你是老手我觉得里面关于免密配置和日常排查的部分也值得扫一眼说不定正好有你没注意过的细节。2. Git安装与初始配置先把地基打好2.1 不同平台的安装方式差别不大Git的安装在不同操作系统上其实差别不小但核心思路都是一样的装好一个命令行工具然后设置好你的身份信息。我接触比较多的是Windows和macOS两个平台Linux服务器上也用过分别说下。Windows平台推荐直接从官网下载安装包一路下一步就行。有几点要注意安装过程中会让你选编辑器默认的Vim对新手不太友好我建议直接选Notepad或者VS Code还有个选项是调整PATH环境变量一定要选“Git from the command line and also from 3rd-party software”这样你在任意终端里都能直接用Git命令不会出现“git不是内部或外部命令”的报错。macOS平台最简单的方式是安装Xcode Command Line Tools装完Git就跟着一起有了装的时候会弹窗授权。如果你想要更新一点的版本可以用Homebrew安装brew install git。我自己用的是Homebrew方式因为官方源里的版本通常比较新而且后续升级也方便。Linux平台分两类Debian系的用apt-get install gitRed Hat系的用yum install git装好之后基本没什么需要额外设置的东西。注意安装完成后先别急着开始用。第一件事是在终端里执行git --version确认安装成功。如果提示找不到命令多半是PATH配置出了问题回上一步检查一下。2.2 第一次使用前必须设置的两项身份信息Git每次提交代码的时候都会把提交人的名字和邮箱记录在提交历史里。这个信息不设置的话Git会用什么它会读取你系统的用户名但那个通常是一串乱码提交到远程仓库后别人根本不知道是谁提交的。设置命令也很简单git config --global user.name 你的名字 git config --global user.email 你的邮箱这里用了--global参数意思是这台机器上的所有仓库都默认使用这个身份。为什么要用--global如果你平时工作电脑和个人电脑混用每台电脑设置一次就够了不用每个仓库都重新配一遍。我见过有些同事提交的时候邮箱写错提交记录里一串错误的邮箱后面想让GitHub统计贡献度发现统计不到还得用filter-branch之类的工具去改历史非常麻烦。所以说这一步一定要在开始使用之前就设置好。查看当前配置用git config --list它会列出所有生效的配置项。如果想修改某一条重新执行一遍相同的配置命令就行后者会覆盖前者。2.3 三个我建议每个新手都配好的基础选项除了用户名和邮箱还有几个配置选项是我强烈建议装上就顺手配掉的这些配置能让后面用起来舒服很多。第一个是换行符设置。Windows和Linux/macOS的换行符不一样Windows用的是CRLFUnix系列用的是LF。如果团队里有人用Windows有人用macOS代码仓库里的换行符就很容易乱掉每次提交都显示大面积的改动实际内容却一行没变。我建议Windows用户执行git config --global core.autocrlf truemacOS和Linux用户执行git config --global core.autocrlf input这样Git在检出代码和提交代码的时候会自动处理换行符的转换减少这类噪音。第二个是别名设置。如果你觉得git status、git commit这样的命令敲起来太长可以设置别名git config --global alias.st status git config --global alias.ci commit git config --global alias.co checkout git config --global alias.br branch设置完以后git st就相当于git status了。我在自己手册里配了六个左右的别名用惯了之后效率提升挺明显的。网上有些开发者会用更激进的缩写比如把git checkout缩成git co我个人觉得太短反而没有可读性适可而止就好。第三个是默认编辑器。执行git config --global core.editor code --wait可以把编辑器设置成VS Code。这个配置的主要用途是当Git需要你输入提交信息或者处理合并冲突的时候会打开你指定的编辑器比默认的Vim对新手友好得多。2.4 用.gitignore忽略不需要进版本库的文件这个文件可以说是很多新手最容易漏掉的东西。不配.gitignore会有什么后果典型场景是Java项目里自动生成的target目录、Node项目里的node_modules、Python项目里的__pycache__还有一些IDE的配置目录比如.idea、.vscode这些文件会被一起提交到仓库里不仅把仓库撑得很大还会引起很多无意义的冲突。.gitignore文件的内容其实就是一个规则列表放在项目根目录每一行是一个忽略规则。例如target/ node_modules/ __pycache__/ *.log .idea/ .vscode/文件写好后下次执行git status就不会再看到这些目录的改动了。如果你想忽略一个已经被提交过的文件需要先把它从版本库里移除再添加忽略规则git rm -r --cached 目录名--cached参数的意思是只从Git的跟踪列表里移除保留本地文件。3. 日常基础操作提交、查看、对比与回退3.1 工作区、暂存区、版本库的三角关系不把这个概念搞清楚后面用命令的时候就是懵的。Git把事情分成了三个区域你正在编辑的文件所在的工作区、存放准备提交内容的暂存区、以及已经提交成功的版本库。我打个比方工作区就是你的办公桌暂存区是文件筐版本库是文件柜。你处理完一份文件先放在文件筐里git add攒了一批文件后统一归档到文件柜git commit。git status就是看看办公桌上和文件筐里都有哪些文件的状态。日常操作里最标准的流程就是三步git status # 查看当前状态 git add 文件名或目录 # 把改动放入暂存区 git commit -m 提交说明 # 把暂存区的内容提交到版本库刚入门的人最容易犯的一个错误是以为git commit会把你所有的改动都提交上去。实际上它只提交已经git add过的内容。如果你新改了一个文件但忘了git add直接git commit这个文件就不会出现在提交里。要查看当前仓库的状态随时执行git status。输出会分为两个部分Changes to be committed是已暂存的改动Changes not staged for commit是工作区有改动但还没暂存的。短格式用git status -s输出更精简每行一个文件左边两列分别表示暂存区状态和工作区状态。3.2 提交信息怎么写得清晰又不啰嗦提交信息是给未来的自己和其他同事看的不是给Git看的。我见过太多“update”“fix”“commit”这种没营养的提交信息过了一个月回看历史根本不知道当时改了什么。一个比较通用的写法是第一行用一句话概括这次提交做了什么不超过50个字符动词开头如果需要补充细节空一行后再写具体说明。比如修复登录接口在空密码时返回500的问题 - 增加密码为空的参数校验 - 补充对应的单元测试为什么要用这种格式因为git log默认只显示第一行太长的说明会被截断。如果你写了多行提交说明用git commit不加-m会打开编辑器让你输入写完保存退出就提交了。我个人的习惯是一次提交只做一件事。比如一个页面你要同时改样式和修逻辑我会建议你分成两次提交每次提交关联的任务更清晰。万一后面需要回退其中某部分改动单独的操作会方便很多。3.3 用log和diff追溯代码变化提交历史是一面镜子能照出项目是怎么一步步变成现在这样的。git log是查看提交历史的基本命令git log --oneline --graph --decorate --all这条命令组合了几个参数--oneline让每个提交只显示一行--graph显示分支合并的图状结构--decorate显示分支和标签指向的提交--all显示所有分支的历史。我建议你直接把这个组合设置成别名后面我会提到。要查看某个文件的修改历史用git log -- 文件名要查看某个提交具体改了什么用git show 提交ID。提交ID就是git log里显示的四十位十六进制字符串实际操作中可以只输入前几位就能识别。git diff用来查看改动内容。不带参数的git diff比较的是工作区和暂存区的差异git diff --cached比较的是暂存区和最近一次提交的差异git diff HEAD比较的是工作区与最近一次提交的差异包括所有已暂存和未暂存的改动。3.4 改错了怎么撤销reset、checkout、restore这部分是我见过最混乱的内容因为Git的撤销命令五花八门不同版本还有不同的推荐方式。我根据实际使用频率按场景整理了一份速查场景一文件改乱了想恢复到上次提交的状态。最简单的方式是git restore 文件名这个命令会丢弃工作区的改动把文件恢复成暂存区或最近一次提交的状态。场景二已经git add了但想取消暂存。执行git restore --staged 文件名文件内容不会变只是从暂存区挪回工作区。场景三提交完了发现提交错了想回退到上一个提交。这里要小心分两种没推送到远程仓库可以用git reset --soft HEAD~1这个命令会撤销最近一次提交但保留你的改动方便重新提交如果推送到了远程仓库而且别人可能已经拉取了就不建议用reset了应该用git revert 提交ID生成一个新的反向提交。注意git reset --hard是危险操作它会同时丢弃暂存区和工作区的所有改动并且无法通过Git恢复。除非你非常确定这些改动不需要了否则别碰--hard这个参数。这里有一个我自己的经验如果只是改错了我倾向于用git restore而不是git checkout -- 文件名因为前者语义更清晰不容易误操作。Git新版本默认推荐的就是restore但网上很多旧教程还在用checkout的方式你看到的时候别被绕晕。4. 分支管理与合并让代码并行推进4.1 分支是什么为什么要有分支简单理解分支就是一条独立的工作线。你可以在主干分支的基础上切出一个新分支在新分支上随意改动、提交不影响主线上其他人的工作。等你觉得改好了再合并回主线。为什么要用分支举个例子项目上线了一个稳定版本你要开始开发新功能这个功能可能要写两周。如果没有分支你写了一半的代码直接放在主干上同事拉代码就会拿到一个半成品甚至编译不过。正确做法是开一个feature/xxx分支在分支上开发开发完测试通过后再合回主干。分支名我建议遵循一定的规范比如功能分支用feature/功能描述修复分支用fix/问题描述发布分支用release/版本号。这个规范不是Git强制要求的但对团队协作确实有帮助一眼就能看出来每个分支的用途和进度。4.2 创建、切换、删除分支的日常操作git branch # 列出本地分支当前分支前面会有* git branch 新分支名 # 创建新分支 git checkout 分支名 # 切换分支 git switch 分支名 # 切换分支新命令 git checkout -b 新分支名 # 创建并切换 git switch -c 新分支名 # 创建并切换新命令 git branch -d 分支名 # 删除分支git switch是Git 2.23以后引入的新命令专门用来切换分支。为什么Git要引入一个新命令因为git checkout承担了太多职责既能切换分支又能恢复文件容易让人混淆。所以新版本的文档推荐用git switch做分支切换用git restore做文件恢复。删除分支这里有个小坑如果分支还没有合并直接执行git branch -d会报错。这时如果想强制删除需要用大写-D。-d之所以让你删不掉是Git在保护你的工作成果很多小白在这里卡住过。我自己的习惯是开发完一个功能、合并完分支以后顺手把本地和远程的分支都删掉保持分支列表干净。本地删除用git branch -d 分支名远程删除用git push origin --delete 分支名。4.3 合并操作的两种方式merge和rebase合并是把一个分支的改动集成到另一个分支的过程。Git提供了两种主要方式merge和rebase。git merge会产生一个“合并提交”Merge Commit它会把两个分支的历史合并成一个分叉再汇合的图状结构。这种方式的好处是保留了真实的历史流程缺点是历史图会比较复杂分支多了以后看起来像一团乱麻。git rebase则不同它的原理是把当前分支的提交“搬”到目标分支的顶端。比如你在feature分支上开发主干分支上别人又提交了几个新commit你执行git rebase mainGit会把你的提交摘下来然后按顺序重新应用到main的最新提交之后。结果是历史变成一条直线非常干净。那什么时候用merge什么时候用rebase我的实践经验是自己的开发阶段用rebase保持历史简洁提交合并请求后团队审核通过时用merge保留合并节点方便追踪功能上线的时间点。如果分支已经推送到远程仓库并且被多人拉取过不要轻易rebase因为rebase会改写提交ID其他人的本地历史会跟远程对不上。4.4 分支冲突的应对思路合并过程中最让人头疼的就是冲突。Git在合并时如果发现同一个文件的同一行在两边的版本不同它不知道该听谁的就停下来让你自己决定。解决冲突的过程其实不难核心就是三步# 1. 合并时发现冲突 git merge feature/login # 2. 用status查看哪些文件冲突 git status # 3. 打开冲突文件手动编辑打开冲突文件后你会看到类似这样的标记 HEAD 这是当前分支的内容 这是被合并分支的内容 feature/login你要做的就是决定保留哪部分、删除哪部分把这些标记也一并删掉然后重新git add这个文件再git commit完成合并提交。冲突并不是什么可怕的事关键是你得知道冲突标记长什么样、怎么处理。我见过不少新手一看到“CONFLICT”这个词就慌了觉得是不是把仓库弄坏了。其实你只要没做了--hard之类的破坏性操作仓库都是安全的冲突只是Git停下来等你做决策而已。5. 远程仓库与团队协作推送、拉取与免密配置5.1 克隆仓库并建立本地与远程的关联远程仓库是Git协作的枢纽。你把代码推送到远程别人从远程拉取大家就能共享同一份代码了。常见的远程仓库托管平台有GitHub、GitLab、Gitee等用法大同小异。如果你是从远程仓库开始一个项目第一步是克隆git clone https://github.com/用户名/仓库名.git克隆之后Git会自动把远程仓库的地址保存在origin这个远程仓库名下。你可以用git remote -v查看当前仓库关联了哪些远程地址。如果你是在本地已经建好仓库想把它关联到远程需要先添加远程地址再推送git remote add origin https://github.com/用户名/仓库名.git git push -u origin main-u参数的意思是设置上游分支把本地当前分支和远程的main分支关联起来。设置完成之后后面直接执行git push或git pull就能自动匹配到对应的远程分支不用再重复指定。5.2 推送和拉取的常见姿势git push的作用是把本地提交推送到远程仓库。git pull的作用是把远程提交拉取到本地并合并。还有一个经常被忽视的是git fetch它只把远程的改动下载到本地但不自动合并你可以先看看远程有什么变动再决定怎么处理。我自己的习惯是在动手写代码前先执行git pull同步一下远程最新状态每次提交完准备推送前再执行git pull --rebase把本地提交挪到最新的远程提交之后这样能避免很多无谓的合并提交。git pull --rebase和直接git pull的区别在于合并策略不同。直接pull等价于fetch加merge会产生合并节点--rebase则会在fetch之后执行rebase把本地的提交搬到远程最新提交的后面。如果你的本地提交还没推送到远程这个操作是很安全的但如果本地提交已经推送过且远端内容有更新就要小心了。推送到远程的时候可能会遇到强制更新被拒绝的问题。如果远程有改动而你没有先pullGit会拒绝推送提示“failed to push some refs”。这时候老老实实先pull再push别直接git push --force。--force会覆盖远程的提交记录如果覆盖了别人的工作成果后果很严重。5.3 免密配置为什么你的Git每次都让你输密码每次推送都需要输入用户名和密码这个问题很多人都会遇到也是很影响使用体验的事情。Git的免密配置本质上有两种方案一是用SSH密钥二是用凭据管理器缓存密码。先说SSH密钥方式。这个方案的原理是你在本地生成一对密钥公钥和私钥把公钥配置到远程仓库平台之后Git通过SSH协议连接远程服务器时服务器会用公钥验证你的身份私钥留在本地不需要再输密码。生成密钥的命令是ssh-keygen -t rsa -b 4096 -C 你的邮箱执行之后会问你要不要设置密码短语可以一路回车跳过。生成的密钥默认在~/.ssh/目录下id_rsa是私钥id_rsa.pub是公钥。然后用cat ~/.ssh/id_rsa.pub查看公钥内容复制到GitHub的Settings - SSH and GPG keys页面Add new key粘贴保存。配置完成后把克隆地址改成SSH格式即gitgithub.com:用户名/仓库名.git的形式。如果之前已经用HTTPS方式克隆的仓库可以直接修改远程地址git remote set-url origin gitgithub.com:用户名/仓库名.git再说HTTPS方式的免密。不用SSH密钥也行Git自带的凭据管理器可以把密码保存到系统里下次自动使用。Windows下安装Git时会自带Git Credential Manager默认就启用了macOS下可以用osxkeychaingit config --global credential.helper osxkeychain设置之后第一次推送输入一次密码之后就不会再问了。这两种方式怎么选我的看法是个人项目用HTTPS加凭据管理器最省事不用处理密钥的生成和配置但如果你配置好了SSH后续包括GitHub、GitLab、Gitee等多个平台都能复用同一把公钥而且SSH连接更稳定所以我个人偏爱SSH方式主要是一次配置长期免维护。5.4 多账号场景下的SSH配置技巧如果你有不止一个Git托管平台的账号或者一个平台上有多个账号SSH的配置就需要多一层设计。默认情况下SSH的密钥是固定的id_rsa但你可以通过配置文件来指定不同域名使用不同的密钥。在~/.ssh/目录下创建config文件内容大概长这样Host github.com HostName github.com User git IdentityFile ~/.ssh/id_rsa_github Host gitlab.com HostName gitlab.com User git IdentityFile ~/.ssh/id_rsa_gitlab这样不同平台的连接会使用各自对应的密钥。生成密钥的时候可以用不同的文件名比如id_rsa_github、id_rsa_gitlab然后把各自的公钥分别配置到对应平台。这个配置的坑在于文件权限。SSH要求~/.ssh目录的权限不能太宽松否则会报“Bad owner or permissions”的错误。Linux和macOS下用chmod 700 ~/.ssh和chmod 600 ~/.ssh/config就能解决。Windows系统上如果遇到类似问题右键文件属性安全选项里把权限收紧只保留当前用户的完全控制权限。6. 日常开发中的几个“早知道就好了”的技巧6.1 用别名把高频命令变得更简短我在前面提到过配置别名这里展开说一下。Git别名不止能缩短命令还能把一长串参数组合封装成一个简单命令。比如查看漂亮的提交历史可以用git config --global alias.lg log --oneline --graph --decorate --all配置完之后输入git lg就能看到带图状的提交历史。我用过的最顺手的几个别名st status -s co checkout ci commit br branch lg log --oneline --graph --decorate --all unstage restore --staged last log -1 HEAD设置别名的原理就是给一个长命令取个短名字本质上是把参数存下来了。你完全可以根据自己喜欢的缩写方式来定不用跟任何人一致。6.2 git stash临时保存正在做的事有一个场景很常见你在当前分支改了半天的代码突然有个紧急bug要处理但你不想把半成品提交上去。这时候git stash就非常有用。git stash # 保存当前改动工作区变干净 git stash list # 查看stash列表 git stash pop # 恢复最近的stash并删除记录 git stash apply # 恢复stash但保留记录我把stash理解成“临时储物柜”把正在做的事保存起来清空工作区去处理别的事情处理完了再从储物柜里拿出来继续。pop和apply的区别在于取出来之后要不要把储物柜里的记录删掉大多数场景用pop就够了如果你需要在多个分支复用同一份改动用apply。有一点要提醒stash默认不会保存未跟踪的新文件。如果你新建了一个文件还没有git add过直接stash是存不到的需要加-u参数git stash -u。6.3 查找哪一行代码是谁在什么时间改的排查问题的时候经常需要知道某一行代码是什么时候被谁改的为什么这么写。git blame就是干这个用的git blame 文件名执行之后每一行代码前面都会显示提交ID、作者、提交时间。如果某一行总是出问题顺着这个信息找当时的提交记录往往能快速定位到上下文。git log -p 文件名也可以看到这个文件每次修改的详细diff适合用来理解一个文件的历史演变过程。还有一个很实用的查找命令是git log -S 关键字它能找到“把某段代码从没有到有”的那个提交。比如你记得项目里曾经有人写过某个函数但现在找不到了就可以用这个命令搜历史提交。7. 常见问题排查与命令速查表7.1 根据实际问题场景快速定位解决方案Git报错信息比较多我把这些年实际工作中遇到频率最高的几个问题整理成了表格。不需要你能看懂所有英文报错只要照着表格里“对应解法”去执行就行。问题描述典型报错信息对应解法提交身份未设置Please tell me who you aregit config --global user.name/email本地分支落后远程failed to push some refs先git pull --rebase再git push执行命令提示不是git仓库not a git repository检查是否在项目目录里或执行git init初始化删除分支被拒绝not fully merged确认改动已合并或用git branch -D强制删除文件名称大小写改了但Git识别不到修改文件大小写后status无变化git mv 旧文件名 新文件名中文文件名显示为八进制乱码\346\265\213\350\257\225.txtgit config --global core.quotepath false最后一个问题的解法也挺有意思的。Git默认会把非ASCII字符转义成八进制显示导致中文文件名变成乱码设置core.quotepath false之后就能正常显示中文了。这个配置在Windows上经常被用到macOS上因为文件系统编码方式不同一般不需要。7.2 排查一个复杂问题的完整思路示例以一个我之前实际遇到过的场景为例同事反馈push代码时一直提示输入密码输对了还是报权限不足但另一台电脑上同样的仓库却没有问题。排查过程先分两边一边是远程仓库上的权限配置一边是本地客户端的认证方式。因为是同一账号远程权限基本可以排除。接着看本地用git remote -v发现仓库是HTTPS方式克隆的再确认凭据管理器有没有生效git config --global credential.helper结果发现输出为空——凭据管理器根本没配置。原因就找到了这台电脑装Git的时候用的是默认配置没有启用凭据管理器。解决方式很简单按远程仓库平台的要求重新配置凭据管理器缓存密码或者把远程地址改成SSH格式。整个过程不到五分钟但如果不知道从哪下手光靠搜索引擎来回试可能一下午就过去了。排查Git问题的基本思路其实就三步第一步复现问题并收集完整报错信息第二步判断问题是出在本地配置、远程配置还是网络连接上第三步针对性地查看相关配置项而不是盲目执行别人的建议。7.3 高频Git命令速查表最后放一份我自己整理的高频命令速查表覆盖日常使用中的绝大部分场景。你可以把它保存下来也可以打印贴在工位上用到的时候扫一眼就知道该敲什么。分类命令作用说明配置git config --global user.name设置全局用户名配置git config --global user.email设置全局邮箱配置git config --list查看全部配置初始化git init将当前目录初始化为Git仓库克隆git clone 地址克隆远程仓库到本地状态git status查看工作区状态暂存git add 文件添加文件到暂存区暂存git add .添加所有改动到暂存区提交git commit -m 说明提交暂存区内容查看git log --oneline简洁查看提交历史对比git diff查看工作区与暂存区的差异分支git branch 名称创建分支分支git checkout -b 名称创建并切换分支切换git switch 名称切换分支合并git merge 名称合并指定分支到当前分支撤销git restore 文件丢弃工作区改动撤销git restore --staged 文件取消暂存状态保存git stash临时保存改动恢复git stash pop恢复临时保存的改动远程git remote -v查看远程仓库地址远程git push推送本地提交到远程远程git pull拉取远程提交并合并远程git fetch拉取远程提交但不合并标签git tag 标签名给当前提交打标签提交git commit --amend修改最近一次提交信息Git命令本身学起来不算难真正难的是遇到问题时的分析思路和那些藏在经验里的“坑”。我这份手册是根据自己的实际使用习惯打磨出来的里面记录的每一条命令都经过数不清的项目验证。你可以按自己的需求增删调整——比如加上团队专用的分支命名规范、加上特殊的钩子脚本用法——最终让它变成真正的“自用手册”。写到这正好也提醒一句如果你之前一直都是网上查一条用一条建议你也抽个时间把常用命令整理一遍整理的过程本身就是一次很好的查漏补缺。
返回列表