Git工作原理和常见问题处理方案

  • 博客定位
  • Git工作区域
            • 工作区域划分
            • 暂存区设计目的
  • Git基本操作
            • 核心操作
            • 初始化和配置指令
  • HEAD指针
  • Git版本回滚
            • 指令介绍
            • reset模式
            • reset hard使用场景
            • reset soft使用场景
            • reset mixed使用场景
            • reset使用注意事项
            • checkout使用场景
  • Git分支管理
            • 什么是分支
            • 分支应用场景
            • 分支相关指令
            • 被合并分支和目标分支
            • merge模式
            • merge和rebase的区别
            • 分支合并的正确方式
            • merge合并完整流程
            • rebase合并完整流程
            • 常见的分支划分方案
  • Git分支仓库
            • fork操作完整流程
            • 本地仓库
  • 版本号标签
  • 文件对比
  • Git常见问题处理方案
            • Git是如何判断和解决冲突的
            • 提交代码的正确步骤是
            • 为什么push代码前,一定要先pull
            • 为什么pull代码前,一定要先commit
            • 怎么减少冲突的可能性
            • 想pull远程代码,又不想commit本地改动,怎么办

博客定位

本篇博客主要讲解Git应用场景和工作原理,以及核心用法

Git的每一个指令,都有非常多灵活的用法,这里不会将单个指令细化讲解

但是会比较全面地涵盖所有常用知识,对于非深度用户来说,用一辈子已经够了

Git工作区域

工作区域划分
  • Remote:远程仓库
  • Repository:本地仓库
  • Index:暂存区
  • Workspace:工作区
暂存区设计目的
  • 不必立刻将代码改动提交到仓库,可以等用户确认无误后再一次性提交
  • 可以有效减少错误提交的次数,并且可以随时通过Index查看改动了哪些代码

Git基本操作

上面的图片基本包含了Git系统的核心需求,其它需求都是围绕这些,在多人多仓库的情景下产生的

核心操作
  • add:将工作目录中新增或修改的内容,提交到暂存区
  • commit:将暂存区中所有的改动,一次性提交到本地仓库
  • push:将本地仓库中所有的改动,推送给远程仓库
  • fetch:将远程仓库的最新改动拉取到本地,但并不会将代码合并到本地,用于查看其他人对远程仓库的改动
  • merge:将一个仓库的代码合并到指定仓库,并更新工作区(准确说是合并分支,后面再说)
  • checkout:将工作区文件恢复到最近一次add/commit时的状态(也可用于分支切换,后面再说)
  • pull:拉取远程仓库代码,再合并到本地仓库,同时更新工作区,相当于fetch+merge
初始化和配置指令
  • init:在空目录创建一个Git仓库
  • config:配置或查询变量值,如配置账号
  • remote:添加或修改远程仓库,本地仓库可以同时和多个远程仓库进行互动
  • clone:从远程克隆仓库到本地,相当于init+remote+pull

HEAD指针

HEAD指针,是为了方便描述Git中的复杂操作,而抽象出来的一个概念

再Git系统中,所有仓库、所有分支中代码版本,都是用commit-id来表示的

Git系统简单概述起来,就是一个文本对比系统+commit-id-tree管理系统

HEAD指针,指向的就是本地仓库当前的commit-id

所有的Git合作,无非就是仓库切换,分支切换,pull到本地,push到远程

这些操作都要经过本地仓库,因此HEAD指针在描述复杂操作时,十分重要,但它本身仅仅代表本地仓库的commit-id而已

HEAD指针可以通过以下方式进行移动

  • 移动本地HEAD指针:git checkout commit-id
  • 移动特定分支的HEAD指针:git branch -f branch-name commit-id

Git版本回滚

Git用于版本回滚的有reset,revert,checkout三个指令,查看版本记录用log指令

指令介绍
  • log:查看提交历史,可以拿到每次提交对应的commit-id
  • reset:将本地仓库代码回退到指定的版本,并将中间的commit记录全部删除。此时在push,远程记录也会被删除
  • revert:将本地仓库代码回退到指定的版本,并保留所有更改记录。本质是将旧代码拉到本地,作为一个新版本去提交
  • checkout:将工作区代码回退到暂存区或本地仓库中的状态,即最近一次add/commit时的状态,不影响本地仓库和远程仓库代码
  • revert会产生新的commit-id,但reset不会

