Git的基本操作以及原理介绍
文章目录
- 基本操作
- 创建git仓库
- 配置name和email
- .git目录的结构
- git add & git commit
- .git目录结构的变化
- git追踪管理的数据
- git的版本回退
- 回退的原理
- 回退的三种情况
- 版本库中文件的删除
- git分支管理
- 分支的删除
- 合并分支时的冲突
- 分支的合并模式
- 分支策略
- git stash
- 不要在master分支上解决冲突
- git的远程操作
- 将修改提交到远程仓库
- push时忽略特殊文件
- 配置命令的别名
- git的标签管理
- 推送标签
- git实战
- 同一分支下的多人协作(不推荐)
- 不同分支下的多人协作
- 为什么本地依然能看到远端已经删除的分支?
- git flow模型
git作为目前最主流的版本控制器,可以控制电脑中所有格式的文件
对于开发人员来说,通常使用git维护项目的源文件
那么什么是版本控制器?版本控制器是一个管理系统,用来记录每次的修改以及版本迭代(每次的版本数据)
基本操作
创建git仓库
要想使用git的版本控制,就需要创建一个git仓库,只有在仓库中的文件才会被git追踪管理
将当前所在目录初始化成git仓库:
git init
此时目录下会多出一个.git文件

配置name和email
使用git config进行配置
git config user.name "用户名"
git config user.email "邮箱地址"
这两个配置项必须与git远程仓库对应
查看配置项
git config -l

删除配置
git config --unset user.name
git config --unset user.email
使用--global选项选项,将配置应用于本地的所有git仓库:
git config --global user.name "用户名"
git config --global user.email "邮箱地址"
相应的,要删除全局的配置,只需要在删除命令中加上--global选项
.git目录的结构
查看一下git的目录树

我们不能修改.git下的所有文件,也不能更改.git的目录结构,这将导致git出错
在.git所在目录下创建了文件,文件会受到git的版本控制吗?

解释之前先说明两个概念:
- 版本库(即仓库):当前目录下的.git被称为版本库
- 除了.git之外的其他文件被称为工作区。我们只能修改工作区中的内容,不能修改版本库中的内容
工作区与版本库的关系:

版本库中,stage被称为暂存区,也叫索引index。此外还有一个master分支,由HEAD指针指向
工作区中的修改(新增、修改、删除)不会受到git的追踪
执行add命令后,git会将工作区中的修改写入暂存区
执行commit后,git会将暂存区中的修改提交到master分支中,此时修改真正地被写入版本库,这些修改才会受到git的追踪控制
此外,版本库中还有一个分区:objects对象库。对象库中存在多个对象,所有对工作区的修改都会被写入到这些对象中(这些对象保存了工作区的修改)
可以注意到暂存区和master都是目录树的结构,其中存储了文件,而这些文件中存储了对象库中对象的指针。也就是说,暂存区和master通过保存对象库中的对象指针,以表示当前的状态
执行add将修改暂存区的目录树,使之索引到对象库中的对象
执行commit操也修改master的目录树,使之索引到对象库中的对象
git add & git commit
将工作区中的修改写入暂存区中
git add filename [filename]
可以使用git add .,表示将当前目录下的所有修改写入暂存区中
将暂存区中的修改写入master分支(本地仓库)中
git commit -m "描述此次提交的目的"
使用git commit时,需要带上-m选项并输入此次提交的目的
如果直接输入git commit,我们将进入vim编辑器并输入此次提交的目的。显然直接使用-m选项是更方便的
打印时间从近到远的commit记录,记录包含了每次提交的提交目的
git log

其中commit id是经过hash得到的定长字符串。对于git log命令,携带--pretty=oneline选项,将简化打印的内容为一行

.git目录结构的变化
再创建两个文件,将其commit到仓库中

此时观察.git的目录结构

其中新增了index文件,即暂存区。执行add操作后,暂存区保存了工作区的修改,所以此时出现了index文件
此外还有存在一个HEAD文件
cat一下HEAD文件,发现指向了仓库中的master文件,也cat一下master文件

发现master文件保存了commit id,该commit id为最近一次commit操作的id
首先,master和index中保存着对象指针,指针指向的对象存储了工作区中的修改信息
所以commit id是一个指针,前两位为目录名,剩下的数字为文件名,这些文件存储在.git的objects目录下,可以在objects目录中找到对应文件
使用命令,打印object的信息
git cat-file -p commit id
-p选项可以将打印信息简化

(似乎不使用-p还无法打印信息)
可以看到object中记录了执行commit操作的用户名与邮箱,以及上一次的commit id
第一行还有一串commit id,git cat-file下,看看是什么

可以看到,该对象似乎保存了工作区中每个文件的object指针,每个文件对应的object中保存了文件的修改信息

ReadMe文件中,确实只有"hello git"这串字符串
总结一下,object保存了每次的commit信息,以及工作区中每个文件的修改信息。如何获取object的指针?master文件保存了最近一次commit对应的object指针,也保存了上一次commit的object指针
注意:要想将工作区中的修改提交到版本库中,必须先执行add将修改提交到工作区,再执行commit将修改提交到版本库,这两个操作不能颠倒
git追踪管理的数据
git追踪管理的不是文件,而是每一次的修改
修改ReadMe文件,使用git status命令查看当前仓库的状态

