git学习【持续更新中。。。】
文章目录
一、Git基本操作
1.创建本地仓库
shell
mkdir gitcode
cd gitcode
git init #初始化


2.配置本地仓库
shell
git 配置项 name,email
git config user.name "ljh"
git config user.email "123123@qq.com"
git config -l # 查看配置项
git config --unset user.name # 删除配置项
git config --global user.name "ljh"
# 生效于所有的git仓库 因为往往我们的服务器上有很多git仓库
# 注意不能直接重置
git config --global --unset user.name
1.局部配置


2.全局配置

3.认识工作区、暂存区、版本库
我们在gitcode目录下,创建一个文件,命名为ReadMe

目前情况下,Git能否管理ReadMe文件呢?是不行的!!这里这个.git 称为版本库(仓库),ReadMe称为工作区,图示如下:

stage叫做暂存区/索引,也可以称为index
对工作区的修改包括:新增、修改、删除
在我们的版本库中存在一个objects区域:我们修改的工作区的内容会写入对象库的git对象中。
stage和master中存的都是索引,objects中存的才是对象。

注意:.git目录是不支持在该目录下进行手动修改的!!!
4.添加文件
shell
git add ReadMe
git add . # 将当前目录下所有文件添加到暂存区
shell
git commit -m "add first file" # 本次提交的细节信息
shell
git log # 查看提交日志
# commit: 哈希计算的数字,十六进制
# Author:ljh <....qq.com>
# Date:
# add first file
git log --pretty=oneline # 仅打印一行log

shell
cat .git/HEAD # ref:refs/heads/master
cat ./git/refs/head/master # 最新一次提交的commit号

我们的commit号:前两位:文件号 后面:文件标识

shell
git cat-file -p commit号
# tree: 所有的commit
# parent: 上一次提交的commit号
# author
# committer: add 3 file commit的内容/更改的内容

要记住!git追踪管理的其实是修改,而不是文件!
shell
git status # 查看当前仓库的状态 哪些文件在工作区被修改了

5.修改文件
如果要查看进行了哪些修改【查看暂存区和工作区文件的差异】
shell
git diff ReadMe

a/ :表示修改前 b/:表示修改后 根据上图可以发现 改动前后文件名没有变化
@@ -1 表示改动前一行 +1,2 表示改动后,连续两行
也可以 git diff HEAD - - [file] 查看版本库和工作区文件的区别
总结:git status + git diff 的组合可以用来查看哪些内容发生了修改+修改了哪些内容
6.版本回退
假如我们现在有两个版本的ReadMe,v1版本内容为git,v2版本内容为git world
shell
git reset [ --soft | --mixed | --hard ] [HEAD]
# 本质是回退的版本库的内容,还可以回退到当前版本
工作区 | 暂存区 | 版本库 |
---|---|---|
git world | git world | git world |
git world | git world | git 【- -soft】 |
git world | git | git 【- -mixed 默认】 |
git | git | git 【- -hard 慎用】 |
具体使用方法:
- git log - -pretty=online 得到的结果如下:
commit号1 (HEAD->master) modify ReadMe
commit号2 add file5
commit号3 add 3 file
commit号4 add first file 我想要回退到这个版本 - 使用 git reset - -hard commit号4 (注意工作区也回退!!!)
运行结果:HEAD is now at 58doaa3【commit号前几位】 add first file【commit 内容】 - 此时我们 la => .git ReadMe cat ReadMe => hello git
我们输入 git log - -pretty=oneline => commit号4 ( HEAD-> master) add first file - 如果反悔了,怎么办?我们刚刚打印出了最近一次修改的commit号1,此时我们使用 git reset - -hard commit号1,我们发现,所有的内容都回来了!log也回来了。为什么有反悔药可以吃呢?因为当前的终端还保留了之前的commit号,如果清掉屏幕/服务器关掉,再次使用git log 就拿不到之前的commit号了,那现在怎么办呢?
- 可以使用git reflog 这个指令记录每一次的提交命令,可以得到每次commit对应的短的commit号,使用这个短的commit号也可以进行恢复

