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 savegit pullgit stash pop
相关文章:

Git工作原理和常见问题处理方案
博客定位Git工作区域工作区域划分暂存区设计目的 Git基本操作核心操作初始化和配置指令 HEAD指针Git版本回滚指令介绍reset模式reset hard使用场景reset soft使用场景reset mixed使用场景reset使用注意事项checkout使用场景 Git分支管理什么是分支分支应用场景分支相关指令被合…...

C++-实现一个简单的菜单程序
C-实现一个简单的菜单程序 1,if-else语句实现1.1,代码实现1.2,功能检测 2,switch语句实现2.1,代码实现2.2,功能检测 1,if-else语句实现 实现一个简单的菜单程序,运行时显示"Men…...
Git更新 fork 的仓库
文章目录 确保本地仓库是最新的配置上游存储库(remote upstream)获取上游存储库的更改合并上游存储库的更改推送更改到你 fork 的仓库 确保本地仓库是最新的 在命令行中,导航到存储库的本地副本所在的目录,并执行以下命令: # 切换到主分支 …...

chorme安装esay scholar及chrome 无法从该网站添加应用、扩展程序和用户脚本解决方案
问题描述 如题,博主想安装easy scholar用于查询论文的分区,结果安装了半天一直出现chrome 无法从该网站添加应用、扩展程序和用户脚本解决方案的问题。 解决方案 先从这个网址下载:https://www.easyscholar.cc/download 然后对下载好的文…...

数据库-扩展语句,约束方式
扩展语句: 例: 自增长: auto_increment:表示该字段可以自增长,默认从一开始,每条记录会自动递增1 复制: 通过like这个语法直接复制ky32的表结构,只能复制表结构,不能复制表里面的…...

精密数据工匠:探索 Netty ChannelHandler 的奥秘
通过上篇文章(Netty入门 — Channel,把握 Netty 通信的命门),我们知道 Channel 是传输数据的通道,但是有了数据,也有数据通道,没有数据加工也是没有意义的,所以今天学习 Netty 的第四…...
Python四种基本结构的操作
列表 列表的创建有两种方法 SampleList [] SampleList list() 列表中元素的添加 append(obj):在列表末尾添加元素obj extend(seq):在列表末尾添加多个值,使用extend()函数,seq是一个可迭代对象,否则报错。 Inser…...
Eureka:com.netflix.discovery.TimedSupervisorTask - task supervisor timed out
1、原因是spring cloud netflix中,某个服务挂掉了或者是执行某个任务时间过长,而没有发送给Eureka心跳 ,导致调用不到指定的服务,所以检查被调用服务器是否有问题。 2、有可能是某一个微服务自身内部G了,导致没有向eu…...

1.spark standalone环境安装
概述 环境是spark 3.2.4 hadoop版本 3.2.4,所以官网下载的包为 spark-3.2.4-bin-hadoop3.2.tgz 在具体安装部署之前,需要先下载Spark的安装包,进到 spark的官网,点击download按钮 使用Spark的时候一般都是需要和Hadoop交互的&a…...

【问题解决】 avue dicUrl 动态参数加载字典数据(已解决)
事情是这样的,用了avue-crud组件,配置了一个option。 现在有一列source属性要展示为 多选的下拉框 ,当然问题不在这而在于,选项是需要根据同级别属性id去拿的。也就是option.column.source 的配置中 需要该行的option.col…...

学习一下,什么是预包装食品?
预包装食品,指预先定量包装或者制作在包装材料和容器中的食品;包括预先定量包装以及预先定量制作在包装材质和容器中并且在一定量限范围内具有统一的质量或体积标识的食品。简单说, 就是指在包装完成后即具有确定的量值,这一确定的…...

从零开始学习搭建量化平台笔记
从零开始学习搭建量化平台笔记 本笔记由纯新手小白开发学习记录,欢迎大佬请教指点留言,有空的话还可以认识一下,来上海请您喝咖啡~~ 2023/10/30:上份工作辞职并休息了几个月后,打算开始找个关于量化投资相关的工作。面…...
【whisper】在python中调用whisper提取字幕或翻译字幕到文本
最近在做视频处理相关的业务。其中有需要将视频提取字幕的需求,在我们实现过程中分为两步:先将音频分离,然后就用到了whisper来进行语音识别或者翻译。本文将详细介绍一下whisper的基本使用以及在python中调用whisper的两种方式。 一、whispe…...
git diff对比差异时指定或排除特定的文件和目录
文章目录 前言git diff指定或者排除文件指定文件和目录排除文件和目录 番外篇总结 前言 你一般什么时候会用GPT? 居然会有这种话题,答案就是作为程序员的我天天在用,虽然GPT有个胡说八道的毛病,但试试总没错的,就比如今天题目中这…...

数据结构介绍与时间、空间复杂度
数据结构介绍 什么是数据结构?什么是算法?数据结构和算法的重要性 数据结构定义 数据结构是计算机科学中研究数据组织、存储和管理的一门学科。数据结构描述了数据对象之间的关系,以及对数据对象进行操作的方法和规则。 常见的数据结构 数…...

(c语言进阶)字符串函数、字符分类函数和字符转换函数
一.求字符串长度 1.strlen() (1)基本概念 头文件:<string.h> (2)易错点:strlen()的返回值为无符号整形 #include<stdio.h> #include<string.h> int main() {const char* str1 "abcdef";const char* str2 "bbb&q…...