打印信息说,我们修改了ReadMe文件,但是暂存区中没有文件(no changes added)需要被提交
因为我们没有执行add
使用以下命令,查看工作区与暂存区中[某个文件]的差异
git diff [filename]

打印的是unix通用的diff格式:
---和a表示改动前,+++和b表示改动后
-1表示第一行为改动前的内容,+1表示之后的一行为改动后的内容,2表示改动后的内容到第二行结束
使用以下命令,查看版本库与工作区中[某个文件]的差异
git diff HEAD [filename]

将当前工作区的修改add到暂存区中,执行git status

打印信息说,当前暂存区中的信息已经准备好被提交了(changes to be committed)
并且指明了暂存区中修改的文件为ReadMe
commit之后,再执行commit status

打印信息说,工作区与暂存区都没有发生修改
git的版本回退
版本回退本质上是回退版本库中的内容
使用以下命令,进行版本回退
git reset [--soft | --mixed | --hard] [HEAD] -- commit id
- –soft:回退版本库中的内容
- –mixed:回退版本库与暂存区中的内容,可以指定需要回退的文件
- –hard:回退所有区域的内容
其中miexed为默认选项
之前说过,执行了git init后的目录下有三个区域,工作区、暂存区以及版本库(仓库),reset命令的不同选项将不同程度地回退这些区域中的内容
注意:hard选项需要慎用!因为它将回退工作区中的数据!
根据git log打印的commit id,进行hard选项的版本回退,使ReadMe中只有"hello git"

可以看到之前有的"appending…“消失,只剩下"hello git”,并且日志也进行了回退
如果你有回退之前的commit id,你甚至可以撤销回退,回退之前的回退

该commit id为回退之前的id,此时成功撤销了回退
同时日志的回退也被撤销了

如果想要撤销回退,执行git reflog可以查看所有add和commit的信息,其中就包含了commit id的前7个字符,使用commit id的前7个字符也能进行执行/撤销回退

而一旦找不到commit id,将无法执行/撤销回退的操作
回退的原理
为什么git的回退这么快?因为回退只是修改了master保存的指针
master存储了最近一次的commit id,也就是object指针。object对象记录了每一次的修改操作。版本回退本质上是在修改master的值,使master指向不同的object指针。此时仓库中最近一次的commit操作就被修改,最近一次的commit不同,仓库中的数据就不同
回退的三种情况
撤销操作的本质:防止错误的代码从版本库中被push到远程仓库中
用code表示错误的代码,那么将出现以下三种情况
| 工作区 | 暂存区 | 版本库 | 解决方法 |
|---|---|---|---|
| code | git checkout – | ||
| code | code | git reset + git checkout --或者git reset --hard | |
| code | code | code | git reset --hard,前提条件: commit之后没有push |
- 工作区中开发了大量代码,但是没有add,此时要撤销工作区中的修改
- 工作区中开发了大量代码,add了但是没有commit,此时要撤销工作区与暂存区的修改
- 工作区中开发了大量代码,add并且commit了,此时要撤销工作区、暂存区与版本库的修改
情况一:只有工作区需要回退代码
执行命令,将工作区的文件回退到最近一次add的状态,也就是和暂存区一致
git checkout -- filename
注意,必须要加上--,否则命令的效果完全不一样!

情况二:工作区和暂存区都需要回退代码
先修改ReadMe中的内容,添加"code"并且add修改到暂存区中

两种解决方法:
执行hard回退命令,使工作区与暂存区中的代码和版本库一致
git reset --hard HEAD filename

注意,git reset --hard不能回退指定文件,只有mixed模式能回退指定文件!
另一种方法:将情况二转换成情况一
执行命令,使暂存区中的代码回退,与版本库中的代码一致
git reset HEAD filename
HEAD指针指向了master分支,而master分支保存版本库的最近一次修改,即最新版本
所以git reset HEAD将使版本库和暂存区回退到当前版本,而版本库本来就是当前版本,所以只有暂存区回退到了当前版本
用git status验证:

此时git status说,暂存区中没有修改需要被提交,也就是暂存区的内容和工作区中的内容一致
此时执行git checkout -- ReadMe,使工作区中版本和暂存区中的版本一致即可

情况三:所有区域都需要回退代码
执行命令,将工作区、暂存区以及版本库中的代码回退到上一版本
git reset --hard HEAD^
(其中HEAD,表示上一次修改即当前版本,而HEAD^表示上一个版本,HEAD^^表示上两个版本…)
一般来说都是将代码回退到上一版本,但是具体来说是哪个版本,就需要根据情况决定了

版本库中文件的删除
第一种方式:
- 先删除工作区中的文件
- 再将修改提交到暂存区中
- 最后将暂存区中的修改提交到版本库中
rm file1
git add file1
git commit -m "delete file1"

可以看到当前版本库中已经没有file1文件了
第二种方式:
- 执行git rm,同时删除工作区与暂存区中对应文件
- 将暂存区中的修改commit到版本库中
其实就是git rm等价于rm+git add
git rm file2
git commit -m "delete file2"

