基础须知
什么是版本管理和版本管理系统
git是一个VCS(Version Control System),用于管理修改了的code,支持不同的对于一个项目的版本管理,使其更容易与他人合作并实时记录一系列操作。当然文件文档也可以。有了git,就可以进行版本回溯、diff等操作,了解到一个项目的构建历史。当然也可以实现合并不同的分支、或者创建在不同的分支操作等等
安装
windows直接去github release下载,会有一系列操作告知的
linux在cli中根据不同的发行版进行拉取安装即可
分支 commit 等基础命令
GIT仓库保存目录下文件的 快照 ,并希望提交记录尽可能轻量
条件允许的情况下,它会将当前版本与仓库中的上一个版本进行对比,并把所有的差异打包到一起作为一个提交记录。
git会保存提交的历史记录
- 这也是为什么大多数提交记录的上面都有 parent 节点的原因
在本地commit存储和读取
|
|
Git Branch
“我想基于这个提交以及它所有的 parent 提交进行新的工作。”
Git的分支非常轻量,并且早建分支!多用分支!,分支会简单指向某个提交记录。
即使创建再多的分支也不会造成储存或内存上的开销,
branch和commit结合起来,便可以协同工作。
信息的管理
|
|
信息的合并和rebase
我要把这两个 parent 节点本身及它们所有的祖先都包含到一个分支
一般来说新建一个分支,在其上开发某个新功能,开发完成后再合并回主线。
图一
图二git merge bugFix后,main包含了所有对代码库的修改,之后我们也可以再次移动bugFix分支,将其merge到main上,此时所有的分支都会颜色相同,包含所有的代码修改
gir rebase为第二种办法,会取出一系列提交记录后复制到另外部分,图二便是在bugFix后rebase的结果,注意原本的提交记录会继续保留
|
|
GIT特性
HEAD
HEAD是对当前分支的符号引用,总是指向分支上最近一次提交记录。通常指向分支名,提交的时候修改分支状态,我们也可以通过HEAD以可见的样子看到状态。简单来说就是指向当前节点的
通常用来表示当前工作区基于哪个版本进行开发,也可以理解为当前开发所在分支的最后一次提交
|
|
分离的 HEAD
分离的 HEAD 就是让其指向了某个具体的提交记录而不是分支名。在命令执行之前的状态如下所示:
HEAD -> main -> C1
HEAD 指向 main, main 指向 C1。而如果我们check out C1了,则HEAD->C1
注意这里checkout 的地方是commit的标签,用于修改指向commit
记住!head的分离是基于commit的,而切换分支是不会分离的
那么分离头指针操作,适合的场景都有哪些呢?
如果我们想基于某次提交做一些新的尝试,而且不确定这些代码要不要合入正式分支的时候,可以使用这种方式。在这上面的修改不会影响其他分支,也不用创建新的分支
相对引用
git log用来查看提交对应的哈希
哈希值在真实的 Git 世界中也会更长(译者注:基于 SHA-1,共 40 位)git通常根据前几位就可以识别了
相对引用则非常给力,我们从一个易于记忆的地方开始计算
|
|
我们也可以用HEAD作为参照物
|
|
这样就可以不停向上了
你会想,会不会^后面也可以跟数字呢?可以的兄弟,可以的
|
|
实际上如果我们在HEAD上有多个分支,那么^后面跟的数字就是决定去哪一个分支,而不是步数
强制修改分支位置
|
|
撤销变更
- git reset 把分支记录回退几个提交记录实现撤销变更,原来指向的提交记录会变的像没有提交一样
reset对远程分支无效
-
git revert 则是用于远程分支的撤销
- 其会产生一次commit专门用来记录撤销
注意谨慎使用git reset –hard而彻底删除工作区和暂存区的修改,执行前务必确认没有需要保留的未提交内容。这时候就可以
-
git reflog 备份操作记录
- 误删也可以找到历史哈希值恢复:git reset –hard <哈希>
快捷的整理提交记录
git cherry-pick <commit1> <commit2>
可以方便快捷的把提交复制到HEAD下,形成新的提交分支链,我们可以用其来整理main分支
|
|
要在心里牢记 cherry-pick 可以将提交树上任何地方的提交记录取过来追加到 HEAD 上
由此可以有操作
|
|
来进行少量提交和整理
交互式rebase
使用带--interactive
的rebase命令,简写为-1
git rebase -i <commit>
其会打开一个UI界面列出被复制到目标分支的备选提交记录以及一系列的哈希、提交说明,可以确定顺序、选择的commit等
这个ui编辑器可以选为vim neovim nano等等
tag
给commit设定一个永远指向其的锚点tag
|
|
describe输出<tag>_<numcommits>_g<hash>
-
tag是离ref 最近的标签
-
numcommits是表示ref和tag相差多少提交记录
如下
远程仓库
当我们从远程clone的时候,例如在main分支,实际上是origin/<分支>即origin,这是远程分支的规范命名
<remote name>/<branch name>
,通常就是oringin
进行设置
根据不同的系统进行安装后,我们使用git config进行设置
|
|
进行基础设置
当我们在别的项目中进行初始化,则需要
git init,实现将一个已存在本地的项目变为一个git仓库或是初始化一个空仓库,也是我们经常使用的一个指令(没有初始化的仓库有很多指令是用不了的)
配置公钥ssh key
现在常用ed25519和rsa。目录在~/.ssh
|
|
然后到github添加ssh key后就可以将远程切换成ssh格式
|
|
然后就可以愉快的Push了
与远程进行交互、进行提交
|
|
注意!fetch不会更新本地的main分支,可以理解为只是对远程的数据进行了下载
可以通过下面方式合并到main,git pull则自动实现了fetch和merge的操作
|
|
pull requests?(PR)
远程服务器拒绝直接推送(push)提交到main, 因为策略配置要求 pull requests 来提交更新.
发生偏离了怎么办?
如果远程的分支和本地原本拉下来的分支出现了偏差,我们需要在push前进行rebase或者merge创建好新的合并分支。或者如上文进行git pull同步
|
|
这样便可以将我们的工作移动到最新的提交记录下
也可以直接
|
|
通常和远程工作的时候我们就会通过上面的方式同步到远程main下然后推送,这样远程的main始终是集成的开发分支
但是rebase的话不会保留原来的分支树,这时候就可以使用merge开始建立准备push到main的链后还保留原来的树
|
|
注意事项
提交
注意规范,
-
commit的时候注意自己“干了什么”
一个提交只做一件事(如 “修复登录按钮样式”“新增用户列表接口”),避免一次提交包含多个不相关的修改。这样后续回滚或查看历史时更精准。
❌ 不好:git commit -m “修改了一堆东西"
✅ 推荐:git commit -m “fix: 修复移动端登录按钮点击无响应问题" -
提交信息要规范
用简洁明了的语言描述 “做了什么”,最好遵循约定式提交(Conventional Commits):- feat: 新增xxx功能(新功能)
- fix: 修复xxxbug(bug 修复)
- docs: 更新接口文档(文档修改)
- refactor: 重构用户模块代码(代码重构,不影响功能)
避免模糊描述(如 “改了点东西”“更新”)。
-
提交前检查修改内容
提交前用 git status 确认要提交的文件,用 git diff 检查具体修改内容,避免误提交敏感信息(如密码、密钥)或无关文件(如日志、临时文件)。
分支
名称尽量有意义:
- feature/user-login(新功能:用户登录)
- bugfix/payment-error(bug 修复:支付错误)
- hotfix/security-vulnerability(紧急修复:安全漏洞)
避免 dev1、test (除非你在本地测试自己的仓库)等模糊名称。
主分支保持稳定:
main/master 分支应始终保持可部署状态,开发新功能时从主分支创建新分支,完成后通过 PR/MR 合并,
.gitingore
一开始以为是正则,结果不是,流汗了
- 普通文件名、目录
- 直接写名字就可以
- *.名称 通配符
- 递归匹配,例如src//*.test.txt匹配任意目录下的test
- / 放开头仅忽略根目录下文件
- !取消定义的忽略规则
一般会把dotfiles 环境变量 log cache等写入
一些特性
-
对跟踪的文件无效——即git add 或git commit过的文件,修改ignore也改不了
-
git rm --cached <file name>
#从commit暂存区移除保留本地文件
-
-
优先级是相对当前目录的,当然根目录就是整个仓库生效
参考链接
www.youtube.com/watch?v=2ReR1YJrNOM