Git 简介及异常场景处理

news2024/12/24 3:15:41

一、简介

介绍Git之前,还得先介绍下 版本控制系统(VCS), 和它的发展历史

纵观版本控制系统的发展历史,广义上讲,版本控制工具的历史可以分为三代:

第一代

第一代版本控制系统被称为本地版本控制系统。通过加锁将并发执行转换成顺序执行。 一次只能有一个人处理文件。具体流程如下:首先,应该把文件放在一个服务器上,方便使用者上传或下载文件;其次,任何人想对文件修改时,需要先把这个文件加锁,通过checkout指令,使得其他人无法修改;最后,当修改完成之后,需要释放锁,通过checkin指令,形成一个新的版本,存放到服务器端。

第一代版本控制系统主要有 RCS、SCCS(1972年发布)和 DSEE(被认为是 Atria ClearCase 的前身)。目前,有些项目还在使用!

悲观锁
每次获取数据的时候,都会担心数据被修改,所以每次获取数据的时候都会进行加锁,确保在自己使用的过程中数据不会被别人修改,使用完成后进行数据解锁。由于数据进行加锁,期间对该数据进行读写的其他线程都会进行等待。

第二代

第二代版本控制系统被称为集中式版本控制系统(Centralized Version Control Systems,CVCS),其对同步修改更加宽容,但有一个明显的限制,用户必须在允许提交之前将当前修订合并到他们的工作中。

由上图可看到,在集中式版本控制系统中,如果服务器嗝屁了,那么所有的开发者就只能干瞪眼了!因为,SVN 对于项目的管理是依赖于服务器中的中心仓库的!我们的更改必须要提交到服务器中的中心仓库。

第二代版本控制系统主要有 CVS、SourceSafe、Subversion、Team Foundation Server、SVK。

乐观锁
每次获取数据的时候,都不会担心数据被修改,所以每次获取数据的时候都不会进行加锁,但是在更新数据的时候需要判断该数据是否被别人修改过。如果数据被其他线程修改,则不进行数据更新,如果数据没有被其他线程修改,则进行数据更新。由于数据没有进行加锁,期间该数据可以被其他线程进行读写操作。
乐观锁一般会使用版本号机制或 CAS 算法实现。

第三代

第三代版本控制系统被称为分布式版本控制系统(Distributed Version Control Systems,DVCS),其允许合并和提交分开。在每个使用者电脑上就有一个完整的数据仓库,没有网络依然可以使用。

由上图可看到,分布式式版本控制系统也可以有个服务器端的仓库,用来同步各开发者的私有仓库!在分布式版本控制系统中,每个参与者的本地也会有一个完整的仓库。及时服务器端崩溃,我们仍然可以使用 Git(仅在本地仓库管理我们的代码),在网络具备时,再和服务器进行同步即可!

第三代版本控制系统主要有 Bazaar、Git、Mercurial、BitKeeper,、Monotone。目前,第三代版本控制系统已经大有一同江湖的趋势!

那么市面上常用的版本控制系统有哪些呢?

SVN 一个集中式版本控制系统(Centralized VCS)

SVN(Subversion 的缩写)是一个开放源代码的版本控制系统,相较于 RCS、CVS,它采用了分支管理系统。SVN 由 CollabNet 公司于 2000 年资助并发起开发,目的是创建一个更好用的版本控制系统以取代 CVS。

2000 年 2 月,CollabNet 联系了 Open Source Development with CVS(Coriolis, 1999)的作者 Karl Fogel,问他是否愿意为这个新项目工作。这时 Karl 已经在和他的朋友 Jim Blandy 讨论一个新的版本控制系统的设计。他不仅已经起好了名字 “Subversion”,而且有了 Subvesion 资料库的基本设计。

经过 14 个月的编码,在 2001 年 8 月 31 号,Subversion 可以“自我寄生”了。就是说,Subversion 开发人员停止使用 CVS 管理 Subversion 的源代码,开始使用 Subversion 代替。

2009 年 11 月,Subversion 被 Apache Incubator 项目所接收。2010 年 1 月,正式成为 Apache 软件基金会的一个顶级项目。

