Git

Git

原理

本地操作
在学习常用命令之前,你首先需要知道的 Git 的「三个分区」和对应的文件的「三种状态」:

在这里插入图片描述

工作区:就是你本地实际写代码的地方,无论你是用 vim 直接改也好,还是在 IDE 里写,都无所谓。

对应的文件状态是:modified,已修改,但还没保存到数据库中。 暂存区:就是临时存放的地方。

对应的文件状态是:staged,Git 已经对该文件做了标记,下次提交知道要包含它。

本地库:存放本地历史版本信息。

对应的文件状态是:committed,文件已经安全的保存在本地数据库中。

Git 的数据模型

什么是快照 (snapshot) 呢?
首先我们来学两个 Git 中的术语:

blob, 就是单个的文件;
tree, 就是一个文件夹。
快照则是被追踪的最顶层的树。

比如我的“公众号”文件夹的这么一个结构:

那么一个快照就是追踪的“公众号”这颗树。

在这里插入图片描述

本地库的数据模型
Git 记录了每个快照的 parent,也就是当前这个文件夹的上一个版本。

那么快照的迭代更新的过程就可以表示为一个有向无环图.

在这里插入图片描述

每个快照其实都对应了一次 commit,我们用代码来表示一下:

class commit {
  array<commit> parents
  String author
  String message
  Tree snapshot
}

这就是 Git 的数据模型。

blob, tree, snapshot 其实都一样,它们在 Git 中都是对象,都可以被引用或者被搜索,会基于它们的 SHA-1 hash 进行寻址。

git cat-file -t: 查看每个 SHA-1 的类型;
git cat-file -p: 查看每个对象的内容和简单的数据结构。
但是通过这个哈希值来搜索也太不方便了,毕竟这是一串 40 位的十六进制字符,就是第二部分 git log 里输出的那个编码。

因此,Git 还给了一个引用 reference。

比如,我们常见的 HEAD 就是一个特殊的引用。

本地库就是由 对象 和 引用 构成的,或者叫 Repositories.

在硬盘上,Git 只存储 对象 和 引用,所有的 Git 命令都对应提交一个快照。

常用命令

  • git init 初始化git仓库
  • git clone 克隆git仓库
  • git remote add origin ***.git 添加一个新的远程残酷
  • git push -u origin master 本地的 master 分支推送到 origin 主机的 master 分支。
  • 推送到远程仓库的dev分支:git push origin dev
  • git log 查看提交历史
  • git log --graph --pretty=oneline --abbrev-commit
  • git status 显示显示工作目录和暂存区的状态
  • git diff 比较文件在暂存区和工作区的差异
  • git add * 把所有的内容都加到缓存区
  • git commit -m "message" git提交代码,并假设提交信息
  • commit之后又改了一个小bug,但是又不想增加一个commit,可以用:git commit --amend --no-edit,直接将改动添加到上一次的commit中
  • git push 把本地的分支推到远程仓库
  • git pull 拉取最新的git代码
  • touch .gitignore 创建一个.gitignore文件

git标签管理

  • 首先切换到需要打标签的分支上,然后使用git tag v1.0就可以在当前commit打上v1.0的标签
  • git tag v1.0 commitID 对特定commit打标签
  • 打标签时加上message:git tag -a -m "message"
  • git tag 查看所有标签
  • git show [tagname] 查看标签详细信息
  • git push origin可以推送一个本地标签到远程仓库
  • git push origin --tags可以推送全部未推送过的本地标签
  • git tag -d可以删除一个本地标签
  • git push origin :refs/tags/可以删除一个远程标签(先从本地删除)

Git撤销与回滚

reset用于回滚,revert用于撤销。

Git进行回滚

使用git log命令,查看分支提交历史,确认需要回退的版本
使用git reset --hard commit_id命令,进行版本回退
使用git push origin命令,推送至远程分支

快捷命令:

回退上个版本:git reset --hard HEAD^ 

【注:HEAD是指向当前版本的指针,HEAD表示上个版本,HEAD^表示上上个版本】

如果修改到的文件比较少,我们可以不通过命令回滚的方式,手动删除之前的修改,再进行提交。

Git进行撤销