可以看到当前目录只剩下了ReadMe文件
git分支管理
之前说过,HEAD指针指向master分支,master分支存储了一个对象指针,该对象保存了最近一次commit,查看该对象的数据

可以看到该对象中还保存了一个对象指针parent,分支下的每一次commit都有先后时间,根据时间顺序,保存每次修改的对象就形成了一条时间链。parent保存了时间链中,当前对象的上一个对象的指针
通过parent指针,我们就能不断地往前追溯历史commit
我们还可以在master主分支上创建分支,并对该分支提交修改,此时也将形成一条版本链
执行指令,查看当前git仓库中存在哪些分支
git branch -a
-a将显示本地分支与远程分支,默认只显示本地分支

除了master分支,HEAD也能指向其他分支,由HEAD指向的分支被称为工作分支,也就是当前分支
执行命令,创建新的分支:
git brach dev

创建新的分支后的目录结构:

此时.git目录下出现了dev文件,查看该文件中的内容

发现它和master文件的内容一样,由此证明新建分支的数据基于原分支
切换分支
git checkout 分支名

* 在dev之前,说明当前HEAD指针指向了dev分支
也能使用一行命令完成分支的创建与切换:
git ckeckout -b 分支名
在dev分支中,修改ReadMe文件,并切换到master分支,查看ReadMe文件

发现只有在dev分支中才能看见修改后的ReadMe文件,而在master分支中,无法看见修改后的ReadMe文件
说明此次的修改被提交到了dev分支上,对master分支不可见
同理,在dev分支上提交数据后,refs/heads/dev保存的对象指针和refs/heads/master保存的对象指针不再相同

如何合并分支?首先要切回master分支
git checkout master
git merge 分支名

合并分支后,打印信息说,master分支下的ReadMe文件新增了一行数据
分支的删除
不能删除当前所在分支(工作分支),只能删除其他的分支
git branch -d 分支名
合并分支与删除分支的速度非常快。因此,git鼓励我们在分支上完成任务,合并到master分支中再删除分支,这样将更加安全
如果分支执行了add或者commit,但是没有被合并,此时无法使用-d删除该分支(git认为创建出来的分支都是要被merge的,只有在merge分支后,才能删除该分支),只能使用-D强制删除该分支
git branch -D 分支名
合并分支时的冲突
在dev分支中修改ReadMe文件,也在master分支中修改ReadMe文件,使两份文件不同
修改完文件我们要进行add和commit,使仓库中两个分支下的文件内容不同

此时执行合并操作

打印信息说合并失败,此时查看ReadMe文件
其中<<<<<<HEAD到=======之间为当前分支下的数据,========到dev之间为dev分支的数据,两者不相同所以产生了冲突
如何解决冲突?手动解决,在master分支中的冲突文件中保留想要的代码。解决冲突后执行add和commit,此时合并操作才算完成

查看当前日志

使用以下命令,可以以图表的形式看到master分支与dev分支之间的关系
git log --graph --abbrev-commit

分支的合并模式
如果执行命令
git merge 分支名
调试信息中有"fast-forward"字段时,说明这次的提交为ff模式
该模式的合并无法通过git log --graph --abbrev-commit查看,图中不会出现两个分支合并成一个分支的信息,因此我们无法得知master合并了哪个分支
ff模式的本质是将被合并分支的最近一次提交对象指针写入到master分支的最近一次提交对象指针中

当合并没有发生冲突时,git默认使用ff模式
此外,还有一种模式: no-ff,这种模式的合并可以通过git log --graph --abbrev-commit知道两哪个分支发生了合并
使用no-ff模式的合并:
git merge -no-ff -m "此次合并的目的" 被合并的分支名
由于合并完分支后,还需要进行commit操作,所以需要-m提交信息
分支策略
master主分支对应着线上环境,必须是十分稳定的,所以提交的代码需要能稳定运行,没有重大的bug
而其他分支则是不稳定,存在bug的。开发人员在这些分支上进行开发,进行一系列测试验证后,就能将其他分支上的代码合并到master分支中
基于分支,我们就能进行同一项目的多人同时开发,同时也演变出了多种分支策略
git stash
如果在其他分支中修改了文件,未进行add和commit,此时的操作将不受到git的版本控制,只是单纯的对工作区的修改。切回master分支后,可以在本地看见其他分支对文件的修改
若其他分支修改文件后,进行了add和commit,此时的操作将受到git的版本控制。切回master分支后,无法看见其他分支对文件的修改
如果不进行add和commit,又不想让master分支看见其他分支对文件的修改,可以使用命令
git stash
该命令将保存分支对文件的修改到一个特殊文件中,也就是将修改后的文件添加到git的版本控制中,此时master分支无法看见其他分支对于文件的修改

此时.git的目录树中,多了一个stash文件,用来保存分支中的修改

执行命令,打印stash中保存的修改
git stash list
如果在dev分支中修改了文件,并执行git stash,切出该分支,再切回dev分支
此时分支中的数据和master分支相同,要想恢复之前所做的修改,就需要执行命令,将stash中的修改恢复到分支中
git stash pop