reset有三种模式,它们对本地仓库的改动都是一样的,但是对暂存区和工作区的处理方式有所不同

reset模式
  • hard模式:暂存区和工作区也会被重置
  • soft模式:暂存区和工作区仍然保留改动
  • mixed模式:暂存区被重置,工作区被保留
reset hard使用场景
  • 将本地所有改动回退到目标版本,并清除中间所有的提交记录
  • 使用方式:git reset --hard commit-id
reset soft使用场景
  • 提交了错误的commit,想要撤回记录
  • 发现merge处理方式错误,但想保留工作区最新代码
  • commit提交到错误的分支
reset mixed使用场景
  • 想保留工作区最新代码,同时想清空暂存区add记录
reset使用注意事项
  • reset只会回退本地代码,并不会回退远程仓库,如果想回退远程仓库,必须手动push本地代码
  • 由于HEAD指向的是已存在的旧版commit-id,远程仓库出于保护并不允许直接push,需要强制push
  • 强制推送指令:git push origin:main -f
  • GitLab会开启ForcePush保护,push -f 可能会识别,需要自己去网页关闭Repository Protect
checkout使用场景
  • checkout用于恢复工作区文件,指令不改变本地仓库和暂存区
  • 如果暂存区有未提交的add记录,则将工作区回退到上次add时的状态
  • 如果暂存区无记录,则将工作区回退到上次commit时的状态
  • 回退全部文件:git checkout – .
  • 回退指定文件:git checkout file1 file2

Git分支管理

什么是分支
  • 在单人开发、单版本开发的情景下,Git的版本记录是一个链表结构,版本要么新增,要么回退
  • 在多人开发、多个子功能同时开发、不同版本之间需要进行功能合并的情景下,链表结构的版本管理便无法再满足需求
  • 于是便诞生了树结构的版本管理方式,版本号允许新开分支进行单独的版本管理,而不影响主分支版本
  • 需要合并不同分支功能的时候,允许不同分支之间进行代码合并
分支应用场景
  • 开发版本和发布版本要独立维护
  • BUG修复和新功能开发需要独立进行
  • 两个小组开发不同功能,功能完成之前,不想同步彼此的代码
  • 不同服务器、不同客户的产品版本号不一样,需要独立维护
分支相关指令
  • 查看分支:git branch
  • 创建分支:git branch branch-name
  • 切换分支:git checkout branch-name
  • 合并分支:git merge branch-name 注意,merge只是将分支合并到本地仓库,并不会自动push到远程仓库
  • 删除分支:git branch -d branch-name
  • 取消分支合并:git reset --hard HEAD~
被合并分支和目标分支
  • 假定我们现在有两个分支,master和bugfix
  • bugfix分支修复了一些问题,现在要将这些修复合并到master
  • 此时我们称bugfix为被合并分支(merged-branch),master为目标分支(target-branch)
merge模式
  • fast-forward模式:当master分支没变动过时,如果想要合并bugfix的改动,直接将master头指针移动到bugfix头指针位置
  • no-fast-forward模式:即使master分支没有变动,仍然生成一个新的合并版本号,而不是快速移动指针
  • squash模式:合并方式和no-fast-forward一致,但合并时会将bugfix的所有中间提交记录合并成一个commit
  • git合并默认采用的是fast-forward模式,通过–no-ff,–squash参数指定另外两个模式
  • 这三种模式都是针对master本身没有变动的情况,在master有变动时,处理方式都是一样的
  • 在master有变动时,会采用类似于squash的方式,将bugfix所有改动合并成一个commit,合并到master
merge和rebase的区别
  • 合并指令除了merge之外,还有rebase指令,他们的主要区别在于生成commit记录的方式不同
  • merge会将bugfix的所有commit合并成一个新commit,合并到master上,同时移动master的HEAD指针到最新commit节点上
  • rebase会将bugfix的所有commit逐个合并到master上,形成多个新的commit节点,同时移动bugfix的HEAD指针到最新commit节点上
  • merge的目的在于将bugfix的改动合并到master,rebase的目的在于将master的改动合并到bugfix
  • merge和rebase,都只会改变其中一个分支的HEAD,如果想将两个分支合而为一,需要手动将另外一个分支的HEAD指针也移动到最新的commit节点
  • merge和base最大的区别在于,merge的记录比较简洁,rebase的记录比较详细,根据需要选择