一些时候,为了验证Bug,我们可能会直接在测试服务器上打断点调试。如果忘记去掉调试内容,在执行git pull更新时,Git会提示你提交修改。

此时,你可能已经不记得修改什么了,这个时候,我们可以用git checkout – file命令,来清空工作区的修改。是的,git checkout命令不仅可以用来切换分支,还能撤销文件修改。

如果想要撤销提交到暂存区后的文件内容怎么办呢(即执行git add之后),我们可以使用git reset HEAD file命令撤销提交到暂存区的内容,再使用git checkout – file命令来撤销工作区的修改,需要分两步进行操作。

reset还是revert?

reset和revert都可以用来回滚代码。但他们是有区别的,准确来说,reset是用来"回退"版本,而revert是用来"还原"某次或者某几次提交。

比如我们有四次修改历史

42eae13 (HEAD -> master) 第四次修改
97ea0f9 第三次修改
e50b7c2 第二次修改
3a52650 第一次修改

如果发现,在第四次修改有错误,需要回滚到第三次修改,就可以用reset命令来回退。

执行 git reset --hard 97ea0f9,这个时候,git的提交历史变为:

97ea0f9 (HEAD -> master) 第三次修改
e50b7c2 第二次修改
3a52650 第一次修改

使用reset命令,Git会把要回退版本之后提交的修改都删除掉。要从第四次修改回退到第一次修改,那么会删除第二、三、四次的修改。【注:这里并不是真正的物理删除】

那如果发现第三次修改有错误,想要恢复第三次修改,却要保留第四次修改呢?

这个时候就可以用revert命令:

git revert -n 97ea0f9
git commit -m "恢复第三次修改"

Git提交历史会变成:

33b8b30 (HEAD -> master) Revert "恢复第三次修改"
42eae13 第四次修改
97ea0f9 第三次修改
e50b7c2 第二次修改
3a52650 第一次修改

实际上,Git把第三次修改从提交中剔除(还原)了,还保留了第四次修改,并且产生了新的commit_id。

Git 分支管理

  • 创建分支: git branch test

  • 切换分支: git checkout test

  • 创建并切换分支:git checkout -b test

  • 将test分支的更改合并到master分支:先在test分支上commit、push,再:git checkout master; git merge test

  • 如果合并时产生冲突:先手动解决冲突,再合并

  • 删除分支:git branch -d test

  • git stash
    
    • 如果当前分支还有任务没有做完,也不想提交,但此时需要切换或者创建其它分支,就可以使用stash将当前分支的所有修改(包括暂存区)先储藏起来;然后就可以切换到其它分支
    • 在其它分支工作完成之后,首先切换回原来的分支,然后使用git stash list命令查看
    • 可以使用git stash apply恢复之前储藏的工作现场,再使用git stash drop删除掉储藏的内容
    • 也可以直接用git stash pop恢复并删除内容
  • 如果在其它分支上做了一个修改(比如修复了一个bug,这次修改有一个commitID),想要将这次修改应用到当前分支上,可以使用:git cherry-pick commitID,可以复制一个特定的提交到当前分支

其他内容

git merge和rebase的区别

首先是git log区别

采用merge和rebase后,git log的区别,merge命令不会保留merge的分支的commit

img

处理冲突的方式

  • (一股脑)使用merge命令合并分支,解决完冲突,执行git add .git commit -m'fix conflict'。这个时候会产生一个commit。
  • (交互式)使用rebase命令合并分支,解决完冲突,执行git add .git rebase --continue,不会产生额外的commit。这样的好处是,‘干净’,分支上不会有无意义的解决分支的commit;坏处,如果合并的分支中存在多个commit,需要重复处理多次冲突。

git pullgit pull --rebase区别:git pull做了两个操作分别是‘获取’和合并。所以加了rebase就是以rebase的方式进行合并分支,默认为merge。

git mergegit merge --no-ff的区别

我自己尝试merge命令后,发现:merge时并没有产生一个commit。不是说merge时会产生一个merge commit吗?

注意:只有在冲突的时候,解决完冲突才会自动产生一个commit。

如果想在没有冲突的情况下也自动生成一个commit,记录此次合并就可以用:git merge --no-ff命令,下面用一张图来表示两者的区别:

