当前位置: 首页 > article >正文

git原理与常用命令及其使用

认识工作区、暂存区、版本库

⼯作区:是在电脑上你要写代码或⽂件的⽬录。
暂存区:英⽂叫 stage 或 index。⼀般存放在 .git ⽬录下的 index ⽂件(.git/index)中,我们
把暂存区有时也叫作索引(index)。
版本库:⼜名仓库,英⽂名 repository 。⼯作区有⼀个隐藏⽬录 .git ,它不算⼯作区,⽽
是 Git 的版本库。这个版本库⾥⾯的所有⽂件都可以被 Git 管理起来,每个⽂件的修改、删除,Git
都能跟踪,以便任何时刻都可以追踪历史,或者在将来某个时刻可以“还原”。

图中左侧为⼯作区,右侧为版本库。Git 的版本库⾥存了很多东西,其中最重要的就是暂存区。
在创建 Git 版本库时,Git 会为我们⾃动创建⼀个唯⼀的 master 分⽀,以及指向 master 的⼀个指
针叫 HEAD。
当对⼯作区修改(或新增)的⽂件执⾏ git add 命令时,暂存区⽬录树的⽂件索引会被更新。
当执⾏提交操作 git commit 时,master 分⽀会做相应的更新,可以简单理解为暂存区的⽬录
树才会被真正写到版本库中。
必须要通过使用 git add 和 git commit 命令才能将⽂件添加到仓库中 进行管理!
1. index 就是我们的暂存区,add 后的内容都是添加到这⾥的。
2. HEAD 就是我们的默认指向 master 分⽀的指针
3. objects 为 Git 的对象库,⾥⾯包含了创建的各种版本库对象及内容。当执⾏ git add 命令
时,暂存区的⽬录树被更新,同时⼯作区修改(或新增)的⽂件内容被写⼊到对象库中的⼀个新的
对象中,就位于 ".git/objects" ⽬录下,让我们来看看这些对象有何⽤处:
查找 object 时要将 commit id 分成2部分,其前2位是⽂件夹名称,后38位是⽂件名称。
找到这个⽂件之后,⼀般不能直接看到⾥⾯是什么,该类⽂件是经过 (安全哈希算法)加密过的
⽂件,好在我们可以使⽤ git cat-file 命令来查看版本库对象的内容。
总结⼀下,在本地的 git 仓库中,有⼏个⽂件或者⽬录很特殊
  • index: 暂存区, git add 后会更新该内容。
  • HEAD: 默认指向 master 分⽀的⼀个指针。
  • refs/heads/master: ⽂件⾥保存当前 master 分⽀的最新 commit id 。
  • objects: 包含了创建的各种版本库对象及内容,可以简单理解为放了 git 维护的所有修改。

修改文件

Git 比其他版本控制系统设计得优秀,因为 Git 跟踪并管理的是修改,而非文件。
git diff [file] 命令用来显示暂存区和⼯作区⽂件的差异,显示的格式正是Unix通⽤的diff格
式。也可以使⽤ git diff HEAD -- [file] 命令来查看版本库和⼯作区⽂件的区别。
知道了对 ReadMe 做了什么修改后,再把它提交到本地仓库就放心了。

版本回退

git reset 命令语法格式为: git reset [--soft | --mixed | --hard]  [HEAD]
--mixed 为默认选项,使⽤时可以不⽤带该参数。该参数将暂存区的内容退回为指定提交版本内容,⼯作区⽂件保持不变。
--soft参数对于⼯作区和暂存区的内容都不变,只是将版本库回退到某个指定版本。
--hard参数将暂存区与⼯作区都退回到指定版本。切记⼯作区有未提交的代码时不要⽤这个命令,因为⼯作区会回滚,你没有提交的代码就再也找不回了,所以使⽤该参数前⼀定要慎重。
HEAD 说明:
可直接写成 commit id,表示指定退回的版本
HEAD 表示当前版本
HEAD^ 上⼀个版本   或HEAD^1 
HEAD^^ 上上⼀个版本     或HEAD^2
以此类推
version3 被用 git reset --hard 变成 version2 

git log 并不能打印出 version 3 的 commit id ,运⽓好的话我们可以从终端
上去找找之前的记录,运⽓不好的话 commit id 已经被我们搞丢了
Git 还提供了⼀个 git reflog

Git 版本回退的时候,也可以使⽤部分 commit id 来代表⽬标版本
Git 的版本回退速度⾮常快,因为 Git 在内部有个指向当前分支(此处是master)的
HEAD 指针, refs/heads/master 文件里保存当前 master 分⽀的最新 commit id 。当我们
在回退版本的时候,Git 仅仅是给 refs/heads/master 中存储⼀个特定的version,可以简单理解
成如下示意图

撤销修改

如果我们在我们的⼯作区写了很⻓时间代码,需求变更之类的情况

情况⼀:对于⼯作区的代码,还没有 add

