Git 简介及异常场景处理

一、简介

介绍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 笑声.txtgit 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.mzph.cn/news/191109.shtml

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

相关文章

文艺复兴!ICO或再次兴起?香港Web3崛起前五部曲之一!

近日&#xff0c;香港证券及期货专业总会发布了《2024至2025年度财政预算案》&#xff0c;提出了一系列举措&#xff0c;其中最引人注目的莫过于政府考虑推出ICO发行机制&#xff0c;这一预算案被广泛视为香港在Web3崛起前的文艺复兴五部曲之一&#xff0c;引发了业界和投资者的…

关于 ls -s 输出文件大小的单位问题的讨论(stat 和ls -s的块不一样的,只是名称相同而已)

自己看书正好看到这里&#xff0c;正纳闷呢&#xff0c;上网查了下&#xff0c;发现不是我自己在为这个问题感到困惑。 有个大哥提出一个问题&#xff1a; 问题标题&#xff1a; ls -s的单位到底是什么&#xff1f; man ls -s, --size print the alloca…

MyBatis的创建,简单易懂的一篇blog

文章目录 一、MyBatis是什么二、操作流程三.配置resource总结 一、MyBatis是什么 MyBatis 是⼀款优秀的持久层框架&#xff0c;它⽀持⾃定义 SQL、存储过程以及⾼级映射。MyBatis 去除了⼏乎所有的 JDBC 代码以及设置参数和获取结果集的⼯作。MyBatis 可以通过简单的 XML 或注…

Azure Machine Learning - 使用 REST API 创建 Azure AI 搜索索引

本文介绍如何使用 Azure AI 搜索 REST AP和用于发送和接收请求的 REST 客户端以交互方式构建请求。 关注TechLead&#xff0c;分享AI全维度知识。作者拥有10年互联网服务架构、AI产品研发经验、团队管理经验&#xff0c;同济本复旦硕&#xff0c;复旦机器人智能实验室成员&…

【计算机网络】14、DHCP

文章目录 一、概述1.1 好处 二、概念2.1 分配 IP2.2 控制租赁时间2.3 DHCP 的其他网络功能2.4 IP地址范围和用户类别2.5 安全 三、DHCP 消息3.1 DHCP discover message3.2 DHCP offers a message 如果没有 DHCP&#xff0c;IT管理者必须手动选出可用的 ip&#xff0c;这太耗时了…

TA-Lib学习研究笔记——Price Transform (五)

TA-Lib学习研究笔记——Price Transform &#xff08;五&#xff09; 1.AVGPRICE Average Price 函数名&#xff1a;AVGPRICE 名称&#xff1a;平均价格函数 语法&#xff1a; real AVGPRICE(open, high, low, close) df[AVGPRICE] tlb.AVGPRICE(df[open],df[high],df[low…

电子印章管理系统:是什么、3个平台推荐

说到印章&#xff0c;相信看过近现代电视剧的人都见过&#xff0c;一般在订立合约时最常用到&#xff0c;双方在合约上加盖印鉴&#xff0c;即代表着合约的成立。 我小时候还见过我父亲的印章&#xff0c;只是随着时代的发展&#xff0c;印章因为不易携带&#xff0c;容易被盗…

二叉树OJ题目——C语言

LeetCode 104.二叉树的最大深度 1. 题目描述&#xff1a; 给定一个二叉树 root &#xff0c;返回其最大深度。 二叉树的 最大深度 是指从根节点到最远叶子节点的最长路径上的节点数。 示例 1&#xff1a; 输入&#xff1a;root [3,9,20,null,null,15,7] 输出&#xff1a;3示例…

CSS浅谈动画性能

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 目的一、举个栗子二、性能分析1.从图层分析2.性能分析 总结 目的 为了探究使用动画时&#xff0c;『transform』和『width、height、margin等』的差异 一、举个栗子…

【1】基于多设计模式下的同步异步日志系统