以下是几款常用的 SVN 客户端图形化软件:

  • TortoiseSVN:开源软件,在 Windows 上非常受到欢迎的一套客户端软件,它与资源管理器集成得相当不错,可以透过资源管理器在文件或目录上用鼠标右键的菜单完成 SVN 的操作。官方网站:Home · TortoiseSVN

  • SnailSVN:Mac OS X 平台下类似 TortoiseSVN 的图形化 SVN 客户端,可自动标记文件状态,并通过右键菜单提供各种常用 SVN 功能。 网站:SnailSVN

  • Ankhsvn:将 subversion 的操作集成进 Visual Studio 的 SVN 客户端软件。官方网站:http://ankhsvn.open.collab.net/

  • Subclipse:将 Subversion 的操作集成进 Eclipse 的 SVN 客户端软件。官方网站:http://subclipse.tigris.org/

  • SmartSVN:同时支持 Mac、Linux、Windows。是一款收费软件。

BitKeeper

BitKeeper 是一套 BitMover 公司开发的分布式版本控制软件,它曾是一款专有软件。BitKeeper 是最初的分布式源代码控制系统。BitKeeper 的许多概念取自 TeamWare(Larry McVoy 在 Sun 公司时开发的产品)。

BitMover 公司 CEO Larry McVoy 与 Linus 曾是好友, Larry 说服 Linus 在内核开发中使用 BitKeeper。而 BitKeeper 在免费使用的许可证中加入很多限制条件,惹恼了内核开发者,最终促使 Linus 开发出了毁灭 BitMove r的 Git。

2016 年 5 月 11 日,BitKeeper 宣布以 Apache 2.0 许可证开源。

Git 一个分布式版本控制系统(Distributed VCS)

在 Linux 开源的初期,Linux 开源项目的代码是 linus 本人通过 linux 命令 diff 和 patch 两条命令手动完成。随着 Linux 代码越来越壮大,靠 Linus 一个人来手动合并已经不现实。2002 年,Linus 选择了一个商业版本控制系统 BitKeeper 作为 Linux 内核的代码管理工具(BitKeeper 的开发商 BitMover 授权 linux 社区免费使用)。但是,免费使用是有很多的限制的,因此 linux 社区的大佬开始破解 BitKeeper。其中,samba 的作者 andrew 破解成功了。但是被 BitMover 公司发现,收回免费使用权。

迫不得已,Linus 选择了自己开发一个分布式版本控制工具以替代 BitKeeper。linus 闭关一个月,写出了 Git。在一个月后,Git 成功接管了 Linux 社区的版本控制工作,并且开始开源。维基百科中,有如下历史记录:

  • 2005 年 4 月 3 日,开始开发 Git。

  • 2005 年 4 月 6 日,项目发布。

  • 2005 年 4 月 7 日,Git 就可以作为自身的版本控制工具了。

  • 2005 年 4 月 18 日,发生第一个多分支合并。

  • 2005 年 4 月 29 日,Git 的性能就已经达到了 Linus 的预期。

  • 2005 年 6 月 16 日,Linux 核心 2.6.12 发布,那时 Git 已经在维护 Linux 核心的源代码了。

  • 在 2005 年 7 月 26 日,Linus 功成身退,将 Git 的维护交给另外一个 Git 的主要贡献者 Junio C Hamano。

在 Linus Torvalds 开发出 Git 分布式版本控制系统 11 年后的 2016 年,BitKeeper 宣布在 Apache 2.0 许可证下开源。