为什么每次回退的速度都很快呢?原因如下图:
我们实际上回退的时候仅仅修改了master中的commit ID,所以速度很快
7.撤销修改
如果我们在我们的工作区写了很长时间代码,越写越写不下去,觉得自己写的实在是垃圾,想恢复到上一个版本
会出现下面几种情况
工作区 | 暂存区 | 版本库 | 解决方式 |
---|---|---|---|
1.xxx code | 1.手动撤销------不推荐,易出错 2.git checkout - - [filename] ------推荐 | ||
2.xxx code | xxx code | git reset | |
3.xxx code | xxx code | xxx code | 前提条件:commit之后没有push,使用git reset - -hard HEAD^ |
情况2的解决方案一:git reset HEAD ReadMe 【默认是 - -mixed 的】,HEAD表示回退到当前版本,HEAD^ 表示回退到上一版本,我们情况2的当前版本库为空。- -mixed 是暂存区和版本库回退,所以暂存区的 xxx code就清掉了,此时仅工作区有内容,就回到了情况1。之后我们再使用情况1的解决方案,git checkout - -Reade 即可
情况3:版本库存在最新版本的代码 xxx code,但是上一版不包含 xxx code,我们通常使用git进行版本控制的流程如下:工作区->(git add)->暂存区->(git commit)->版本库->(git push)->远程仓库,我们情况3撤销的前提是在commit之后没有进行push,撤销的目的就是不要影响远程仓库的代码。此时我们直接使用指令 git reset - -hard HEAD^ 即可。
8.删除文件
我们删除一个文件通常有两种方式:
- 首先 rm file5 删除工作区的内容,然后 git add file5 将删除提交同步至 暂存区,最后再 git commit -m "delete file5" 将删除同步到版本库
- 首先使用git rm file5 将工作区,和暂存区的内容都删掉,最后使用git commit -m "delete xxx" 将删除提交到版本库即可。
二、Git分支管理
1.理解分支
我们首先来看一个例子以便于我们更好的理解git分支功能:
HEAD可以指向其他分支,被指向的分支就是当前正在工作的分支。


2.创建、切换、合并分支
shell
git branch # 查看当前本地有哪些分支

shell
git branch dev # 创建一个名为dev的分支
cat .git/refs/heads

并且可以发现他们俩指向的提交的commit号是相同的,此时的状态为:

我们如何切换分支呢:
shell
git checkout dev
此时状态变成了:
注:在dev分支上修改代码,不会影响master分支【工作区、暂存区、版本库都是】

我们在dev上提交代码,此时状态变为了:

那我们如果让master和dev合并,master也保持最新状态呢?分为以下两步:
- git checkout master
- git merge dev

我们此时再
shell
cat .git/refs/heads/master
发现此时的master主分支的commit id和dev分支之前的commit id 是相同的

3.删除分支
删除本地分支,为了节约资源,指令为:
shell
git branch -d dev
因为创建,合并和删除分支非常快,所以Git鼓励你使用分支完成某个任务,合并后再删掉分支,这和直接在master分支上工作效果是一样的,但过程更安全。
4.合并冲突
git合并冲突是怎么造成的呢?
假如我们原来:master分支和dev分支 上的内容都是 aaa on dev branch
这时候我们将dev分支上的内容修改为 bbb on dev branch,并且将master分支上的内容修改为 ccc on dev branch,我们再使用git merge指令来合并,就会发生冲突!!!如何解决呢?
我们先在我们的服务器上复现出来上面出现的这种情况,这里再介绍一个新的指令:
shell
git checkout -b dev1
# 这条指令等于 git branch dev1 + git checkout dev1

模拟完上面的状态后,此时git中的状态图为:
我们再次切换到master分支上,然后尝试去合并
shell
git merge dev1

如何解决冲突呢?我们先看一下我们master分支下的ReadMe文件

我们的解决方案是:手动 vim ReadMe,然后删除掉不需要的代码 即可,再将修改后的文件进行add和commit就ok了。
此时git中的状态就是:
我们再去验证下dev分支下还是不是原来的数据:
此外,git也是提供可视图的:
shell
git log --graph --abbrev-commit

5.合并模式
git merge的模式:fast-forward模式:看不出来最新的提交到底是merge进来的还是正常提交的

介于fast-forward模式看不出来是否是合并而来的,所以合并可采用no-ff模式【很推荐,分别找锅】,即:
shell
git merge --no-ff -m "merge dev2" dev2
此时提交后的状态图信息为:
6.分支策略

有了分支,就可以进行多人协作开发了
7.bug分支
我们先模拟一下这个场景:
这种情况是我们不能忍受的!

我们的解决方案是使用 git stash 指令,要注意的是,git stash只能存储被git管理的文件,使用git stash后,工作区的代码就被存入到stash中了,且此时切回master分支时,未提交的代码不会影响master分支的使用。


后续需要处理stash中存储的工作区的内容时,可以通过:
shell
git stash list # 查看stash中存储了哪些内容
git stash pop # 将stash中内容恢复到工作区
这个时候就可以转去master分支去修复bug了,dev1分支上工作区的内容不会影响到master分支,我们基于master分支的基础上再创建fix_bug分支,去修复bug,修复完成后合并到主分支。此时的状态图如下:
此时如果让master去合并dev 这个操作是不可取的!因为dev上的bug还未修复,会和master冲突。

正确的做法是:让dev去合并master,合并后就算有问题也可以在本地分支多次修改测试,不会影响master代码,此时的状态:

8.强制删除分支
这个需求的场景如下:

shell
git branch -d # 不行,只能删被merge后的分支
git branch -D # 强制删除