1. 项目介绍 本项⽬主要实现⼀个⽇志系统&#xff0c; 其主要⽀持以下功能: • ⽀持多级别⽇志消息 • ⽀持同步⽇志和异步⽇志 • ⽀持可靠写⼊⽇志到控制台、⽂件以及滚动⽂件中 • ⽀持多线程程序并发写⽇志 • ⽀持扩展不同的⽇志落地⽬标地 2. 开发环境 • CentOS 7 • vs…

Prism.js实现代码高亮并添加行号

先上效果: Prism.js Prism 是一款轻量、可扩展的代码语法高亮库&#xff0c;使用现代化的 Web 标准构建。 使用 Prismjs 可以快速为网站添加代码高亮功能&#xff0c;支持超过113中编程语言&#xff0c;还支持多种插件&#xff0c;是简洁、高效的代码高亮解决方案。 为什么选…

C++跨目录include问题

不同文件夹下使用预处理器指示符#include 使用举例 假设我们有如下一个工程&#xff0c;其中包含了几个源代码和头文件&#xff0c;其中main.cpp是主源代码文件&#xff0c;里面含有main函数&#xff1a; 在foldder main中包含&#xff1a;func4.hpp&#xff0c;func4.cpp&am…

1.0 十大经典排序算法

分类 算法 本系列算法整理自&#xff1a;https://github.com/hustcc/JS-Sorting-Algorithm 同时也参考了维基百科做了一些补充。 排序算法是《数据结构与算法》中最基本的算法之一。 排序算法可以分为内部排序和外部排序&#xff0c;内部排序是数据记录在内存中进行排序&#…

物流单管理系统软件物流单打印,物流单打印模板,佳易王物流快运单管理软件下载

物流单管理系统软件物流单打印&#xff0c;物流单打印模板&#xff0c;佳易王物流快运单管理软件下载 软件试用版下载或技术支持可以点击最下方官网卡片 上图&#xff1a;在物流开单时&#xff0c;可以先输入电话&#xff0c;如果之前存在该托运人信息&#xff0c;则可以一键…

Motion 5 for Mac,释放创意,打造精彩视频特效!

Motion 5 for Mac是一款强大的视频后期特效处理软件&#xff0c;为Mac用户提供了无限的创意可能性。无论你是专业的影视制作人&#xff0c;还是想为个人视频添加独特特效的爱好者&#xff0c;Motion 5都能满足你的需求&#xff0c;让你的视频脱颖而出。 Motion 5提供了丰富多样…

【滑动窗口】将X减到0的最小操作数

将X减到0的最小操作数 1658. 将 x 减到 0 的最小操作数 - 力扣&#xff08;LeetCode&#xff09; 文章目录 将X减到0的最小操作数题目描述算法原理代码编写Java代码编写C代码编写 题目描述 给你一个整数数组 nums 和一个整数 x 。每一次操作时&#xff0c;你应当移除数组 num…

【HarmonyOS开发】ArkTs编译为SO包的流程记录

1、创建一个Static Library的静态模块 2、编写我们的SO控件 2.1 编译配置 {"apiType": "stageMode","buildOption": {"artifactType": "obfuscation"},"targets": [{"name": "default",&qu…

Linux:查看端口占用的进程

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

dart语言多线程遇到的问题:Isolate.spawnUri(),在真机调试中无法生成隔离

报错原因 [ERROR:flutter/runtime/dart_vm_initializer.cc(41)] Unhandled Exception: IsolateSpawnException: Unable to spawn isolate: Unsupported isolate URI: 未处理的异常&#xff1a;IsolateSpawnException&#xff1a;无法生成隔离&#xff1a;不支持隔离 URI&…

递归实例化导致的栈溢出问题【简直蠢得出奇】

问题描述 今天在练习数据库增删改查&#xff0c;体验三层架构思想时&#xff0c;随便写了点DAO层代码&#xff0c;但服务器运行时竟然爆出了栈溢出的问题&#xff0c;说实话&#xff0c;空指针问题我还能放着耐心去代码里找找问题&#xff0c;但这个栈溢出&#xff0c;我之前就…