二、Git常用命令

  • git config --global user.name "你的名字" 让你全部的Git仓库绑定你的名字

  • git config --global user.email "你的邮箱" 让你全部的Git仓库绑定你的邮箱

  • git init 初始化你的仓库

  • git add . 把工作区的文件全部提交到暂存区

  • git add ./<file>/ 把工作区的<file>文件提交到暂存区

  • git commit -m "xxx" 把暂存区的所有文件提交到仓库区,暂存区空空荡荡

  • git remote add origin https://github.com/name/name_cangku.git 把本地仓库与远程仓库连接起来

  • git push -u origin master 把仓库区的主分支master提交到远程仓库里

  • git push -u origin <其他分支> 把其他分支提交到远程仓库

  • git status查看当前仓库的状态

  • git diff 查看文件修改的具体内容

  • git log 显示从最近到最远的提交历史

  • git clone + 仓库地址下载克隆文件

  • git reset --hard + 版本号 回溯版本,版本号在commit的时候与master跟随在一起

  • git reflog 显示命令历史

  • git checkout -- <file> 撤销命令,用版本库里的文件替换掉工作区的文件。我觉得就像是Git世界的ctrl + z

  • git rm 删除版本库的文件

  • git branch 查看当前所有分支

  • git branch <分支名字> 创建分支

  • git checkout <分支名字> 切换到分支

  • git merge <分支名字> 合并分支

  • git branch -d <分支名字> 删除分支,有可能会删除失败,因为Git会保护没有被合并的分支

  • git branch -D + <分支名字> 强行删除,丢弃没被合并的分支

  • git log --graph 查看分支合并图

  • git merge --no-ff <分支名字> 合并分支的时候禁用Fast forward模式,因为这个模式会丢失分支历史信息

  • git stash 当有其他任务插进来时,把当前工作现场“存储”起来,以后恢复后继续工作

  • git stash list 查看你刚刚“存放”起来的工作去哪里了

  • git stash apply 恢复却不删除stash内容

  • git stash drop 删除stash内容

  • git stash pop 恢复的同时把stash内容也删了

  • git remote 查看远程库的信息,会显示origin,远程仓库默认名称为origin

  • git remote -v 显示更详细的信息

  • git pull 把最新的提交从远程仓库中抓取下来,在本地合并,和git push相反

  • git rebase 把分叉的提交历史“整理”成一条直线,看上去更直观

  • git tag 查看所有标签,可以知道历史版本的tag

  • git tag <name> 打标签,默认为HEAD。比如git tag v1.0

  • git tag <tagName> <版本号> 把版本号打上标签,版本号就是commit时,跟在旁边的一串字母数字

  • git show <tagName> 查看标签信息

  • git tag -a <tagName> -m "<说明>" 创建带说明的标签。 -a指定标签名,-m指定说明文字

  • git tag -d <tagName> 删除标签

  • git push origin <tagname> 推送某个标签到远程

  • git push origin --tags 一次性推送全部尚未推送到远程的本地标签

  • git push origin :refs/tags/<tagname> 删除远程标签<tagname>

  • git config --global color.ui true 让Git显示颜色,会让命令输出看起来更醒目

  • git add -f <file> 强制提交已忽略的的文件

  • git check-ignore -v <file> 检查为什么Git会忽略该文件

git commit提交规范

type: commit 的类型
feat: 新特性
fix: 修改问题
refactor: 代码重构
docs: 文档修改
style: 代码格式修改, 注意不是 css 修改
test: 测试用例修改
chore: 其他修改, 比如构建流程, 依赖管理.
scope: commit 影响的范围, 比如: route, component, utils, build...
subject: commit 的概述, 建议符合 50/72 formatting
body: commit 具体修改内容, 可以分为多行, 建议符合 50/72 formatting
footer: 一些备注, 通常是 BREAKING CHANGE 或修复的 bug 的链接.

三、Git异常场景处理

场景1:git 文件名大小写的坑

当你创建了一个 Components.jsx 的文件,后来给它改了个名,components.jsx,  会发现一个神奇的现象:git 对这个改动没有跟踪记录;

git 默认情况下是不区分大小写的,需要单独设置

git config core.ignorecase false

场景2:刚刚提交的代码,发现写错了怎么办?

刚提交了一个代码,发现有几个字写错了:

怎么修复?

当场再写一个修复这几个错别字的 commit?可以是可以,不过还有一个更加优雅和简单的解决方法:commit -—amend。

"amend" 是「修正」的意思。在提交时,如果加上 --amend 参数,Git 不会在当前 commit 上增加 commit,而是会把当前 commit 里的内容和暂存区(stageing area)里的内容合并起来后创建一个新的 commit,用这个新的 commit 把当前 commit 替换掉。所以 commit --amend 做的事就是它的字面意思:对最新一条 commit 进行修正。