不要在master分支上解决冲突
项目上线后可能遇到的场景:存在一个小bug,此时基于master分支创建分支fix_bug进行bug修复,修复成功后在master分支中合并fix_bug分支,项目再次上线
同时,项目的开发也在不断进行中,在发现bug之前,创建了一个分支dev开发新的功能。等到功能开发好时,项目已经不再是当时创建分支时的项目,而是修改了bug后的项目。此时在master分支中合并dev分支将产生冲突

我们不能直接合并dev分支,并在master分支上手动修改文件,这可能导致使修改后的文件出现bug
正确做法应该是:在dev分支上合并master分支并且手动修改冲突,测试没有问题后,再到master分支中合并dev分支
git的远程操作
git的全程叫做分布式版本控制系统,版本控制很好理解,如何理解分布式?
一个项目的开发往往需要多人的分工协作,之前所说的git仓库:工作区、暂存区以及版本库都是在本地运行的。一个开发人员对项目进行了修改,另一个开发人员要如何获取到他的修改呢?或者说如何让其他人看到我对项目的修改?
显然只使用本地的git无法解决这个问题。git为我们提供了一个解决方案,使用中央服务器存储git仓库,我们也叫它远程仓库
每个开发人员都能访问到远程仓库,需要开发项目时,从远端仓库将整个仓库拉取下来进行开发。开发完成后,将本地的修改提交到远程仓库中。那么其他开发人员就能通过远程仓库看到你对项目的开发,并且也能拉取你对项目的修改,进一步进行开发
用https克隆远程仓库,注意:不能在拥有.git目录的路径下(已经初始化过本地仓库的地方)克隆仓库!
克隆也能理解为第一次拉取
在远程仓库中可以找到该仓库的链接,通常有https和ssh协议,先演示https协议的克隆,将URL复制下来,执行命令
git clone URL

查看远程仓库的信息
git remote [-v]
直接使用git remote将打印本地仓库中已经配置的远程仓库名字,通常是origin

而git remote -v将查看已经配置的远程仓库列表,以及它们的URL。fetch表示本地拥有远程仓库的拉取权限,push则表示提交权限
用ssh克隆远程仓库:
需要先将本地服务器的公钥放到远端的git服务器中
如何配置git服务器的公钥?
找到个人设置中的相关配置项

点击添加公钥:

在本地服务器中生成公钥与私钥:
进入/~/.ssh目录,如果没有则创建目录
如果目录中没有id_rsa 和id_rsa.pub文件,则执行以下命令
ssh-keygen -t rsa -b 4096 -C "your_email@example.com"
其中-C选项表示添加注释信息,用来表示生成的密钥对的用途,将这个信息设置为自己的邮箱即可
输入命令后一直回车直到能够输入其他命令为止

此时目录下新增两个文件:id_rsa 和id_rsa.pub

生成后,将公钥(id_rsa.pub中的字符)写入git服务器中

此时执行命令,即可克隆仓库
git clone ssh链接

将修改提交到远程仓库
注意:不是将整个本地仓库的修改提交到远程仓库,而是将某个分支的修改提交到远程仓库
克隆完远程仓库后,需要配置user.name和user.email,这两个信息要和git服务器中的信息一致
首先在工作区中修改文件,并add与commit,最后执行push,将版本库中的修改提交到远程仓库
git push 仓库名 本地仓库的分支:远程仓库的分支
push其实做了两步操作:将本地仓库某个分支的修改提交到远程仓库中,将指定分支与远端分支进行合并
其中,仓库名是本地服务器配置的远程仓库的名字,一般是origin
同时指定要push哪个本地分支中的修改到远程仓库中的哪个分支,这两个分支名一般用:隔开,当两者相同时,可以只写一次分支名(github的master分支现在叫做main分支)

此时远程仓库中出现了分支的修改,新增了ReadMe文件

push操作的本质是本地分支与远端分支的交互,交互之前需要先建立连接。一般在克隆仓库时,本地仓库的master分支与远程仓库的master分支就自动建立了连接,可以直接使用git push。而其他分支没有建立连接,需要使用上面的长命令进行push操作
当本地仓库的版本领先于远程仓库的版本,此时进行push操作以推送更新
当远程仓库的版本领先于本地仓库的版本,此时要进行pull操作以同步与远程仓库的版本
假设远程仓库的hello.txt被其他人修改了并且push了,这是修改后的内容

此时我要进行下一步的开发,就必须与远程仓库的版本保持同步
使用pull命令完成同步
git pull 仓库名 本地仓库的分支:远程仓库的分支
pull和push的使用相同,pull其实也进行了两步操作:将远程仓库中指定分支的修改拉取到本地,与本地分支进行合并

push时忽略特殊文件
创建远程仓库中,可以勾选添加.gitignore文件的选项:指定一些不想被push的文件,这些文件的修改就不会被add到暂存区中,更不会被push到远程仓库中了
在.gitignore文件中的文件不会被git追踪管理,即忽略这些文件,.gitignore文件需要位于git工作区的根目录下
若新建仓库时没有勾选添加.gitignore文件的选项,后续想要添加该文件时,可以直接添加

该文件在工作区的根目录下