分支合并的正确方式
  • 合并前请先将本地最新代码push到所在远程仓库,避免操作出错时导致本地改动丢失

  • 分支合并只会影响本地仓库,推送到远程仓库需要手动push

merge合并完整流程
  • 提交本地改动:git commit

  • 推送本地改动:git push

  • 切换到目标分支:git checkout master

  • 合并BUG分支:git merge bugfix

  • 推送合并结果到master:git push origin master

  • 移动bugfix到最新位置:git push -f origin bugfix

  • 以上代码根据实际需要来执行,不需要的步骤可以跳过

rebase合并完整流程
  • 提交本地改动:git commit
  • 推送本地改动:git push
  • 切换到目标分支:git checkout bugfix
  • 改变目标分支的基线:git rebase master
  • 推送合并结果到bugfix:git push origin bugfix
  • 移动master到最新位置:git push -f origin master
  • 以上代码根据实际需要来执行,不需要的步骤可以跳过
常见的分支划分方案
  • master:用于发布管理的分支,每个版本会贴上版本号标签
  • develop:日常开发用的分支
  • feature:独立功能开发用的分支,开发完毕合并到develop
  • release:为发布做准备的分支,来自develop,合并到master
  • hotfix:对已发布的版本做紧急BUG修复

Git分支仓库

Git可以通过Fork功能,创建一个拥有一模一样版本记录的仓库副本,并且允许这两个副本直接相互合并代码

GitHub开源项目的管理方式,运用的便是这一种方式,开发者不允许直接修改仓库,只能自己Fork一份仓库进行修改

修改结束后,可以向父仓库发起Merge Request,管理员审核通过后才会合并成功

fork操作完整流程
  • 从父仓库的Git页面中,点击Fork按钮,复制一份到自己的仓库
  • 将fork仓库拉到本地:git clone fork-git-url(fork仓库在本地的别名默认为origin)
  • 查看远程仓库配置:git remote -v
  • 添加父仓库配置到本地:git remote add parent parent-git-url(parent是父仓库的别名)
  • 拉取父仓库信息:git fetch parent
  • 合并父仓库分支代码:git merge parent/main
  • 推送分支代码到fork仓库:git push origin main
本地仓库
  • 本地仓库本身相当于一个独立的分支仓库,可以创建子分支,可以从任何分支拉取代码,也可以向任何分支推送代码
  • Git也可以没有远程仓库,只创建本地仓库,此时仍然能使用commit和revert,但不能再使用push和pull
  • Git的大多指令,都是针对本地仓库进行操作的,只有经过push后,才会推送到远程仓库
  • Git中通过树结构,记录了所有分支的版本号演变过程,如果push会导致版本树后退,那么必须使用push -f才能强制推送
  • 如果我们不想手动解决冲突,并且确定自己的代码是最终的、正确的,也可以通过push -f来强制推送

版本号标签

标签是给版本号起的一个别名,方便记住和操作

  • 查看标签列表:git tag
  • 给当前分支最新版本打标签:git tag tag-name
  • 给指定版本打标签:git tag tag-name commit-id
  • 删除指定标签:git tag -d tag-name
  • 推送标签到远程仓库:git push origin --tags
  • 添加和删除标签都需要push,才能对远程仓库生效

文件对比

  • 对比分支差异:git diff <branch-name-1> <branch-name-2> [specified-path] [specified-file]
  • 查看工作区和指定分支差异:git diff <branch-name>
  • 对比版本号差异:git diff <commit-id-1> <commit-id-2>

Git常见问题处理方案

Git是如何判断和解决冲突的

Git是基于文件名和文本行来判断冲突的

如果两个来自不同用户的commit,都修改了同一个文件的同一行文本,即被视为冲突

Git命令行工具会列出具体冲突的文件和行数,手动编辑文件解决冲突后,再重新合并代码

如果用的是图形化工具或IDE插件的话,一般会自己弹出对比窗口,方便用户去预览和修改冲突

提交代码的正确步骤是

add => commit => pull => push

为什么push代码前,一定要先pull

因为从上次拉取代码,到现在提交代码,中间远程仓库的代码可能已经被修改了

这样就有可能和我们的修改产生冲突,所以必须先pull远程代码改动,解决冲突后再提交

为什么pull代码前,一定要先commit

因为pull代码可能会和工作区代码产生冲突

只有将工作区的改动commit到本地仓库,Git才能在pull时对比出冲突的地方