可以使用  git checkout -- [file] 命令让⼯作区的
⽂件回到最近⼀次 add 或 commit 时的状态。 要注意 git checkout -- [file] 命令中的
-- 很重要,切记不要省略,⼀旦省略,该命令就变为其他意思了。

情况⼆:已经 add ,但没有 commit

add 后还是保存到了暂存区呢?怎么撤销呢?
git reset 回退命令,该命令如果使⽤ --mixed 参数,可以将暂存区
的内容退回为指定的版本内容,但⼯作区⽂件保持不变。那我们就可以只回退下暂存区的内容了

 git status 查看⼀下,发现现在暂存区是干净的,工作区有修改。

这时候就回到情况一了。

情况三:已经 add ,并且也 commit 了

不要担⼼,我们可以 git reset --hard HEAD^ 回退到上⼀个版本!不过,这是有条件的,就是
你还没有把⾃⼰的本地版本库推送到远程。还记得Git是分布式版本控制系统吗?我们后⾯会讲到远程
版本库,⼀旦你推送到远程版本库,你就真的惨了……

删除文件

工作区和版本库就不⼀致了,要删⽂件,目前除了要删⼯作区的⽂件,还要清除版本库的文件

确实要从版本库中删除该⽂件
不小心删错了

分支管理

每次提交,Git都把代码串成⼀条时间线,这条时间线就可以理解为是⼀个分⽀。
再来理解⼀下HEAD,HEAD 严格来说不是指向提交,⽽是指向master,master才是指向提交的,所 以,HEAD 指向的就是当前分支。每次提交,master分⽀都会向前移动⼀步,这样,随着你不断提交,master分⽀的线也越来越长,而HEAD只要⼀直指向master分支即可指向当前分支

创建分支

Git ⽀持我们查看或创建其他分⽀,在这⾥我们来创建第⼀个⾃⼰的分⽀ dev ,对应的命令为
git branch dev
当我们创建新的分⽀后,Git 新建了⼀个指针叫 dev, * 表示当前 HEAD 指向的分⽀是 master 分
⽀。另外,可以通过⽬录结构发现,新的 dev 分⽀
发现⽬前 dev 和 master 指向同⼀个修改。并且也可以验证下 HEAD ⽬前是指向 master 的。
cat .git/HEAD

切换分支

git checkout dev

切换到分支dev提交代码后,当再切换到 master 分⽀之时,HEAD 就指向了 master,当然看不到提交了

合并分支

git merge 

为了在 master 主分⽀上能看到新的提交,就需要合并分支
git merge dev # 合并 dev 分⽀
Updating 16623e1..3740dce
Fast-forward
ReadMe | 1 +
1 file changed, 1 insertion(+)
git merge 命令⽤于合并指定分⽀到当前分⽀。合并后,master 就能看到 dev 分⽀提交的内容
了。此时的状态如图如下所⽰。
git merge 命令⽤于合并指定分⽀到当前分⽀。合并后,master 就能看到 dev 分⽀提交的内容
了。此时的状态如图如下所显示。
Fast-forward 代表“快进模式”,也就是直接把master指向dev的当前提交,所以合并速度⾮常快。
当然,也不是每次合并都能 Fast-forward,我们后⾯会讲其他方式的合并。
这种情况下,Git 只能试图把各⾃的修改合并起来,但这种合并就可能会有冲突

发现 ⽂件有冲突后,可以 cat ReadMe 直接查看⽂件内容,要说的是 Git 会⽤ <<<<<<<,=======,
>>>>>>> 来标记出不同分⽀的冲突内容
⼿动调整冲突代码,并需要再次提交修正后的结果
结果如下
记 dev1 分⽀使⽤完毕后就可以删除了

git log可以看分支状态

这样的好处是,从分⽀历史上就可以看出分⽀信息。例如我们现在已经删除了在合并冲突部分创建的 dev1 分⽀,但依旧能看到 master 其实是由其他分⽀合并
--no-ff 参数,表⽰禁⽤ Fast forward 模式。禁⽤ Fast forward 模式后合并会创建
⼀个新的 commit ,所以加上 -m 参数,把描述写进去。
git merge --no-ff -m "merge with no-ff" dev2
所以在合并分⽀时,加上 --no-ff 参数就可以⽤普通模式合并,合并后的历史有分⽀,能看出来曾
经做过合并,⽽ fast forward 合并就看不出来曾经做过合并。

删除分支

git branch -d dev

合并完成后, dev 分⽀对于我们来说就没用了, 那么dev分⽀就可以被删除掉,注意 如果当前正处于某分支下,就不能删除当前分⽀
因为创建、合并和删除分⽀非常快,所以Git⿎励你使⽤分⽀完成某个任务,合并后再删掉分⽀,这和直接在master分⽀上⼯作效果是⼀样的,但过程更安全

分支管理策略