解决MySQL大版本升级导致.Net(C#)程序连接报错问题
数据库版本从MySQL 5.7.21 升级到 MySQL8.0.21 数据升级完成后,直接修改程序的数据库连接配置信息 <connectionStrings> <add name"myConnectionString" connectionString"server192.168.31.200;uidapp;pwdFgTDkn0q!75;databasemail;&q…...
Java 将对象List转为csv文件并上传远程文件服务器实现方案
问题情景: 最近项目中遇到了根据第三方系统传递过来的参数,封装为List<实体类对象>后,将该实体类转换为csv文件,然后上传到远程的sftp服务器指定目录的需求。 实现思路: List<实体类对象>转为csv文件的…...

分享8个分布式Kafka的使用场景
Kafka 最初是为海量日志处理而构建的。它保留消息直到过期,并让消费者按照自己的节奏提取消息。与它的前辈不同,Kafka 不仅仅是一个消息队列,它还是一个适用于各种情况的开源事件流平台。 1. 日志处理与分析 下图显示了典型的 ELK࿰…...
【再见了暗恋对象 朋友们看完之后的一些感悟】
【再见了暗恋对象】写完之后魏野是我的第一个读者,魏野的反应是:这就是青春啊,喜欢了一个不喜欢自己的人而且男生觉得很困扰女孩子喜欢被牵引着走,但是男孩子牵引就是因为不喜欢这个女孩子,好可怜!青春就这…...

多模态2025:技术路线“神仙打架”,视频生成冲上云霄
文|魏琳华 编|王一粟 一场大会,聚集了中国多模态大模型的“半壁江山”。 智源大会2025为期两天的论坛中,汇集了学界、创业公司和大厂等三方的热门选手,关于多模态的集中讨论达到了前所未有的热度。其中,…...
Leetcode 3576. Transform Array to All Equal Elements
Leetcode 3576. Transform Array to All Equal Elements 1. 解题思路2. 代码实现 题目链接:3576. Transform Array to All Equal Elements 1. 解题思路 这一题思路上就是分别考察一下是否能将其转化为全1或者全-1数组即可。 至于每一种情况是否可以达到…...

3.3.1_1 检错编码(奇偶校验码)
从这节课开始,我们会探讨数据链路层的差错控制功能,差错控制功能的主要目标是要发现并且解决一个帧内部的位错误,我们需要使用特殊的编码技术去发现帧内部的位错误,当我们发现位错误之后,通常来说有两种解决方案。第一…...
2024年赣州旅游投资集团社会招聘笔试真
2024年赣州旅游投资集团社会招聘笔试真 题 ( 满 分 1 0 0 分 时 间 1 2 0 分 钟 ) 一、单选题(每题只有一个正确答案,答错、不答或多答均不得分) 1.纪要的特点不包括()。 A.概括重点 B.指导传达 C. 客观纪实 D.有言必录 【答案】: D 2.1864年,()预言了电磁波的存在,并指出…...
AI编程--插件对比分析:CodeRider、GitHub Copilot及其他
AI编程插件对比分析:CodeRider、GitHub Copilot及其他 随着人工智能技术的快速发展,AI编程插件已成为提升开发者生产力的重要工具。CodeRider和GitHub Copilot作为市场上的领先者,分别以其独特的特性和生态系统吸引了大量开发者。本文将从功…...

Razor编程中@Html的方法使用大全
文章目录 1. 基础HTML辅助方法1.1 Html.ActionLink()1.2 Html.RouteLink()1.3 Html.Display() / Html.DisplayFor()1.4 Html.Editor() / Html.EditorFor()1.5 Html.Label() / Html.LabelFor()1.6 Html.TextBox() / Html.TextBoxFor() 2. 表单相关辅助方法2.1 Html.BeginForm() …...

Chromium 136 编译指南 Windows篇:depot_tools 配置与源码获取(二)
引言 工欲善其事,必先利其器。在完成了 Visual Studio 2022 和 Windows SDK 的安装后,我们即将接触到 Chromium 开发生态中最核心的工具——depot_tools。这个由 Google 精心打造的工具集,就像是连接开发者与 Chromium 庞大代码库的智能桥梁…...

springboot 日志类切面,接口成功记录日志,失败不记录
springboot 日志类切面,接口成功记录日志,失败不记录 自定义一个注解方法 import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target;/***…...
Docker拉取MySQL后数据库连接失败的解决方案
在使用Docker部署MySQL时,拉取并启动容器后,有时可能会遇到数据库连接失败的问题。这种问题可能由多种原因导致,包括配置错误、网络设置问题、权限问题等。本文将分析可能的原因,并提供解决方案。 一、确认MySQL容器的运行状态 …...

热门Chrome扩展程序存在明文传输风险,用户隐私安全受威胁
赛门铁克威胁猎手团队最新报告披露,数款拥有数百万活跃用户的Chrome扩展程序正在通过未加密的HTTP连接静默泄露用户敏感数据,严重威胁用户隐私安全。 知名扩展程序存在明文传输风险 尽管宣称提供安全浏览、数据分析或便捷界面等功能,但SEMR…...