具体地,对于上面这个错误,你就可以把文件中的错别字修改好之后,输入:

git add 笑声.txt

git commit --amend -m 'XXX'

Git 会把你带到提交信息编辑界面。可以看到,提交信息默认是当前提交的提交信息。你可以修改或者保留它,然后保存退出。然后,你的最新 commit 就被更新了。

场景3:想直接丢弃刚写的提交?

有的时候,刚写完的 commit 写得实在太烂,连自己的都看不下去,与其修改它还不如丢掉重写。这种情况,就可以用 reset 来丢弃最新的提交。

git reset --hard HEAD^

// --hard 标志告诉 git 要完全重置工作目录和暂存区,去匹配最后一次提交。在这个过程中,所有未提交的改动和新添加的东西都会被删除。
// HEAD 是一个指向你最后一次提交的指针

// 如果你只是想回滚到之前的一个特定提交

git reset --hard commit_id

// --soft 参数:仅仅在本地库移动 HEAD 指针。
// --mixed 参数:在本地库移动 HEAD 指针、重置暂存区。
// --hard 参数:在本地库移动 HEAD 指针、 重置暂存区、重置工作区。

场景4:需求代码一顿敲,自信push,结果发现推错了分支?

方法1:reset
# 取消最新的提交,然后保留现场原状
git reset HEAD~ --soft
git stash

# 切换到正确的分支
git checkout feature2
git stash pop
git add .    # 或添加特定文件
git commit -m "commit message"
方法2:cherry-pick(摘樱桃)
git log //在dev分支找到要合并的commit记录
git checkout feature2
# 把主分支上的最新提交摘过来
git cherry-pick commitId //需合并到feature2的commitId

# 再删掉主分支上的最新提交
git checkout dev
git reset HEAD~ --hard

场景5:一个需求分支代码commit了太多次,合并到master前想简化提交记录?

新建分支就改了一行代码,推送前看了下提交记录,

发现修改了n次,想要精简提交记录,可以使用

git rebase -i <branchName> 
// -i 是希望调整commit message
// branchName目的分支

pick完当前分支相对目标分值的commit 之后,会提示代码冲突,解决完需要

git rebase --continue  // 继续变基操作

git push -f //强推

场景6:代码已经 push 上去了才发现写错?

(1)出错的内容在你自己的 branch

需要修改的commit 未 push 到远端,可以直接对需要修改的commit进行操作,然后push;

若修改的commit 已经 push 到远端,由于你在本地对已有的 commit 做了修改,这时你再 push 就会失败,因为中央仓库包含本地没有的 commits。但这个和前面讲过的情况不同,这次的冲突不是因为同事 push 了新的提交,而是因为你刻意修改了一些内容,这个冲突是你预料到的,你本来就希望用本地的内容覆盖掉中央仓库的内容。那么这时就不要乖乖听话,按照提示去先 pull 一下再 push 了,而是要选择「强行」push:

git push origin branch1 -f

-f 是 --force 的缩写,意为「忽略冲突,强制 push」。

(2)出错的内容已经合并到 master
同事的工作都在 master 上,你永远不知道你的一次强制 push 会不会洗掉同事刚发上去的新提交。所以除非你是人员数量和行为都完全可控的超小团队,可以和同事做到无死角的完美沟通,不然一定别在 master 上强制 push。

在这种时候,你只能退一步,选用另一种策略:增加一个新的提交,把之前提交的内容抹掉。

有两种回退方案可供选择 git revert 和 git reset

git revert commit_id
// git revert是用一次新的commit来回滚之前的commit,此次提交之前的commit都会被保留;
// git revert --abort:冲突发生后,当前的操作会回到指令执行之前的样子,回到原始的状态,相当于什么事没有发生
// git revert --quit:冲突发生后,从反做操作行为中退出,该指令会保留文件冲突
// git revert --skip:冲突发生后,跳过此次反做操作
// git revert --continue:冲突发生后,解决冲突并add后,执行该命令,会继续之前的操作流程