img

如果不加 --no-ff 则被合并的分支之前的commit都会被抹去,只会保留一个解决冲突后的 merge commit。

Git和SVN

这个也比较常问这里简单总结一下。

SVN

SVN是Subversion的简称,是一个开放源代码的版本控制系统,支持大多数常见的操作系统。作为一个开源的版本控制系统,Subversion管理着随时间改变的数据。这些数据放置在一个中央资料档案库(repository)中。这个档案库很像一个普通的文件服务器,不过它会记住每一次文件的变动。这样你就可以把档案恢复到旧的版本,或是浏览文件的变动历史。Subversion是一个通用的系统,可用来管理任何类型的文件,其中包括了程序源码。

1619080707336.png

集中式代码管理的核心是服务器 (opens new window),所有开发者在开始新一天的工作之前必须从服务器获取代码,然后开发,最后解决冲突,提交。所有的版本信息都放在服务器上。如果脱离了服务器,开发者基本上可以说是无法工作的。下面举例说明:

1、从服务器下载项目组最新代码。

2、进入自己的分支,进行工作,每隔一个小时向服务器自己的分支提交一次代码(很多人都有这个习惯。因为有时候自己对代码改来改去,最后又想还原到前一个小时的版本,或者看看前一个小时自己修改了哪些代码,就需要这样做了)。

3、下班时间快到了,把自己的分支合并到服务器主分支上,一天的工作完成,并反映给服务器。

Git

Git是一款免费、开源的分布式版本控制系统,用于敏捷高效地处理任何或小或大的项目

Git是一个开源的分布式版本控制系统,用以有效、高速的处理从很小到非常大的项目版本管理。Git 是 Linus Torvalds 为了帮助管理 Linux 内核开发而开发的一个开放源码的版本控制软件。

分布式相比于集中式的最大区别在于开发者可以提交到本地,每个开发者通过克隆(git clone),在本地机器上拷贝一个完整的Git仓库.

1619080794290.png

主要区别

  • SVN属于集中化的版本控制系统,有个不太精确的比喻:SVN = 版本控制+ 备份服务器

    SVN使用起来有点像是档案仓库的感觉,支持并行读写文件,支持代码的版本化管理,功能包括取出、导入、更新、分支、改名、还原、合并等。

  • Git是一个分布式版本控制系统,操作命令包括:clone,pull,push,branch ,merge ,push,rebase,Git擅长的是程序代码的版本化管理。

  • GIT跟SVN一样有自己的集中式版本库或服务器。但,GIT更倾向于被使用于分布式模式,也就是每个开发人员从中心版本库/服务器上chect out代码后会在自己的机器上克隆一个自己的版本库。可以这样说,如果你被困在一个不能连接网络的地方时,就像在飞机上,地下室,电梯里等,你仍然能够提交文件,查看历史版本记录,创建项目分支,等。对一些人来说,这好像没多大用处,但当你突然遇到没有网络的环境时,这个将解决你的大麻烦。

  • GIT把内容按元数据方式存储,而SVN是按文件

    所有的资源控制系统都是把文件的元信息隐藏在一个类似.svn,.cvs等的文件夹里。如果你把.git目录的体积大小跟.svn比较,你会发现它们差距很大。因为.git目录是处于你的机器上的一个克隆版的版本库,它拥有中心版本库上所有的东西,例如标签,分支,版本记录等。

  • 分支在SVN中一点不特别,就是版本库中的另外的一个目录。如果你想知道是否合并了一个分支,你需要手工运行像这样的命令svn propget svn:mergeinfo,来确认代码是否被合并。然而,处理GIT的分支却是相当的简单和有趣。你可以从同一个工作目录下快速的在几个分支间切换。你很容易发现未被合并的分支,你能简单而快捷的合并这些文件。

  • GIT没有一个全局的版本号,而SVN有

    目前为止这是跟SVN相比GIT缺少的最大的一个特征。你也知道,SVN的版本号实际是任何一个相应时间的源代码快照。

  • GIT的内容完整性要优于SVN:

    GIT的内容存储使用的是SHA-1哈希算法。这能确保代码内容的完整性,确保在遇到磁盘故障和网络问题时降低对版本库的破坏。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值