此时创建一个以so结尾的文件,并将当前目录下的所有文件add到工作区中,执行git status命令,查看哪些文件的修改需要被commit到版本库中

发现调试信息中,没有a.so文件只有.gitignore文件,说明.gitignore文件生效了
如何强制添加文件到暂存区中,就算该文件在.gitignore中出现?
为add添加-f选项,强制提交修改到暂存区中
git add -f filename

也可以在.gitignore文件中添加规则,使git不要不略某个文件的提交

!表示不忽略该文件的提交
如何判定某一文件是否被忽略?
git check-ignore -v filename

打印信息说,该文件被第三行的规则忽略了
配置命令的别名
git config --global alias.别名 '原名(不需要加git)'
给status起别名

git的标签管理
使用标签可以方便的查看信息,以及记录一些有意义的信息
执行命令,为最近的一次commit将被打上指定的标签
git tag 标签名
查看所有标签
git tag

.git的目录树中也出现了相应的目录,查看该文件

发现该文件存储了最近一次的commit id
为指定的commit打标签,先通过git log --pretty=oneline --abbrev-commit,列出所有commit id,找到想要打标签的commit id

执行
git tag 标签名 commitid
执行命令,为commit打标签并添加注释:
git tag -a 标签名 -m "注释内容" commit id
执行命令,查看标签的注释:
git show 标签名
git show将显示对应commit的详细信息,如果该commit的标签有注释,那么也将一起展示,如果没有则只显示其他信息

删除标签:
git tag -d 标签名
推送标签
git push 仓库名 标签名
推送所有标签:
git push 仓库名 --tags

删除远端仓库的标签(首先要先删除本地仓库的标签)
git push 仓库名 :标签名
git实战
同一分支下的多人协作(不推荐)
开发者1在dev分支下的hello.txt文件中添加"111",开发者2在dev分支下的test文件中添加"222"
先在远端仓库中添加新的分支

接着在两个开发者的机器上执行git pull,获取最新的仓库版本(新的分支)
但是执行git branch后,无法看到新的分支。这是因为远端的分支与本地的分支没有关系,所以就算拉取了,也不会执行分支合并的操作。使用git branch -r选项就能看到远端的分支

此时我们要在本地手动创建名字相同的分支,并将本地分支与远端分支建立连接
执行命令建立连接
git checkout -b 本地分支名 仓库名/远端分支名
除此之外,使用其他命令也能达到同样效果(前提是dev分支不存在)
git branch 本地分支名 仓库名/远端分支名v
git checkout 本地分支名
若dev分支存在,则执行
git branch --set-upstream-to=仓库名/远端分支名 本地分支名
git checkout 本地分支名

执行git branch -vv可以查看本地仓库与远端仓库的连接
为什么要建立连接?这样可以直接使用git push与git pull这样的短命令,而不使用git push origin main这样的长命令
开发者1完成操作,修改文件后add、commit、push三板斧

开发者2执行相同的操作

而开发者2修改完hello.txt却无法提交,原因是此时的远端仓库中hello.txt和开发者2本地仓库最近一次pull的版本不同(开发者1的提交导致版本的不同),此时提交将产生冲突
解决方法是:执行git pull,此时hello.txt文件产生冲突,手动修改冲突并重新add、commit、push即可

最后一步:将dev分支合并到master分支中
有两种方法:
- 将本地的dev分支合并到master分支中,再将master分支push到远端
- 在git服务器上提交pr(pull request)申请,由管理员审批后,合并将被执行
如何提交pr申请?

选择选项,将dev分支合并到main分支中,添加标题和内容后选择reviewers和addignees,点击新建pr
关于reviewers和addignees的区别,可以看这篇博客Git GitHub上的Reviewers和Assignees之间有什么区别|极客笔记 (deepinout.com)
相关人员审查没问题后,就会进行合并操作了
另一种方法是在本地执行merge操作,推荐使用pr合并方式,经过审查员的审查,合并操作会更加安全
首先,执行合并操作的开发人员的本地仓库中,dev分支可能不是最新,此时需要先pull拉取最新版本
git checkout dev
git pull
由于无法保证main分支也是最新的,所以也需要pull
git checkout main
git pull
由于无法保证将dev分支合并到main分支是否会发生冲突,所以先到dev分支下,将main分支合并到dev分支。若发生冲突则手动解决冲突
git checkout dev
git merge main
解决完冲突后,再回到main分支下,合并dev分支
git checkout main
git merge dev
最后进行push操作即可
git push
删除dev分支(可选)
git branch -d dev
可以看到同一分支下的多人协作非常麻烦,产生冲突的概率极大,需要不停的pull解决冲突
所以开发中的多人协作一般是在不同分支下进行的
不同分支下的多人协作
每个开发者(开发项目的不同功能)对应不同分支,在属于自己的分支上提交自己开发的代码
最后这些代码将合并到main分支下
如:开发者1在feature-1分支下提交file1文件,开发者2在feature-2分支下提交file2文件
开发者1:首先pull更新本地的master分支,然后在本地master分支下,创建feature-1分支,编辑文件file1并进行add和commit操作
git pull
git checkout -b feature-1
此时的push操作比较特殊,不能直接git push,而要执行
git push 远端仓库名 本地分支名
因为此时的远端仓库中没有feature-1分支,我们只是在本地创建了feature-1分支,所以这次的提交需要将整个分支进行提交
总结下:可以在本地创建新分支,也可以在远端创建新分支
- 在本地创建新分支后,需要将整个分支进行提交
- 而在远端创建新分支后,需要先pull获取远端的分支,再创建本地的同名分支并建立连接