git reset [--soft | --mixed | --hard] [HEAD]
// git reset是回到某次提交,提交及之前的commit都会被保留,但是此commit id之后的修改都会被删除;

注意:在回滚这一操作上看,效果差不多。但是在日后继续merge以前的老版本时有区别。因为git revert是用一次逆向的commit“中和”之前的提交,因此日后合并老的branch时,导致这部分改变不会再次出现;但是git reset是直接把某些commit在某个branch上删除,因而和老的branch再次merge时,这些被回滚的commit还会被引入。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

组合(回溯+剪枝、图解)

77. 组合 - 力扣&#xff08;LeetCode&#xff09; 题目描述 给定两个整数 n 和 k&#xff0c;返回范围 [1, n] 中所有可能的 k 个数的组合。 你可以按 任何顺序 返回答案。 样例输入 示例 1&#xff1a; 输入&#xff1a;n 4, k 2 输出&#xff1a; [[2,4],[3,4],[2,3],…

LORA概述: 大语言模型的低阶适应

LORA概述: 大语言模型的低阶适应 LORA: 大语言模型的低阶适应前言摘要论文十问实验RoBERTaDeBERTaGPT-2GPT-3 结论代码调用 LORA: 大语言模型的低阶适应 前言 LoRA的核心思想在于优化预训练语言模型的微调过程&#xff0c;通过有效地处理权重矩阵的变化&#xff08;即梯度更新…

Docker中部署并启动RabbitMQ

目的 由于最近频繁更换云服务器&#xff0c;导致环境啥的都需要重新配置&#xff0c;关于RabbitMQ&#xff0c;我在看其他博主的文章时&#xff0c;总是不能第一时间找到想要的配置方法&#xff08;也不是没有&#xff0c;只是花的时间太久&#xff09;&#xff0c;于是打算自己…

接口响应时长几十秒问题排查以及解决

目录 背景 解决方案 总结 背景 线上系统运行几年后&#xff0c;被项目上提bug&#xff0c;有些接口响应很慢&#xff0c;加载页面要几十秒 解决方案 1、步骤一&#xff0c;加索引 性能优化成本高&#xff0c;需要开发周期&#xff0c;临时方案先分析慢sql&#xff0c;通过增…

C语言——深入理解指针(4)

目录 1.回调函数 2. qsort 函数的使用 2.1 排序整型数据 2.2 排序结构体数据 3. qsort 函数的模拟实现 1.回调函数 回调函数就是通过一个函数指针调用的函数。 你把函数的地址作为参数传递给另一个函数&#xff0c;当这个指针被用来调用其所指向的函数时&#xff0c;被调…

Linux:查看端口占用的进程

命令 netstat -tunlp可以从图中看到&#xff0c;端口被那个进程占用&#xff0c;对应进程的pid是多少。

软件测试工程师如何面试?

首先作为HR的角度&#xff1a; 一般我们面试的时候都会问应聘者一些问题&#xff0c;但是问什么&#xff1f;怎么问&#xff1f;每个HR都会有不同的做法。 有的HR问的比较广泛&#xff0c;有的HR比较注重专业度&#xff0c;还有的HR喜欢问一些开放性的问题&#xff0c;没有标…

版本控制系统Git学习笔记-Git分支操作

文章目录 概述一、Git分支简介1.1 基本概念1.2 创建分支1.3 分支切换1.4 删除分支 二、新建和合并分支2.1 工作流程示意图2.2 新建分支2.3 合并分支2.4 分支示例2.4.1 当前除了主分支&#xff0c;再次创建了两个分支2.4.2 先合并test1分支2.4.3 合并testbranch分支 2.5 解决合并…

智慧工地一体化解决方案(里程碑管理)源码

智慧工地为管理人员提供及时、高效、优质的远程管理服务&#xff0c;提升安全管理水平&#xff0c;确保施工安全提高施工质量。实现对人、机、料、法、环的全方位实时监控&#xff0c;变被动“监督”为主动“监控”。 一、建设背景 施工现场有数量多、分布广&#xff0c;总部统…

C++11 左值 右值