在实际开发中,我们应该按照⼏个基本原则进⾏分⽀管理: ⾸先,master分⽀应该是⾮常稳定的,也就是仅⽤来发布新版本,平时不能在上⾯⼲活; 那在哪⼲活呢?⼲活都在dev分⽀上,也就是说,dev分⽀是不稳定的,到某个时候,⽐如1.0版本发布 时,再把dev分⽀合并到master上,在master分⽀发布1.0版本; 每个⼈都在dev分⽀上⼲活,每个⼈都有⾃⼰的分⽀,时不时地往dev分⽀上合并就 可以了。

所以,团队合作的分⽀看起来就像这样:

bug 分⽀

假如我们现在正在 dev2 分⽀上进⾏开发,开发到⼀半,突然发现 master 分⽀上⾯有 bug,需要
解决。在Git中,每个 bug 都可以通过⼀个新的临时分⽀来修复,修复后,合并分⽀,然后将临时分⽀删除。
Git 提供了 git stash 命令,可以将当前的⼯作区信息进⾏储藏,被储藏的内容可以在将来某个时
间恢复出来。
此时再用  git status 查看⼯作区,就是干净的(除⾮有没有被 Git 管理的⽂件),因此可以放⼼地创建分支来修复bug。 储藏 dev2 ⼯作区之后,由于我们要基于master分⽀修复 bug,所以需要切回 master 分⽀,再新建临时分⽀来修复 bug。
修复完成后,切换到 master 分⽀,并完成合并,最后删除 fix_bug 分支

⼯作区是⼲净的,刚才的⼯作现场存到哪去了?⽤ git stash list 命令看看:⼯作现场还在,Git 把 stash 内容存在某个地⽅了,但是需要恢复⼀下,如何恢复现场呢?我们可以使 ⽤ git stash pop 命令,恢复的同时会把 stash 也删了

恢复现场也可以采⽤ git stash apply 恢复,但是恢复后,stash内容并不删除,你需要
git stash drop 来删除; 你可以多次stash,恢复的时候,先⽤ git stash list 查看,然后恢复指定的stash,⽤命令 git stash apply stash@{0} ,这部分请同学们⾃⾏使⽤。 恢复完代码之后我们便可以继续完成开发,开发完成后便可以进⾏提交
我们的最终⽬的是要让 master 合并 dev2 分⽀的,那么正常情况下我们切回 master 分⽀直接合
并即可,但这样其实是有⼀定⻛险的。 是因为在合并分⽀时可能会有冲突,⽽代码冲突需要我们⼿动解决(在 master 上解决)。我们⽆法 保证对于冲突问题可以正确地⼀次性解决掉,因为在实际的项⽬中,代码冲突不只⼀两⾏那么简单, 有可能⼏⼗上百⾏,甚⾄更多,解决的过程中难免⼿误出错,导致错误的代码被合并到 master 上。

删除临时分支

软件开发中,总有⽆穷⽆尽的新的功能要不断添加进来。
添加⼀个新功能时,你肯定不希望因为⼀些实验性质的代码,把主分⽀搞乱了,所以,每添加⼀个新
功能,最好新建⼀个分⽀,我们可以将其称之为 feature 分⽀,在上⾯开发,完成后,合并,最
后,删除该 feature 分⽀。
可是,如果我们今天正在某个 feature 分⽀上开发了⼀半,被产品经理突然叫停,说是要停⽌新功
能的开发。虽然⽩⼲了,但是这个 feature 分⽀还是必须就地销毁,留着⽆⽤了。这时使⽤传统
git branch -d 命令删除分⽀的⽅法是不⾏的。演⽰如下:
git branch -D dev3

http://www.kler.cn/a/595727.html

相关文章:

  • electron框架(4.0)electron-builde和electron Forge的打包方式
  • 鸿蒙开发工程师简历项目撰写全攻略
  • 开源模型应用落地-LangGraph101-多智能体协同实践(六)
  • 蓝桥杯 第十天 2019国赛第4题 矩阵计数
  • 《Python实战进阶》No42: 多线程与多进程编程详解(下)
  • PowerBI纯小白如何驾驭DAX公式一键生成:copilot for fabric
  • Docker学习笔记(十)搭建Docker私有仓库
  • 密码协议与网络安全——引言
  • 零基础搭建智能法律知识库!腾讯云HAI实战教程
  • 基于Arm GNU Toolchain编译生成的.elf转hex/bin文件格式方法
  • 数学建模 绘图 图表 可视化(3)
  • 星越L_超速报警功能使用讲解
  • Java Web开发技术解析:从基础到实践的全栈指南
  • 手撸一个 deepseek 聊天历史对话、多轮对话(ollama + deepseek + langchain + flask)
  • 基于图像处理和机器学习实现的压差表数值读取
  • HarmonyOS鸿蒙开发 BuilderParam在父组件的Builder的点击事件报错:Error message:is not callable
  • 【时时三省】(C语言基础)习题2 scanf函数
  • Pytorch使用手册—自定义 C++ 和 CUDA 运算符(专题五十一)
  • 用AI优化云平台上的企业客服通话满意度和工单解决效率(上)
  • docker compose启动ollama+openweb ui,本地大模型十分钟搭建,速度主要取决于网速