此时远程仓库下已经存在feature-1分支了

开发者2执行与开发者1相同的操作:基于master分支创建新的分支feature-2,在该分支上编写文件file2,并执行add、commit以及push操作,在执行push操作之前需要先pull获取最新的远程仓库
开发过程中可能遇到的场景:开发者1需要帮助开发者2完成后续开发
此时开发者1的本地仓库中没有featrue-2分支,所以需要将该分支拉取下来

解释一下这时的pull为什么只需要使用短链接?
pull操作其实有两种:1. 拉取某一分支下的内容,此时需要使用长连接,如果本地分支与远端分支建立连接后即可使用短连接 2. 拉取仓库中的内容,如新的分支,此时使用短连接即可,但是拉取到的新分支不会和本地分支建立连接
但是拉取操作只是将远端的分支拉取下来,本地没有相应的分支,打印的信息提示我们要在本地创建相同的分支并与其链接
git checkout -b feature-2 origin/feature-2
此时处于feature-2分支下,继续编写该分支下的文件,完成开发者2未完成的代码
最后:将feature-1分支和feature-2分支合并到main分支下
在git服务端分别提交两次pr申请即可
在提交pr申请前,推荐先用其他分支合并main分支,解决可能存在的冲突,再用main分支合并其他分支,此时将不会产生冲突
为什么本地依然能看到远端已经删除的分支?
将远端分支删除后,本地使用git branch -a依然能看到远端分支,如何解决?


使用命令清理远端无用分支即可
git remote prune origin

此时远端分支只有main分支,剩下的本地分支用git branch -d删除即可
git flow模型
git flow模型是企业级常用的一种git分支设置规范,这只是一种常用的开发模型,并不适合于所有的开发团队。了解它有助于我们理解软件开发的流程