什么是左值&#xff1f;什么是左值引用&#xff1f; 左值是一个表示数据的表达式(如变量名或解引用的指针)&#xff0c;我们可以获取它的地址可以对它赋 值&#xff0c;左值可以出现赋值符号的左边&#xff0c;右值不能出现在赋值符号左边。定义时const修饰符后的左 值&am…

亚马逊云科技re:Invent大会,助力安全构建规模化生成式AI应用

2023亚马逊云科技re:Invent全球大会进入第三天&#xff0c;亚马逊云科技数据和人工智能副总裁Swami Sivasubramanian博士在周三的主题演讲中&#xff0c;为大家带来了关于亚马逊云科技生成式AI的最新能力、面向生成式AI时代的数据战略以及借助生成式AI应用提高生产效率的精彩分…

变量和引用

变量和引用 2.1.深入认识变量 2.1.1.什么是变量 变量是在程序中保存用户数据的一段内存存储空间&#xff0c;变量名是内存空间的首地址 变量三要素&#xff1a;名称、类型、值 2.1.2.变量的名称 组成: 字母、数字、下划线组成&#xff0c;不能以数字开头 变量名称的长…

Android 获取应用签名

Android 获取应用签名 本文主要讲下在android中如何获取应用签名. 也方便平时用来区分一个应用是不是原包应用. 1: 通过PackageManager获取签名信息 首先,通过packageManager获取到指定应用的PackageInfo. 这里需要传入的flag是PackageManager.GET_SIGNATURES /*** {link P…

scrapyd及gerapy的使用及docker-compse部署

一、scrapyd的介绍 scrapyd是一个用于部署和运行scrapy爬虫的程序&#xff0c;它允许你通过JSON API(也即是web api)来部署爬虫项目和控制爬虫运行&#xff0c;scrapyd是一个守护进程&#xff0c;监听爬虫的运行和请求&#xff0c;然后启动进程来执行它们 scrapyd的安装 scr…

蓝桥第一期模拟总结

文章目录 1.动态的 Tab 栏2.地球漫游3.迷惑的this4.燃烧卡路里5.魔法失灵了6.年龄统计 所有题目链接 1.动态的 Tab 栏 本题要实现一个tab栏固定效果&#xff0c;看见题目就想到css中的 position: fixed; 尝试了很久都没能实现效果&#xff0c;后来又想到了粘性定位 position: …

网络编程之套接字

端口 && IP 在学习套接字编程之前&#xff0c;我们必须了解一下前缀知识。首先是IP和端口的作用。 在这之前&#xff0c;我们要明白一件事。那就是把数据从一台主机发送到另一台主机&#xff0c;是目的吗&#xff1f;&#xff1f;&#xff1f;当然不是&#xff01;&a…

TOP-K问题和向上调整算法和向下调整算法的时间复杂度问题的分析

TOP-K问题 TOP-K问题&#xff1a;即求数据结合中前K个最大的元素或者最小的元素&#xff0c;一般情况下数据量都比较大 比如&#xff1a;专业前10名、世界500强、富豪榜、游戏中前100的活跃玩家等 对于Top-K问题&#xff0c;能想到的最简单直接的方式就是排序&#xff0c;但是…

聊聊测试for Jeffky

什么是测试 测试是一个系统性的过程&#xff0c;它涉及到在已开发的软件中执行程序、应用工具和技术来评估其质量、功能和性能。这个过程的目的是发现并纠正程序中的错误&#xff0c;提高软件的可靠性和稳定性&#xff0c;以满足用户的需求。 测试的分类 什么是自动化测试 自动…

Android Termux 安装Kali Linux 或 kali Nethunter史诗级详细教程

Android Termux 安装Kali Linux 或 kali Nethunter史诗级详细教程 一、Termux配置1、下载安装2、配置存储和换源3、基本工具安装 二、Kali Linux安装1、下载安装脚本2、更换apt源3、图形化安装 三、Kali Nethunter安装1、下载安装脚本2、更换apt源3、图形化连接 四、报错汇总1、…

五、关闭三台虚拟机的防火墙和Selinux

目录 1、关闭每台虚拟机的防火墙 2、关闭每台虚拟机的Selinux 2.1 什么是SELinux