好记性不如烂笔头,古人诚不欺我。
之前学过git的基本操作,但是在后续使用上经常记不起来具体命令,趁着空闲重学一遍,记录如下
git log
单行显示历史
git log --pretty=oneline
HEAD
是git的指针,表示当前版本,HEAD^
表示当前版本的上一个版本,HEAD^^
表示当前版本的前两个版本,以此类推。
一种简单的表示方法是HEAD~n
,其中n
为任意整数,表示当前版本的前n个版本。
回退到上一个版本的命令是:
git reset --hard HEAD^
注意上图,当再次执行git log后发现:–hard会导致当前提交记录消失
如果执行了上述命令仍然还想回复之前的提交,那么可以查看之前命令行记录找到要找回版本的commit ID
,使用命令
git reset --hard 提交id
发现重新将HEAD指向丢失的版本。我们之前编写的内容又回来了。
实际上HEAD类似C语言的指针可以指向不同内存一样,也可以指向不同的版本,HEAD指向那个版本,我们文件就定位在哪个版本。
上述操作其实还有一个问题,当我们执行git reset --hard HEAD^
前没有执行git log
,那就找不到要恢复版本的提交id了,此时可以利用
git reflog
查看我们操作的每一条命令,包括历史版本的提交id,下图中可以看到要回退版本的提交id,那么就可以在回退回去了。
版本回退时,可以使用git log
查看历史版本,然后执行git reset --hard 提交id
回退到指定版本,如果要重返未来,执行git reflog
查看未来版本的提交id,仍然执行git reset --hard 未来提交id
返回到未来版本
(图片来自阮一峰的官网)
在git管理中,文本文件的存放位置分为三个区域
其中工作区是我们写代码的区域,当写好一部分功能后,执行 git add .
就将所有文件提交到暂存区,当多个文件根据功能依次编写并提交到暂存区以后,执行git commit -m "提交信息"
一次性将代码提交到仓库。commit提交只是将暂存区的文件修改进行了提交,如果文件修改没有执行add
,那么不会提交在项目目录下的名为.git
隐藏文件夹即为仓库所在位置。
需要注意的是git能管理并记录文本文件的版本,同时检查出每次提交修改的差异,但是对于二进制文件却不能检查出修改的差异,比如word文件,只能管理版本,不能看出具体每次提交修改了哪些内容。
当切出一个分支修改,或者暂存以后进行文件修改之后,我们想要恢复到修改以前的状态,那么执行
git checkout -- 文件名
执行以后就恢复到了之前git add
或者git commit
之后的状态了
场景1:当修改乱了工作区某个文件内容时,想丢弃工作区的修改时,执行git checkout -- file名称
场景2:当不仅仅修改乱了工作区某个文件内容,而且还添加到了暂存,想丢弃修改,那么分为两步,第一步用 git reset HEAD 文件名称
就回到了场景一,第二步按场景1进行操作。
场景3:当不仅修改了暂存区还提交了本地仓库后想撤销修改,那么可以执行版本回退实现。
git 实际管理的不是文件,而是文件的修改。当新增文件执行add
和commit
操作提交以后,我们手动删除或者执行rm删除后,还可以利用git恢复改文件。使用命令
git checkout -- 文件名
在windows power shell中执行
ssh-keygen -t rsa -C "自己的邮箱@qq.com"
一路回车,如果顺利那么就会在用户主目录找到.ssh目录,里面有id_rsa
和id_rsa.pub
两个文件,分别是私钥和公钥。私钥不能泄露,公钥可以放心告诉别人。
github是世界上最流行的公有github仓库,github需要SSH key的原因是github需要识别出提交内容是我自己提交的,不是别人毛寸的,git支持ssh协议,所以github知道知道了我的公钥,就可以确认是自己推送的。
在github等远程仓库管理平台新建一个仓库(具体操作再次省略,参考github文档),然后复制仓库地址,在本地仓库执行
git remote add origin 复制的地址
添加以后远程库的名字就是origin
,这是默认的,也可以修改,不过一般一看就知道是远程库,如果要同时添加两个远程仓库,那么必须对origin
重命名了
git remote add github 复制的github的地址
git remote add gitlab 复制码云仓库的地址
还有一种添加是为远程分支增加另一个仓库地址,相当于一个库名两个地址,这种的好处是可以将代码同时推送到同一个远程库
git remote set-url --add origin 仓库地址
git remote -v
git remote show 远程分支名
这里的重命名是指修改远程仓库显示在本地的名称
git remote rename 旧名称 新名称
这里的删除并不是真正的删除,而是取消本地目录下关联的远程库
git remote remove origin
默认只有一个远程分支时,在本地执行
git push -u origin master
-u
参数就把本地的master
分支和远程的master
分支关联起来,以后推送和拉取可以省略改参数。master
分支推送到远程,//拉取分支
git pull 远程仓库1 远程分支名称:本地分支名称
//推送分支
git push 远程仓库1 远程分支名称:本地分支名称
建立一个git仓库推荐的方法是先建立远程仓库,然后利用克隆命令克隆下来
git clone 远程仓库地址
git 地址有两种格式 https
和ssh
格式,两者对比,https速度慢(每次推送都需要口令),ssh速度快,
该命令在本地主机生成一个记录,默认与远程主机的版本库同名,如果要指定本地的目录名,那么执行
git clone 远程仓库地址 本地仓库名
git remote -v
当前仓库详细信息
git remote show origin
分支类似平行宇宙,能够实现多人同时对一个项目进行开发。
git checkout -b dev #dev是分支名称
git branch dev
git checkout dev
git branch
新建分支后,可以查看当前处于dev分支(标*
代表当前分支)
在当前dev分支上某个文件上增加内容并提交
git checkout master
或者
git switch master
checkout
与之前的撤销修改checkout -- file
是同一个命令容易混淆,因此新版git提供了switch命令来切换分支当dev分支上的一个新功能编写完毕后,需要合并到master分支进行部署测试,切换到master分支,执行
git merge dev
git merge
就是把指定分支合并到当前分支,合并以后,可以查看内容一致。
新功能完成后,就可以删除之前的开发分支dev了,执行
git branch -d dev
当多人在不同分支上对同一行代码进行了修改,那么合并是会出现冲突,如下图
利用git status
查看冲突文件
图中提示both modified
即都修改了这个文件,利用vscode等编辑器能更加方便的看出修改的内容
手动修改以后,再次执行 git add .
和git commit -m "提交信息"
完成提交
执行
git log --graph --pretty=oneline --abbrev-commit
或者
git log --graph
最后删除feature分支 git branch -d feature1
开发过程中,分支一般分为以下几种
最稳定的分支,时刻都能部署到生产环境上,不能在上班干活
开发分支,所有人员基于此分支进行开发,开发到一个指定阶段就合并到master
分支,master
分支发布1.0
版本。多人开发时每人都有自己的分支,时不时的往dev
上合并就可以.
新功能分支,每一个新需求就从dev
分支checkout
一个新功能分支feature-n
进行开发,开发完毕后合并回dev分支.
当一个新功能分支feature-01
开发完毕准备合并到dev
分支时,需求又变化了,不需要这个功能了,那么执行
git branch -d feature-01
会提示删除失败,因为该分支还没有被合并,如果删除则丢失此分支,如果要强行删除,那么执行
git branch -D feature-01
完成删除
当生产环境出现bug需要紧急修复时,每个bug可以通过一个新的临时分支bug-01
来修复,修复完毕后切换回master分支进行合并,最后删除bug-01
分支。bug有可能在你在feature2
分支上写新功能的时候提出,这时你的新功能没有写完,可以对未完成代码进行贮藏,贮藏就是对未完成代码的临时存放,执行
git stash
贮藏完成后,切换到master
分支,创建临时分支修复bug,修复完成后切换到master
,完成合并,最后删除bug-01
分支。
最后切回新功能feature2
分支,恢复贮藏,执行
git stash list
可以查看贮藏列表,再执行
git stash pop
恢复之前贮藏的代码并删除贮藏。
除了使用git stash pop
恢复之外还可以使用
git stash apply stash@{n} //n为具体的某次贮藏
恢复,恢复后stash内容仍然在,需要使用
git stash drop //删除一次
git stash clear //删除所有
来删除。
贮藏可以执行多次,当多次贮藏后会有一个列表,想要恢复指定贮藏只能使用git stash appley *待确定*}
来实现。
接上述,当在master上修复bug后,因为dev也是从master上拉出来的,dev上也存在这个bug,必须修复,有个简单方法是把修复bug的这次提交ea32632 bug 修复
“复制”到dev上,而不是把整个master
合并过来。
切换到dev
分支以后,执行 摘 樱桃 操作
git cherry-pick bug修复提交的id
自动给dev
分支做出提交。同理,我们修复bug时也可以在dev
分支上执行,然后“复制”到master上。但是一般dev上有新功能。
当从远程仓库克隆后,git自动把本地master
分支和远程的master
分支对应起来了,并且远程仓库默认名称为origin
多人协作的流程一般是:
克隆仓库 -> 检出dev分支 -> 创建自己的分支 -> 功能开发、提交并合并到dev分支 -> 拉取远程dev分支 -> 解决冲突 -> 推送到远程dev分支。
注意:
master
分支,此时需要origin
的dev
分支到本地,执行git checkout -b dev origin/dev
dev
分支与远程origin/dev
分支没有连接,报错。执行连接命令git branch --set-upstream-to=origin/dev dev
git pull 远程仓库名称 远程分支名:本地分支名
如果拉取的远程分支是和当前所在本地分支合并,那么冒号以后的可以省略
git pull 远程仓库名称 远程分支名
如果当前分支只追踪了一个远程分支,那么 远程仓库名称和远程分支名也可以删除
git pull
git log --graph --pretty=oneline
在上述多人协作的多次提交中,假设我修改了两处内容后要推送到远程dev分支,在这之前有人推送到了新的dev到远程,我拉取后合并(flag),就会出现提交历史发叉现象,虽然可以直接推送到远程,但是不好看。那么现在就可以使用变基使提交变为一条直线后在推送。
在执行完flag后,执行
git rebase
等待执行完毕,执行git log --pretty=oneline
查看提交历史,发现变为了一条直线。仔细查看会发现rebase会把我们的提交改变位置,不过最终结果不变。
一般工作中我们在master版本上线后,切出dev分支进行开发,开发完成后,在dev上变基到master分支,然后提交测试。
当完成一阶段的代码开发可以发布生成环境时,可以对最后的提交做一个“快照”,方便以后检索,这个快照就是标签,
git tag 标签名 //对HEAD打标签
或者
git tag 标签名 提交id //对某次提交打标签
或者
git tag -a 标签名称 -m "标签说明"
git show 标签名称 //查看指定标签
git show //查看所有标签
git tag -d 标签名称 //删除本地标签
git push origin 标签名 //推送一个本地标签
git push origin --tags //推送所有未推送过的标签
如果标签已经推送到远程分支,那么需要两步,先删除本地分支在删除远程分支。
//依次执行
git tag -d 标签名称 //删除本地标签
git push origin :refs/tags/标签名称 //删除远程分支
当我们对一个项目目录执行 git init之后
因种种原因需要撤回时,可以在执行命令的目录下删除.git隐藏文件夹即可。删除方式为:
rm -rf .git
当我们完成代码编写并commit以后发现有个错误,但是由不能再次提交,(规范有效提交)我们可以采用撤销commit来重新编辑,
git reset --mixed HEAD~1
--mixed
还可以使用--soft
与--hard
,三者区别是 --soft
将提交内容撤销到暂存区,--hard
直接丢弃提交内容,--mixed
将提交内容撤销到工作区。个人觉得用--mixed
比较方便。