| 分支 | 名称 | 适用环境 |
|---|---|---|
| master | 主分支 | 生产环境 |
| release | 预发布分支 | 预发布/测试环境 |
| develop | 开发分支 | 开发环境 |
| feature | 需求开发分支 | 本地 |
| hotfix | 紧急修复分支 | 本地 |
| master分支 |
- master为主分支,该分支唯一且只读,用于部署正式发布环境,一般由合并release分支得到
- master分支为稳定的代码库,任何时候都不能直接在master分支上修改代码
- 产品的功能全部实现后,最终在master分支上对外发布。并且master分支上的所有提交都应该打标签(tag)做记录,方便追溯
- master分支不可删除
feature分支
- feature为新功能或新特性的开发分支,以develop分支为基础创建feature分支
- 命名通常为
feature/user_createtime_feature,表示开发人员,开发时间以及所开发的特性 - 新特性开发完成后需要将feature分支合并到develop分支中,且删除feature分支
develop分支
- develop为开发分支,基于master分支创建的唯一且只读分支,始终保持最新完成以及bug修复后的代码。可部署到对应开发集群
- 通常用来合并feature分支,也可直接在develop分支上开发
release分支
- release分支为预发布分支,基于develop分支创建,可以部署到测试或者预发布集群
- 通常的命名规则:
release/version_publishtime,表示发布的版本以及发布时间 - release分支通常用于提交给测试人员进行测试,若出现问题则需要验证develop是否出现问题,测试完成后可以删除release分支
hotfix分支
- hotfix为bug修复分支或补丁分支,主要用于线上版本的bug修复
- 命名规则通常为
hotfix/user_createtime_hotfix,表示相关人员,创建时间以及具体的bug - 问题修复完成,将其合并到master分支后删除
相关文章:
Git的基本操作以及原理介绍
文章目录 基本操作创建git仓库配置name和email .git目录的结构git add & git commit.git目录结构的变化 git追踪管理的数据git的版本回退回退的原理回退的三种情况 版本库中文件的删除git分支管理分支的删除合并分支时的冲突分支的合并模式分支策略git stash不要在master分…...
2023安全与软工顶会/刊中区块链智能合约相关论文
2023安全与软工顶会/刊中区块链智能合约相关论文 前言软工顶会ISSTAFSEASEICSE 软工顶刊TOSEMTSE 安全顶会S&PUSENIX SecurityCCSNDSS 前言 主要整理了2023年四大安全顶会、四大软工顶会和两个软工顶刊中,有关区块链智能合约的相关论文。 搜索方式是࿱…...
word文档转换为ppt文件,怎么做?
大家是否会遇到需要将word文档转换为ppt文件的情况?除了反反复复粘贴复制以外,还有其他方法可以转换文件格式,今天给大家分享word转换ppt方法。 首先我们先将word文件打开大纲模式 然后我们将文中的大标题设置为1级标题,副标题设…...
机器视觉选型-什么时候用远心镜头
物体厚 当被检测物体厚度较大,需要检测不止一个平面时,典型应用如食品盒,饮料瓶等。 物体位置变化 当被测物体的摆放位置不确定,可能跟镜头成一定角度时。 物体上下跳动 当被测物体在被检测过程中上下跳动,如生产线上下…...
quartz笔记
Quartz-CSDN博客 上面是Quartz的一些基本知识,如果对quartz的基本API不是很了解的话,建议先看下上面的 和Linux Crontab对比 1.执行粒度: Linux Crontab是进程级 quart是线程级 2.跨平台性: Crontab只能在Linxu运行 quart是java实现,可以跨平台 3.调度集上 Crontab的…...
ER 图是什么
文章目录 前言什么是 ER图ER 图实例简化的 ER 图总结 前言 产品经理在梳理产业业务逻辑的过程中,非常重要的一项工作就是梳理各个业务对象之间的关系。如果涉及对象很对的时候,没有工具支持的话很难处理清楚。今天我们就来介绍一个梳理业务对象关系的工…...
PLC电力载波通讯,一种新的IoT通讯技术
前言: PLC-IoT 是 PLC 技术应用在物联场景的创新实践,有效解决电力线路信号干扰、衰减问题,支持 IP 化通信能力,使能终端设备智能化,构建智慧边缘联接。PLC让传统IoT有了更多的连接可能: 电力线通信技术适用的场景包括电力配用电网络、城市智慧路灯、交通路口信号灯、园…...
Elasticsearch:通过摄取管道加上嵌套向量对大型文档进行分块轻松地实现段落搜索
作者:VECTOR SEARCH 向量搜索是一种基于含义而不是精确或不精确的 token 匹配技术来搜索数据的强大方法。 然而,强大的向量搜索的文本嵌入模型只能按几个句子的顺序处理短文本段落,而不是可以处理任意大量文本的基于 BM25 的技术。 现在&…...
OpenCV图像纹理
LBP描述 LBP(Local Binary Pattern,局部二值模式)是一种用来描述图像局部纹理特征的算子;它具有旋转不变性和灰度不变性等显著的优点。它是首先由T. Ojala, M.Pietikinen, 和D. Harwood 在1994年提出,用于纹理特征提取…...
自媒体写手提问常用的ChatGPT通用提示词模板
如何撰写一篇具有吸引力和可读性的自媒体文章? 如何确定自媒体文章的主题和受众群体? 如何为自媒体文章取一个引人入胜的标题? 如何让自媒体文章的开头更加吸引人? 如何为自媒体文章构建一个清晰、逻辑严谨的框架?…...
分类预测 | Matlab实现PSO-LSTM-Attention粒子群算法优化长短期记忆神经网络融合注意力机制多特征分类预测
分类预测 | Matlab实现PSO-LSTM-Attention粒子群算法优化长短期记忆神经网络融合注意力机制多特征分类预测 目录 分类预测 | Matlab实现PSO-LSTM-Attention粒子群算法优化长短期记忆神经网络融合注意力机制多特征分类预测分类效果基本描述程序设计参考资料 分类效果 基本描述 1…...
3GPP TS38.201 NR; Physical layer; General description (Release 18)
TS38.201是介绍性的标准,简单介绍了RAN的信道组成和PHY层承担的功能,下图是PHY层相关标准的关系。 文章目录 结构信道类型调制方式PHY层支持的过程物理层测量其他标准TS 38.202: Physical layer services provided by the physical layerTS 38.211: Ph…...
【GitLab】-HTTP 500 curl 22 The requested URL returned error: 500~SSH解决
写在前面 本文主要介绍通过SSH的方式拉取GitLab代码。 目录 写在前面一、场景描述二、具体步骤1.环境说明2.生成秘钥3.GitLab添加秘钥4.验证SSH方式4.更改原有HTTP方式为SSH 三、参考资料写在后面系列文章 一、场景描述 之前笔者是通过 HTTP Personal access token 的方式拉取…...
【如何学习Python自动化测试】—— 自动化测试环境搭建
1、 自动化测试环境搭建 1.1 为什么选择 Python 什么是python,引用python官方的说法就是“一种解释型的、面向对象、带有励志语义的高级程序设计语言”,对于很多测试人员来说,这段话包含了很多术语,而测试人员大多是希望利用编程…...
在通用jar包中引入其他spring boot starter,并在通用jar包中直接配置这些starter的yml相关属性
场景 我在通用jar包中引入 spring-boot-starter-actuator 这样希望引用通用jar的所有服务都可以直接使用 actuator 中的功能, 问题在于,正常情况下,actuator的配置都写在每个项目的yml文件中,这就意味着,虽然每个项目…...
Seaborn 回归(Regression)及矩阵(Matrix)绘图
Seaborn中的回归包括回归拟合曲线图以及回归误差图。Matrix图主要是热度图。 1. 回归及矩阵绘图API概述 seaborn中“回归”绘图函数共3个: lmplot(回归统计绘图):figure级regplot函数,绘图同regplot完全相同。(lm指lin…...
nginx学习(1)
一、下载安装NGINX: 先安装gcc-c编译器 yum install gcc-c yum install -y openssl openssl-devel(1)下载pcre-8.3.7.tar.gz 直接访问:http://downloads.sourceforge.net/project/pcre/pcre/8.37/pcre-8.37.tar.gz,就…...
CLEARTEXT communication to XX not permitted by network security policy 报错
在进行网络请求时,日志中打印 CLEARTEXT communication to XX not permitted by network security policy 原因: Android P系统网络访问安全策略升级,限制了非加密的流量请求 Android P系统限制了明文流量的网络请求,之下的版本…...
91.移动零(力扣)
问题描述 代码解决以及思想 class Solution { public:void moveZeroes(vector<int>& nums) {int left 0; // 左指针,用于指向当前非零元素应该放置的位置int right 0; // 右指针,用于遍历数组int len nums.size(); // 数组长度while …...
PatchMatchNet笔记
PatchMatchNet笔记 1 概述2 PatchmatchNet网络结构图2.1 多尺度特征提取2.2 基于学习的补丁匹配 3 性能评价 PatchmatchNet: Learned Multi-View Patchmatch Stereo:基于学习的多视角补丁匹配立体算法 1 概述 特点 高速,低内存,可以处理…...
[2025CVPR]DeepVideo-R1:基于难度感知回归GRPO的视频强化微调框架详解
突破视频大语言模型推理瓶颈,在多个视频基准上实现SOTA性能 一、核心问题与创新亮点 1.1 GRPO在视频任务中的两大挑战 安全措施依赖问题 GRPO使用min和clip函数限制策略更新幅度,导致: 梯度抑制:当新旧策略差异过大时梯度消失收敛困难:策略无法充分优化# 传统GRPO的梯…...
内存分配函数malloc kmalloc vmalloc
内存分配函数malloc kmalloc vmalloc malloc实现步骤: 1)请求大小调整:首先,malloc 需要调整用户请求的大小,以适应内部数据结构(例如,可能需要存储额外的元数据)。通常,这包括对齐调整,确保分配的内存地址满足特定硬件要求(如对齐到8字节或16字节边界)。 2)空闲…...
相机Camera日志实例分析之二:相机Camx【专业模式开启直方图拍照】单帧流程日志详解
【关注我,后续持续新增专题博文,谢谢!!!】 上一篇我们讲了: 这一篇我们开始讲: 目录 一、场景操作步骤 二、日志基础关键字分级如下 三、场景日志如下: 一、场景操作步骤 操作步…...
《Playwright:微软的自动化测试工具详解》
Playwright 简介:声明内容来自网络,将内容拼接整理出来的文档 Playwright 是微软开发的自动化测试工具,支持 Chrome、Firefox、Safari 等主流浏览器,提供多语言 API(Python、JavaScript、Java、.NET)。它的特点包括&a…...
JUC笔记(上)-复习 涉及死锁 volatile synchronized CAS 原子操作
一、上下文切换 即使单核CPU也可以进行多线程执行代码,CPU会给每个线程分配CPU时间片来实现这个机制。时间片非常短,所以CPU会不断地切换线程执行,从而让我们感觉多个线程是同时执行的。时间片一般是十几毫秒(ms)。通过时间片分配算法执行。…...
selenium学习实战【Python爬虫】
selenium学习实战【Python爬虫】 文章目录 selenium学习实战【Python爬虫】一、声明二、学习目标三、安装依赖3.1 安装selenium库3.2 安装浏览器驱动3.2.1 查看Edge版本3.2.2 驱动安装 四、代码讲解4.1 配置浏览器4.2 加载更多4.3 寻找内容4.4 完整代码 五、报告文件爬取5.1 提…...
Spring Cloud Gateway 中自定义验证码接口返回 404 的排查与解决
Spring Cloud Gateway 中自定义验证码接口返回 404 的排查与解决 问题背景 在一个基于 Spring Cloud Gateway WebFlux 构建的微服务项目中,新增了一个本地验证码接口 /code,使用函数式路由(RouterFunction)和 Hutool 的 Circle…...
SAP学习笔记 - 开发26 - 前端Fiori开发 OData V2 和 V4 的差异 (Deepseek整理)
上一章用到了V2 的概念,其实 Fiori当中还有 V4,咱们这一章来总结一下 V2 和 V4。 SAP学习笔记 - 开发25 - 前端Fiori开发 Remote OData Service(使用远端Odata服务),代理中间件(ui5-middleware-simpleproxy)-CSDN博客…...
iOS性能调优实战:借助克魔(KeyMob)与常用工具深度洞察App瓶颈
在日常iOS开发过程中,性能问题往往是最令人头疼的一类Bug。尤其是在App上线前的压测阶段或是处理用户反馈的高发期,开发者往往需要面对卡顿、崩溃、能耗异常、日志混乱等一系列问题。这些问题表面上看似偶发,但背后往往隐藏着系统资源调度不当…...
LangChain知识库管理后端接口:数据库操作详解—— 构建本地知识库系统的基础《二》
这段 Python 代码是一个完整的 知识库数据库操作模块,用于对本地知识库系统中的知识库进行增删改查(CRUD)操作。它基于 SQLAlchemy ORM 框架 和一个自定义的装饰器 with_session 实现数据库会话管理。 📘 一、整体功能概述 该模块…...
