在【尚硅谷】Git与GitHub基础全套完整版教程-笔记1中有关于Git的简介,以及添加add、提交commit、撤回reset等命令。
下面先回忆一下上一篇文章的命令,以good.txt为例进行实际操作。
目录
0 回忆上篇文章的内容
4.3.5 前进后退 (三方式)
git在管理历史版本时其实有一个指针,指针的名字叫“HEAD”,方便移动。前进和后退的本质是指针移动。
第一种:基于索引值操作[推荐使用这个方式]
现在指针指向离我们最近的记录。注意:git里面的代码选中就是复制,直接粘贴就好。代码格式:
git reset --hard [局部索引值] //索引值取前面几位数就行
实际操作代码:
git reflog //查看所有的历史记录,包括指针情况
cat good.txt //查看现在good.txt文件的内容
git reset --hard a6ace91 //“穿越”
git reset --hard 42e7e84 //再往后“穿越”
cat good.txt //查看现在good.txt文件的内容
git reset --hard 9a9ebe0 //往前走“穿越”
cat good.txt //查看现在good.txt文件的内容
第二种:使用^(异或)符号,只能后退。
代码格式:
git reset --hard HEAD^^
实际操作代码:
$git log --oneline //查看当前版本的历史记录
$git reset --hard HEAD^ //后退一步
$tail -n 3 good.txt //节省版面,只显示good.txt文件的最后3行
$git log --oneline //查看当前版本的历史记录
$git reset --hard HEAD^^^ //后退三步
$tail -n 3 good.txt //查看当前版本,只显示最后3行
第三种:使用~(波浪线)符号,只能后退
git reset --hard HEAD~n //注:表示后退 n 步
实际操作代码:
$git log --oneline //查看当前版本的历史记录
$git reset --hard HEAD^^^ //后退三步
//同样后退3步
$git reset --hard HEAD~3 //表示后退3步
总结:后两个方法都需要去历史记录里数一下。git reflog可以查看所有的历史记录。
4.3.6 reset 命令的三个参数对比
(查看命令帮助文档: git help reset)
git help reset //文档不是在线的,提前下载好
--soft 参数
Does not touch the index file or the working tree at all.(不会碰暂存区和工作区)
仅仅在本地库移动 HEAD 指针 (查看状态时绿色提示:本地库和暂存区不同步)
--mixed 参数
在本地库移动 HEAD 指针
重置暂存区
(查看状态时红色提示:本地库和暂存区后退,感觉是工作区前进了)
--hard 参数
在本地库移动 HEAD 指针,三个区域一起移动:重置暂存区和工作区。
4.3.7 删除文件并找回
实际操作代码:
$vim aaa.txt //新建一个aaa.txt文件
$git add aaa.txt
$git commit -m "new aaa.txt" aaa.txt
$git status
//On branch master.
//nothing to commit,working tree clean
$rm aaa.txt
$ll //查看当前目录下的文件
$git status
//提示:git add或者git checkout
//deleted :aaa.txt
$git add aaa.txt
$git status
//提示:git reset
//deleted: aaa.txt
$git commit -m "delete aaa.txt" aaa.txt
$git status
//On branch master.
//nothing to commit,working tree clean
//git在操作的时候只会增加版本,不会去删除历史版本。
$git reflog //查看历史记录,定位当前版本
$git reset --hard 567f4e1 //“穿越”到删除之前的版本
$ll //查看当前目录下的文件,之前删除的aaa.txt找回来了
$vim apple.txt //新建一个apple.txt文件
$ll //有两个文件,apple.txt和good.txt
$git add apple.txt
$git commit -m "new apple.txt" apple.txt
$git reflog //查看历史记录,定位当前版本
$rm apple.txt
$ll //有1个文件,good.txt
$git add apple.txt
$git status
//提示:git reset
//deleted: aaa.txt
$git reset --hard HEAD
//HEAD is now at ac36f52 new apple.txt
$ll //有两个文件,apple.txt和good.txt
删除文件找回方式的小结
前提是删除前文件存在时的状态提交到了本地库。
实际操作代码:
//进入的文件目录
rm aaa.txt //删除本地文件
git add aaa.txt //然后提交到暂存区
git commit -m ”delete aaa” aaa.txt //然后提交到本地仓库(删除完成)
找回操作:
git reset --hard [指针位置]
删除操作已经提交到本地库:指针位置指向历史记录(回到之前未删除版本)
删除操作尚未提交到本地库:指针位置使用 HEAD(git reset --hard HEAD)
4.3.8 比较文件差异
比较文件的不同:
git diff [文件名] //将工作区中的文件和暂存区进行比较
git diff [本地库中历史版本] [文件名] //将工作区中的文件和本地库历史记录比较,不带文件名比较多个文件
实际操作代码:
$ll //有两个文件,apple.txt和good.txt
$git status
//On branch master.
//nothing to commit,working tree clean
$vim apple.txt //修改apple.txt文件
$git diff apple.txt //只要有修改,用这个命令进行比较,显示红色-(删除行);绿色+(新增行)。
$git add apple.txt //把这个文件添加缓存区
$git diff apple.txt //显示没有区别
$git diff HEAD apple.txt //使用指针指向本地库,工作区和本地库进行比较
$git diff HEAD^ apple.txt //工作区和上一个版本(本地库的历史记录)进行比较
$git diff HEAD //不带文件名的时候,比较当前工作区的所有文件
接着4 Git 命令行操作
4.4 分支管理
4.4.2 什么是分支?
(1)在版本控制过程中,使用多条线同时推进多个任务。
版本库初始化之后,本身有master分支。
假设想开发一些新的功能,不想在master主干上进行开发,于是开取新的分支。新的分支feature_blue是从master复制过来的,刚创建的时候内容一致。想再开发一个功能,创建一个新的分支feature_game。两条分支各自开发。开发完成,测试没有问题,feature_blue分支可以合并到master。master可能出现bug,往往出现hot_fix分支,一般热修复(服务器上跑的项目不停止),紧急修复完再合并到master分支。等feature_game分支开发完,合并到master,master又是一个新的master。
(2)分支的好处?
- 同时并行推进多个功能开发,提高开发效率。
- 各个分支在开发过程中彼此独立、互不影响,如果某一个分支开发失败,不会对其他分支有任何影响。失败的分支删除重新开始即可。方便我们试错。其实SVN也有分支,但是用起来不方便,分支文件的管理效率低。
4.4.3 分支操作
实际操作代码:
$git status
//On branch master.
//Your branch is up-to-date with 'origin/master'.
//nothing to commit,working tree clean
$git branch -v //查看现在所有的分支,只有master
$git branch hot_fix //创建新的分支
$git branch -v //查看现在所有的分支,有hot_fix和master(目前在这)
$git checkout hot_fix//切换分支
//Switched to branch 'hot_fix'
$git branch -v //查看现在所有的分支,有hot_fix(目前在这)和master
$vim apple.txt //在hot_fix分支下进行文件操作
$git add apple.txt
$git commit -m "test branch hot_fix" apple.txt
//想把代码合并到master,当前所在的分支必须是master(站在被接受的分支上)
$git checkout master
$git merge hot_fix
//Updating...
$cat apple.txt //看到内容已经合并
总结
o1创建分支: git branch [分支名] /*例: git branch hot_fix
o2查看分支: git branch -v
o3切换分支: git checkout [分支名] /*git checkout hot_fix
o4合并分支: git merge [有新内容分支名]
//第一步:切换到接受修改的分支(被合并、增加新内容)上
git checkout [被合并分支名master] /*切换分支
//第二步:执行 merge 命令 (合并分支指令)
git merge [有新内容分支名]
//hot_fix a865afb hot_fix commit apple /*合并后查询分支效果
//* master a865afb hot_fix commit apple
o5解决冲突
冲突原因: 2个分支修改同一文件的同一位置,但是修改内容不一样时。
$git branch -v //两个分支一致
hot_fix 235ac97 test branch hot_fix
master 235ac97 test branch hot_fix
$vim good.txt //修改文件
$git add good.txt
$git commit -m "test conflict" good.txt
$git branch -v //两个分支不一致
//hot_fix 235ac97 test branch hot_fix
//master d715d90 test conflict
$git checkout hot_fix
$vim good.txt //在hot_fix分支下也修改good.txt,改同一行,第9行,修改不同的内容
$git add good.txt
$git commit -m "test conflict hot_fix" good.txt
$git branch -v //两个分支不一致
//hot_fix 4e38aa4 test conflict hot_fix
//master d715d90 test conflict
$git merge master //直接把master合并过来
//Auto-merging good.txt
//CONFLICT(content):Merge conflict in good.txt
//Automatic merge failed;fix conflicts and then commit the result.
//在SVN中产生冲突会产生几个额外的文件
$vim good.txt //打开文件看看
冲突的表现: 有当前分支内容和另一个分支内容
冲突的解决:
第一步:编辑文件,删除特殊符号
第二步:把文件修改到满意的程度,保存退出
$git status
//You have unmerged paths.
//(use "git merge --abort" to abort the merge)
//Unmerged path:
//(use "git add ..."to mark resolution)
//both modified: good.txt
第三步:git add [文件名]
$git add good.txt
第四步:git commit -m "日志信息"
$git commit -m "resolve conflict" good.txt //带文件名后面会报错
//fatal:cannot do a partial commit during a merge.
$git commit -m "resolve conflict"
//注意:此时 commit 一定不能带具体文件名
5 Git 基本原理
5.1 哈希(Hash)算法简介
哈希是一个系列的加密算法,(对Hash来讲,明文不一定是文字,音频、视频、图片文件都可以)各个不同的哈希算法虽然加密强度不同,但是有以下几个共同点:
①不管输入数据的数据量有多大,输入同一个哈希算法,得到的加密结果长度固定。例如md5(32的十六进制数)、SHA1、CRC32。
②哈希算法确定,输入数据确定,输出数据能够保证不变(同一个数据,不管什么时候执行,不管执行多少次,得到的结果一样)。
③哈希算法确定,输入数据有变化(哪怕细微变化),输出数据一定有变化,而且通常变化很大。
④哈希算法不可逆(根据密文无法反推明文)
Git 底层采用的是 SHA-1 算法。
由于特点③,哈希算法可以被用来验证文件。原理如下图所示:(传输前后hash值对比)
Git 就是靠这种机制来从根本上保证数据完整性的。(字母忽略大小写)
5.2 Git 保存版本的机制
5.2.1 集中式版本控制工具的文件管理机制
以文件变更列表的方式存储信息。这类系统将它们保存的信息看作是一组基本文件和每个文件随时间逐步累积的差异。例如,SVN。
每次只保存修改的那一部分,很好的节约内存空间。
5.2.2 Git 的文件管理机制
Git 把数据看作是小型文件系统的一组快照。每次提交更新时 Git 都会对当前的全部文件制作一个快照并保存这个快照的索引。为了高效,如果文件没有修改,Git 不再重新存储该文件,而是只保留一个链接指向之前存储的文件,所以 Git 的工作方式可以称之为快照流。
5.2.3 Git 文件管理机制细节
(1)Git 的“提交对象” (每个文件对应的hash值)
所有的hash值构成一个tree对象,包含hash值和对应的文件,它自己也有hash值。
提交对象包括tree对象,它自己也有hash值。
$git log //能看到每一次commit都有一个hash值
比特币和git里面的管理文件有非常大的相似点。比特币每一个做hash,然后两两做hash。
(2)提交对象及其父对象形成的链条
每一个版本,每一个快照,会有一个parent,会指向它的父节点。各个版本之间通过这个父子关系所建立的连接。“提交对象”里面还包括author信息和committer信息。
5.3 Git 分支管理机制
5.3.1 分支的创建(就是新建一个指针)
从数据结构上来说,这也是一个列表的结构。第一次提交有“root commit”。下面的master和testing都可以看成指针,指针指向某一个版本,创建指针比复制文件的效率高多了。
5.3.2 分支的切换 (HEAD指向)
切换到testing分支,HEAD指针移动。如下图:
HEAD指向testing时提交了内容。master留在原地,testing分支已经往前走了一步。如下图:
切换回 master,把HEAD指针重新指向master,如下图:
HEAD指向master时提交了数据,master往后移一步。如下图:
总结:分支是Git里面很重要的内容。下一篇文章介绍我们的账号管理。
说明:记录学习笔记,如果错误欢迎指正!写文章不易,转载请联系我。