如果不commit的话,pull会将远程仓库的代码同时拉到本地仓库和工作区,这样未提交的本地改动将会丢失

怎么减少冲突的可能性

每次准备修改代码前,先pull远程代码

每次push代码前,先pull远程代码

不要隔很久才push代码,做完一小块完整任务就可以push

这些措施虽然不能避免冲突,但是可以将冲突限制在小范围内,降低了merge难度

想pull远程代码,又不想commit本地改动,怎么办

git stash save指令可用于将本地改动缓存到暂存区

这样本地的代码就还原到改动前的状态,就可以从远程pull代码了

pull完代码之后再通过git stash pop,可以再将之前的改动合并到pull后的代码当中

如果pull的代码和save的代码有冲突的话,需要手动去解决冲突

git stash save

git pull

git stash pop

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/112564.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

在Photoshop中如何校正倾斜的图片

在Photoshop中如何校正倾斜的图片呢&#xff1f;今天就教大家如何操作。 将需要操作的图片拉到PS软件中&#xff0c;自动形成项目。 点击上方“滤镜”中的“镜头校正”。 进入“镜头校正”窗口&#xff0c;点击左侧的“拉直工具”。文章源自设计学徒自学网-http://www.sx1c.co…

【webrtc】 对视频质量的码率控制的测试与探索

