Ⅰ-Git操作
一、初始化
该处是用来提交时当作签名使用的
?git config --global user.name "我的用户名"
?git config --global user.email "我的邮箱"
?#删除配置信息
?git config --global --unset user.name
?git config --global --unset user.email
二、Git工作流程与区域
1、区域
-
工作区
平时写代码的文件目录
-
暂存区
git add 后提交暂存的地方
-
版本库
git commit 后给你生成版本的地方,注意push是提交到远程仓库而不是版本库,请勿混淆
2、工作流程
每个项目都有一个Git目录(.git)他是Git用来保存元数据和对象数据库的地方.该目录非常重要,每次克隆镜像仓库的时候,实际拷贝的就是这个目录里的数据
①、在工作目录中修改某些文件
从项目中取出某个版本的所有文件和目录,用以开始后续工作的叫做工作目录,这些文件实际上都是从Git目录中的压缩对象数据库中提取出来的,接下去就可以在工作目录中对这些文件进行编辑
②、保存到暂存区域,对暂存区做快照
暂存区域只不过是个简单的文件,一般都放在Git目录中,有时候人们会把这个区域的文件叫做索引文件,不过标准说法还是叫暂存区域
③、提交更新
将保存区在暂存区域的文件快照永久转储到本地数据库(Git目录)中
我们可以从文件所处位置来判断状态:如果是Git目录中保存着的特定版本文件,就属于提交版本;如果做了修改并已放入暂存区域,就属于已暂存状态;如果自上次去除后,做了修改但还没有放到暂存区域,就是已修改状态
三、对象详解(底层命令)
1、git对象
-
key:val 组成的键值对(key是val相应的hash)
键值对在git内部是blob类型(git特有)
-
存储数据文件内容,也称为数据对象
① 直接写入git对象方法与读取(存入".git/objects")
?#将打印内容写入对象(git数据库)并且返回其相应哈希值
?echo "写入的对象内容" | git hash-object -w --stdin
?#读取内容并不能直接cat读取,因为git存入时已经加密,需要如下代码 -p:内容 -t:类型
?git cat-file -p 存入对象的哈希值(此值可以由上一步得到)
?#将文件写入git对象,即我们常见的版本控制中出现的
?git hash-object -w ./test.txt
?#查看Git存储的数据 返回其文件夹内的所有哈希文件
?find .git/objects -type f
2、树对象
树对象是存储键值 作用为控制版本,如我们的版本前回退 就是在操作这个对象的(指向改变)
作用就是生成快照
这个也是git的必杀特性,因为他的切换分支与版本都很快 只是指针切换
构建树对象
我们可以通过 update-index , write-tree , read-tree 等命令来构建树对象并且塞到暂存区
① 利用 update-index 命令 创建暂存区
利用 update-index 命令 为test.txt文件的首个版本创建一个暂存区,并通过write-tree 命令生成树对象
?#1生成一个树对象
?git update-index --add --cacheinfo 100664(文件状态码:普通文件) 哈希值 对应文件名
?#生成快照(树对象)
?git write-tree
?#2 将第一个树对象加入第二个树对象,使其成为新的树对象
?git read-tree -prefix=bak 哈希值(树对象的) ?
?git write-tree
② 查看暂存区当前样子
git ls-files -s
3、提交对象
-
通过上述两个对象操作后,你会发现你已经生成了不同项目的快照,但是问题是:如果想重用这些快照,你必须记住所有三个 SHA-1(快照)哈希值 .但是,你也完全不知道是谁保存了这些快照,在什么时刻保存的,以及为什么保存这些快照.而以上这些,正是提交对象(commit object)能为你保存的基本信息 -
我们可以通过调用commit-tree命令创建一个提交对象,为此需要指定一个树对象的SHA-1值,为此需要指定一个树对象的SHA-1值 , 以及该提交的父提交对象(如果有的话,第一次将暂存区做快照就没有父对象) -
真正的一个版本其实就是提交对象
① 创建提交对象
echo "first commit" |git commit-tree 树对象的哈希值
②指定一个树对象的SHA-1值 , 以及该提交的父提交对象
echo "second commit" | git commit-tree 提交的树对象哈希值 -p 父亲树对象哈希值
四、高层命令
1、git add .
-
会将工作目录的修改,保存成git对象 先到版本库,再到暂存区 ,而不是直接到暂存区 -
在工作目录修改几个文件,就会生成几个git对象(一个文件对应一个git文件) -
同一个文件,每次修改再add的时候都会生成一个新的git对象,是增量 而不是覆盖 -
所以说git是绝对安全的,就算我只存到暂存区没有提交 git也会给我保存 -
只有后面提交的时候,才会根据暂存区内容给我生成树对象并存入版本区,然后加上我们的提交信息,才生成提交对象存入版本库
?#相当于以下两个命令集合
?git hash-object -w 文件名(修改了多少个工作目录中的文件,就要被执行几次)
?git update-index ...
2、git commit -m "注释内容"
将暂存区提交到版本库
?git write-tree
?git commit-tree
跳过暂存区存入(之前add过的,直接提交)
?git commit -a -m ""
3、git init
初始化仓库 初始化后,在当前目录下出现一个名为.git的文件夹
4、git status
查看文件的状态
5、git diff
-
当前做的那些更新没有暂存? 命令:git diff (不加参数直接输入git diff) -
有哪些更新已经暂存起来准备好了下次提交 命令:git diff --cached 或者git diff --staged(1.6.1以上版本)
6、git log
-
git log (不带参数) 空格键 往下翻页 b 向上翻页 q 退出日志查阅 -
git log --oneline 将日志信息拍成一行显示 -
git reflog 所有的日志信息 -
git log --oneline --decorate --graph --all 查看所有的分支信息命令
7、git rm
删除工作目录对应的文件,再将修改添加到暂存区(如同删除后给你用了 git add 文件名 )
#删除命令
?git rm 文件名
?#直接提交修改,因为rm命令帮你提交到暂存区了
?git commit -m "xxx"
8、git mv
将工作目录中的文件进行重命名,再将修改添加到暂存区
?git mv 原文件名 新文件名
五、配别名
Git并不会在你输入部分命令时自动推断出你想要的命令,如果不想每次都输入完整的Git命令,可以通过git config 文件来轻松为每一个命令设置一个别名
此处运行后将会写入你的配置文件,可以进入配置文件直接删除
?
git config --global alias.自定义命令 " `git` 命令后面的指令 "
?#如配置查看分支信息 "git log --oneline --decorate --graph --all"
?git config --global alias.logbranch "log --oneline --decorate --graph --all"
?#配置切换分支
?git config --global alias.co checkout
?#使用方式
?git logbranch
六、分支
-
前言: 几乎所有的版本控制系统都以某种形式支持分支.使用分支意味着你可以把你的工作从开发主线上分离开来,以免影响开发主线.在很多版本控制系统中,这是略微低效的过程--常常需要完全创建一个源代码目录的副本,对于大项目来说,这会耗费很多时间,而Git的分支模型极其的高校轻量,是Git的必杀特性,也正因为这一特性,是的Git从众多版本控制系统中脱颖而出 -
分支的本质: Git的分支,其实本质上是提交对象 ,,所有的分支都有机会被HEAD引用(HEAD一个时刻只会指向一个分支 ),当我们有新的提交的时候 HEAD会携带当前持有的分支向前移动 Git的默认分支名字是master,在多次提交后,你其实已经有一个指向最后那个提交对象的master分支.他会在每次的提交操作中自动向前 注意:Git的"master"分支并不是一个特殊分支.她就跟其他分支完全没有区别.之所以几乎每个仓库都有master分支,是因为git init 命令默认创建它,并且大多数人懒得区改动它 -
分支的原理:
-
.git/refs 目录中保存了分支及其对应的提交对象 -
当运行类似于git branch (branchname) 这样的命令时,Git会取得当前所在分支最新提交对应的SHA-1值,并将其加入你想要创建的任何新分支中 -
当你执行git branch (branchname) 时,Git如何知道最新提交的SHA-1值呢?答案是HEAD文件 HEAD文件 是一个符号引用(stmbolic reference),指向目前所在的分支.所谓符号医用,意味着它并不像普通引用那样包含一个SHA-1值.它时一个指向其他引用的指针
1、git branch
-
git branch(不加参数) 作用:显示所有分支 信息 -
git branch 分支名 作用:创建分支 -
git branch -v 作用:查看每一个分支最后一次提交 -
git branch -d(-D强制删除) 分支名 作用:删除分支 ,小d需要你这个分支是干净的才能删除(如已合并) -
git branch --merged 作用:查看那些分支已经合并到当前分支 在这个列表中的分支名字前没有*号的分支通常可以使用git branch -d 删除掉 -
git branch --no-merged 作用:查看所有包含未合并工作的分支 尝试使用git branch -d 命令删除在这个列表中的分支时会失败,如果真的想要删除分支并丢掉哪些工作,可以使用-D 选项爱强制删除它 -
git log --oneline --decorate --graph --all 作用:查看所有的分支信息命令 -
git branch 分支名 commitHash 作用:新建一个分支,并且使分支指向对应的提交对象(版本穿梭可以替代撤销与重置 )
2、git checkout 分支名
作用:切换分支 checkout还有其他作用,后面会提到
它会动三个地方:HEAD(指针) 暂存区 工作目录
-
注意 :分支切换会改变你工作目录中的文件,所以在切换分支时,一定要注意你的工作目录里的文件会被改变,如果时切换到一个比较旧的分支,你的工作目录会回复到该分支最后一次提交的样子,如果Git不能干净利落的完成这个任务,它将禁止切换分支 -
坑 :在切换分支时, 如果当前分支上由未暂存的修改(第一次 ) 或者 有未提交的暂存(第一次 ) 分支可以切换成功,但是这种操作可能会污染其他分支 ps:第一次 --当前分支如果已经提交过一次,将不让你切换,但是第一次没有提交过,git会帮你保存文件 但是它并不知道新增修改是属于哪个分支,所以会带回当前分支 -
最佳操作方式:每次在切换分支前,需要提交一下当前分支(先使用status查看状态)
3、git checkout -b "新的分支名"
创建并进入该分支,类似于上面两个命令集合
4、模拟实战流程
-
需要解决主程序的的一个小BUG,所以使用git checkout -b "iss_bug" 新建分支并在这个分支进行bug调修 -
当你再iss_bug 分支上开发到一半,这时,在主程序发现了一个紧急BUG需要你放下这个重要性为次要的bug进行修改.你老板都给你打了紧急电话,所以你需要先将写到一半的bug进行保存提交(commit 提交或者储存 到暂存区,并不是提交合并到主分支,也不是push提交),确定status是干净的时候,切换回主分支,再用第一步的方法创建hot_bug 分支(这时候hit_bug 的版本是master没有进行iss_bug 调修的版本),进行修复 -
当你将紧急bug修复后,进行提交,确定status干净后切换回master分支,进行合并:代码如下
?git checkout master
?git merge hit_bug
-
修改完后再查看status(这是个好习惯,防止偶尔记忆混淆造成不必要的麻烦),再切换至普通bug分支iss_bug 进行修改,成功后切换回去合并 -
如果出现冲突,去出现冲突的文件手动修改(决定保留那部分代码),再进行git add 表示冲突解决,在进行提交
5、合并分支
命令: git merge branchname (分支名)
注意:合并分支时要先切换到主要分支 (即下面的被合并分支),在这个分支上进行合并新分支,使得这个分支进行版本更新
-
快进合并-->不会产生冲突 指被合并分支并没有进行修改,停留在原地,只有新分支进行修改更新,更 新完成后进行合并,原版本相当于直接前进版本,称为快进合并 -
典型合并-->有可能产生冲突 指被合并分支在新分支进行开发时,本身也进行修改开发,可能会改动到同 一代码或者文件而产生重复修改 -
解决冲突:打开冲突的文件 进行修改 ,修改完成后进行:add标记修改完成 ,然后commit进行提交
git 在pull或者合并分支 的时候有时会遇到一个第一段是黄色,下面文字是青色(偏蓝色)。可以不管(直接下面3,4步),如果要输入解释的话就需要:
1.按键盘字母 i 进入insert模式
2.修改最上面那行黄色合并信息,可以不修改
3.按键盘左上角"Esc"
4.输入":wq",注意是冒号+wq,按回车键即可
|