一、Git中的对象(涉及到底层)
-
blob对象
用于表示一个文件;
根据其内容计算哈希值,前面两位哈希值作为./git/objects/
下面的文件夹目录名字,剩下的38位哈希值作为文件的名字。
不同名但是相同内容的文件,其哈希值相同,其blob对象也是共用的,所以就有了树对象,可以保存文件名。 -
commit对象
用于表示一个提交;
每一次提交都会产生一个commit对象,commit对象之间会组织成一棵树的结构,除了第一次提交产生的commit对象,其它的commit对象都会有父亲commit对象;
如果只是提交操作,则父亲节点只有1个;如果是merge操作,则父亲节点会有2个;
commit对象包含的信息有parent和描述信息。 -
tree对象
用于表示根目录树对象;
包含下面几个属性,author-作者,committer-提交者,tree对象-表示一个目录。
1、blob对象
# 该指令用于返回对应文件的哈希值
git hash-object fileURL
# 该指令将文件写入blob对象,并返回对应的哈希值
git hash-object -w 文件名
上述git hash-object
指令只有加了-w
才会写入blob对象,不加只是返回对应文件的哈希值。执行这条指令后会生成key为哈希值,value为压缩后文件内容,并存到.git/objects
目录下面。
直接将git对象刷到版本库中,并没有经过暂存区(./git/index
)。
确认blob对象的类型。
使用git cat-file -p hash
指令拿对应对象的内容。git cat-file -t hash
拿对应对象的类型。
2、tree对象
# 100644表示这是一个普通文件,100755表示这是一个可执行文件,120000表示这是一个连接符号
git update-index --add --cacheinfo 文件模式码 hash tree对象名字
上面的git update-index
指令只是将tree对象作为一条记录放入暂存区并存到.git/index
文件中(为了让blob对象对上文件名),而且暂存区中相同的名字会被覆盖。
可以使用git ls-files -s
指令查看暂存区中的数据。
git write-tree
使用上述指令将tree对象刷到版本库中。
确认tree对象的类型。
3、commit对象
echo '描述信息' | git commit-tree tree对象的哈希值
使用上述命令可以对tree对象添加描述信息,返回commit对象的哈希值,将该commit对象添加到.git/objects
目录下。
确认commit对象的类型。
二、高级指令(平时用的)
1、工作目录下的文件状态
- 未跟踪
- 已跟踪
-
- 已修改
-
- 已暂存
-
- 已提交
git tag 标签名 commithash
使用上述指令可以生成一个标签,标签就类似一个不会改变的分支。
# 删除指定标签
git tag -d 标签名
# 推一个标签到远程仓库
git push origin 标签名
# 把全部不在远程仓库中的标签都推到远程仓库上面
git push --tags
2、基本操作
# 可以指定目录,也可以指定具体的文件
git add ./
使用上述指令将文件进行跟踪,此时已经是已修改的状态了,但是还没有添加到暂存区。
# 将已修改的文件加入到暂存区
git commit -m "description message for this commit"
# 直接将未追踪的文件加入暂存区(初始化后的第一次使用不能直接用这个指令)
git commit -a -m "description message for this commit"
上述指令可以将文件添加到暂存区即.git/index
文件中去。
git rm 文件的URL
使用上述指令后,会将该文件从暂存区中移除,并且也会从工作目录中移除。
git mv 老的文件名 新的文件名
使用上述指令后,可以将文件重命名。
git log --pretty=oneline
使用上述指令后可以查看可以显示所有提交过的版本信息,不包括已经被删除的 commit 记录和 reset 的操作.
git reflog --pretty=oneline
使用上述指令后可以显示所有的操作记录,包括提交,回退的操作。大多用来找出操作记录中的版本号,然后进行相应版本的回退。
3、分支相关
注:分支的本质就是提交对象的指针!
HEAD 文件是一个符号引用,指向目前所在的分支。
git branch 分支名
使用上述指令可以新建一个分支,并指向当前的提交对象,但是并不切换当前分支。
git branch
使用上述指令可以查看所有已存在的分支名。
git branch -d 分支名
使用上述指令可以删除指定的分支,如果要强制删除需使用-D
。
git checkout 分支名
使用上述指令可以将当前的HEAD指向指定的分支。如果切换到一个较旧的分支,工作目录会恢复到该分支最后一次提交时的样子,所以记得先提交,并使用git status
指令检查当前分支是干净的之后,再切换分支。切换后会改变HEAD、暂存区内容、工作目录的内容,不过分支不会跟着HEAD变化,这是和git reset --hard commithash
最大的不同。
git checkout -b 分支名
使用上述指令可以新建一个分支指向当前的提交对象,并立刻切换到该分支上。
git branch -v
使用上述指令可以查看每一个分支上的最后一次提交。
git merge 分支名
使用上述指令后可以将指定分支的修改合并到当前分支上面,注意不要搞反!
git reset --soft commithash
# HEAD~表示上一次HEAD指向的提交对象
git reset --soft HEAD~
使用上述指令后可以将HEAD及其指向的分支都后退一步(相当于撤销了一次提交)。此时仅仅修改了HEAD的指向!
git reset --mixed commithash
# HEAD~表示上一次HEAD指向的提交对象
git reset --mixed HEAD~
使用上述指令后可以将HEAD及其指向的分支都后退一步(相当于撤销了一次提交)。此时不仅修改了HEAD的指向,并且修改了暂存区的内容。
git reset --hard commithash
# HEAD~表示上一次HEAD指向的提交对象
git reset --hard HEAD~
使用上述指令后可以将HEAD及其指向的分支都后退一步(相当于撤销了一次提交)。此时将HEAD的指向、暂存区的内容、当前的工作目录都进行了修改。
git commit -amend
在使用上述指令的时候,如果自上次提交以来你还未做任何修改,那么快照不会改变,但是可以修改提交的信息。
如果你发现上次的提交不完整,你想要将完整的部分和上一次的提交合并为一个提交,可以使用下面的指令。
# 此次提交的修改不完整
git commit -m "this is a commit"
# 将文件改为完整修改的版本
# 追踪要修改的文件
git add 要修改的文件名
# 合并两次的提交
git commit -amend
git stash
如果需要切换分支,且分支中有修改但还没到提交的时候,使用上述指令后,将未完成的修改保存到一个栈中。
当前换回该分支时候,使用下面的指令重新应用这些改动。
# 这条指令不会从栈顶弹出快照,还需要配合drop
git stash apply
# 这条指令会弹出栈顶的快照
git stash drop
# 这条指令会应用栈顶快站并将其出栈
git stash pop
三、合并场景模拟
场景描述:自己在公司开发网站的时候,为了实现某个需求,创建了一个分支,在这个分支上便写了一些代码。此时领导直接打电话给你,说现在的系统有个紧急BUG,赶紧修一些。那你需要切换到主分支上面,为这个BUG新建一个分支,在该分支上解决掉这个BUG之后,切回主分支,合并刚刚为了解决BUG而新建的分支。BUG修完,自己才可以去需求的分支上继续操作。
初始化的系统如下图所示,即有一个version的文本,里面内容是this is v1。
自己为了解决一个新的需求,创建了叫做new98的分支,并在这个分支上面,提交了一次记录,修改了version的文本。
接了领导的需求,切回主分支并新建分支修BUG,将version的文本增加了一行。
将为了修复BUG而新建的分支上的东西合并并到主分支上。
将主分支上的代码合并到新需求的分支上面,可以看到产生了冲突,使用git status
定位到产生冲突的文件。
修复冲突后,使用git add ./
指令标记冲突已解决(此时分支状态是merging),提交修改后才回到正常状态。