目录 环境设置 transport-cc goog-remb (webrtc中的两种码率算法&#xff09; 修改成remb算法 测试 效果 后续 可参考工程 环境设置 要到meshx上操作 telnet 112 然后执行factory_env show |grep meshx_ip 之后telnet meshx_ip 用户名admin 密码****.119 执行一下r…

css矩形盒子实现虚线流动边框+css实现step连接箭头

由于项目里需要手写步骤条 且实现指定状态边框虚线流动效果&#xff0c;故使用css去绘制步骤条连接箭头和绘制边框流动效果 效果&#xff1a; 1.绘制步骤条连接箭头 <ul class"process-list"><div v-for"(process, index) in processes" :key&qu…

视频列表:点击某个视频进行播放,其余视频全部暂停(同时只播放一个视频)

目录 需求实现原理实现代码页面展示 需求 视频列表&#xff1a;点击某个视频进行播放&#xff0c;其余视频全部暂停&#xff08;同时只播放一个视频&#xff09; 实现原理 在 video 标签添加 自定义属性 id (必须唯一)给每个 video 标签 添加 play 视频播放事件播放视频时&…

前端性能瓶颈崩溃项目?Webpack助力解决!

&#x1f3ac; 江城开朗的豌豆&#xff1a;个人主页 &#x1f525; 个人专栏 :《 VUE 》 《 javaScript 》 &#x1f4dd; 个人网站 :《 江城开朗的豌豆&#x1fadb; 》 ⛺️ 生活的理想&#xff0c;就是为了理想的生活 ! 目录 ⭐ 专栏简介 &#x1f4d8; 文章引言 一、背…

数据结构详细笔记——二叉树

文章目录 二叉树的定义和基本术语特殊的二叉树满二叉树完全二叉树二叉排序树平衡二叉树 二叉树的常考性质完全二叉树的常考性质二叉树的存储结构顺序存储链式存储 二叉树的先中后序遍历先序遍历&#xff08;空间复杂度&#xff1a;O&#xff08;h&#xff09;&#xff09;中序遍…

【k8s】pod进阶

一、资源限制 1、资源限制的概念 当定义 Pod 时可以选择性地为每个容器设定所需要的资源数量。 最常见的可设定资源是 CPU 和内存大小&#xff0c;以及其他类型的资源。 当为 Pod 中的容器指定了 request 资源时&#xff0c;调度器就使用该信息来决定将 Pod 调度到哪个节点上…

【高光谱与多光谱:空间-光谱双优化模型驱动】

A Spatial–Spectral Dual-Optimization Model-Driven Deep Network for Hyperspectral and Multispectral Image Fusion &#xff08;一种用于高光谱与多光谱图像融合的空间-光谱双优化模型驱动深度网络&#xff09; 深度学习&#xff0c;特别是卷积神经网络&#xff08;CNN…

【Java 进阶篇】Java Response 输出字符数据案例

在Java Web开发中&#xff0c;使用HTTP响应对象&#xff08;Response&#xff09;来向客户端发送数据是一项非常重要的任务。本篇博客将详细介绍如何使用Java中的Response对象来输出字符数据&#xff0c;并提供示例代码以帮助读者更好地理解和应用这一概念。不仅将讨论基础知识…

java 申请堆外内存吗? java如何使用堆外内存?

java 申请堆外内存吗&#xff1f; java如何使用堆外内存&#xff1f; Java堆外内存管理 JVM可以使用的内存分外2种&#xff1a;堆内存和堆外内存&#xff1a; 堆内存完全由JVM负责分配和释放&#xff0c;如果程序没有缺陷代码导致内存泄露&#xff0c;那么就不会遇到java.lan…

【5G PHY】5G SS/PBCH块介绍(二)

博主未授权任何人或组织机构转载博主任何原创文章&#xff0c;感谢各位对原创的支持&#xff01; 博主链接 本人就职于国际知名终端厂商&#xff0c;负责modem芯片研发。 在5G早期负责终端数据业务层、核心网相关的开发工作&#xff0c;目前牵头6G算力网络技术标准研究。 博客…

工业4G路由器桥接多网络,提升工业环境网络覆盖

一款专为工业环境应用所设计的物联网通讯设备“工业4G路由器”&#xff0c;它具有多种功能和特性。其中之一就是桥接功能&#xff0c;在工业领域中被广泛应用并起着重要的通信作用。 桥接功能是指工业4G路由器通过无线网络的方式&#xff0c;为不同的工业设备提供网络并将其连…

【Linux】jdk、tomcat、MySQL环境搭建的配置安装,Linux更改后端端口

一、作用 工具的组合为开发者和系统管理员提供了构建和运行Java应用程序以及存储和管理数据的完整环境。 JDK&#xff08;Java Development Kit&#xff09;&#xff1a;JDK是Java开发工具包&#xff0c;它提供了开发和运行Java应用程序所需的工具和库。通过安装JDK&#xff0c…

git教程(2)---远程仓库操作

git教程---远程仓库 远程操作创建远程仓库克隆远程仓库HTTPSSSH 向远程仓库推送拉取远程仓库.gitignore文件给git指令起别名IssuesPull Requests 标签管理操作标签推送标签 多人协作场景一场景二 开发模型Git分支设计规范使用Gitee的DevOps平台体验项目开发流程 远程操作 创建…

vue+element ui中的el-button自定义icon图标

实现 button的icon属性自定义一个图标名称&#xff0c;这个自定义的图标名称会默认添加到button下i标签的class上&#xff0c;我们只需要设置i标签的样式就可以了 ##3. 按钮上使用自定义的icon 完整代码 <div class"lookBtn"><el-button icon"el-icon-…

Web3时代:探索DAO的未来之路

Web3 的兴起不仅代表着技术进步&#xff0c;更是对人类协作、创新和价值塑造方式的一次重大思考。在 Web3 时代&#xff0c;社区不再仅仅是共同兴趣的聚集点&#xff0c;而变成了一个价值交流和创新的平台。 去中心化&#xff1a;超越技术的革命 去中心化不仅仅是 Web3 的技术…

go 语言介绍

背景 一直有在零散的时间用go写点代码&#xff0c;正好借着最近比较有时间写东西的契机&#xff0c;给这个看着年轻&#xff0c;实际也已经发展10几年&#xff0c;并在当下众多开发领域都有不可忽视作用的语言做个介绍吧 golang 的起点 golang 的诞生可以说是时代造就了它&a…

MolFormer分子预训练模型

Large-scale chemical language representations capture molecular structure and properties&#xff08;2022&#xff0c;NMI&#xff09; 和原本transformer encoder的不同&#xff1a; 采用linear attention mechanismrotary positional embedding 模型 transformer e…

arcgispro中机器学习部分

参考链接 arcgis.learn 模块 |ArcGIS API for Python arcgis包位置 安装路径\GeoScene\Pro\bin\Python\envs\arcgispro-py3\Lib\site-package\arcgis 以automl进行训练工具为例&#xff0c;工具导入模块中涉及机器学习的模块 该模块所在位置 安装路径\GeoScene\Pro\bin\Py…

VCS与XRUN对语法支持的不同点(持续更新...)

静态方法声明位置不同&#xff1a;VCS支持声明在class内/外&#xff08;extern&#xff09;两种方式&#xff0c;XRUN只支持static function声明于类内&#xff0c;不支持类外声明&#xff08;带extern关键字&#xff09;。 字符串转二进制、8进制、十进制、16进制方法&#xf…