前言:
大佬直接进入下面正题,前言可以略过!
我相信有很多童鞋在刚开始使用git
或者使用了许久之后还是对git
不怎么熟悉,尤其是出现了一大堆英文提示的时候手足无措,又或者代码"莫名其妙"的发生改动,导致团队无法继续正常工作的时候真恨不得不继续使用git
了.
不要慌!这篇文章将带你完完全全掌握平时常见的场景以及出现的问题如何解决的本领!(同时我自己也可以再复习一遍~?)
那么本文章默认你已经学习过了git
,但只是对git
有的知识一知半解的情况下去阐述!(也许热爱git
的你还不熟悉git
基础知识建议可以先去其他地方学习git
相关的基础知识,遇到不理解的也许这篇文章就会帮你解开谜团!)
最小配置
那么我们会发现在使用git
之前需要配置一段这样的命令(如果不配置以后push之类的操作会有一大堆提示信息影响我们的后续操作):
$ git config --global user.name 'your_name'
$ git config --global user.email 'your_email@domain.com'
那么这段命令中的--global
大家有没有想过是什么意思呢?究竟有什么作用?
config三个作用域
来讲下刚刚的--global(全局)
,那么既然有全局就肯定有局部作用域:在git
中叫做--local
,其实还有一个是针对系统的:--system
--global
是对当前用户(根据系统用户名判定)所有仓库有效
--local
只对当前工作的这个仓库有效
--system
对系统所有登录的用户有效(不常用,对整个系统进行配置统一的配置项)
查看config的设置命令:
$ git config --list --local
$ git config --list --global
$ git config --list --system
建立git仓库
把已有的项目代码纳入Git管理(场景一):
$ cd 项目代码所在的文件夹
$ git init
新建的项目直接用Git管理(场景二):
$ cd 某个文件夹
$ git init your_project #会在当前路径下创建和项目名称同名的文件夹
$ cd your_project
文件重命名(方法一)
假设我们重命名readme.md
为read.md
所以我们执行以下命令
$ mv readme.md read.md
这条命令会被git
认为是 readme.md
会删除掉了,然后新增了一个read.md
文件
我们现在要做的是把新增的read.md
文件添加到git
管理里,且删除原来的readme.md
文件
$ git add read.md
$ git rm readme.md
然后使用git status
查看管理状态
结果会发现现在变成了
Changes to be commited:
(use "git reset HEAD <file>..." to unstage)
renamed: readme.md -> read.md
至此,说明git
已经知道了我们在做重命名操作
假设现在我们发现自己误操作了,不想要刚刚的操作了,怎么办呢?
$ git reset --hard
其实这条命令属于git中比较危险的命令,他的意思是把暂存区工作空间里内容都清理掉(还原到刚刚操作重命名之前的状态)
文件重命名(方法二)
细心的童鞋可能发现刚刚重命名的操作过于复杂,那有没有简单的方法重命名呢?答案是:当然有!(有木有很激动)
$ git mv readme.md read.md
然后使用git status
查看管理状态
结果会发现现在也变成了
Changes to be commited:
(use "git reset HEAD <file>..." to unstage)
renamed: readme.md -> read.md
这样一句命令就完成了方法一完成的事情,是不是很简单呢~
那么我们想提交本次操作该怎么做呢?
我们可以直接使用
$ git commit -m '重命名readme.md为read.md'
我们发现现在已经成功的新生成了一个commit
记录
那么我们突然发现这次commit
没什么作用想撤销本次commit
提交该怎么做
$ git log #查看所有commitId
$ git revert <commit> #找到你想撤销的commitId复制并替换掉这里的<commit>
commitId是类似这样的:
删除暂存区文件(并不会直接删除工作区的文件)
$ git rm 文件名
暂存区相关
$ git rm --cached . #清理暂存区所有文件
git log
通过git log查看版本演变历史
其实git log后面还可以携带参数
$ git log --oneline --all #可以查看简洁的所有commit信息
$ git log -n4 #代表查看最近四次的commit信息
$ git log --all --graph #查看基于图形的commit历史记录
$ git log --oneline <branch> #查看某个分支的commit记录
分支操作
$ git branch -av #查看本地共有多少分支
$ git checkout -b temp #创建一个新的temp分支
$ git checkout -b temp <commitId> #基于某一个历史版本新建一个分支
删除分支
$ git branch -d 分支名
如果git有提示说明是在一些情况下git不允许删除,如果确认的确需要删除,那么可以把小写d改成大写D来强制删除
图形界面(git自带)
gitk
打开后也许会是这样
当然咱们可以借助第三方的软件,肯定比git自带的使用更加方便快捷,因为这篇文章重点偏向命令式操作,所以这里就不过多介绍了
分离头指针(detached HEAD)
有时候我们会做出如下操作
$ git checkout 415c5c8086e16 #后面的随机字符串指的是某一次的commitId
这时git
会给我们出现类似下面的提示
[外链图片转存失败(img-ZH8HAaMI-1566535540514)(https://user-gold-cdn.xitu.io/2019/4/30/16a6d56c726f3d47?w=733&h=226&f=png&s=129900)]
what?
这段话大概是在说:
你正在基于415c5c8086e16
这个commit
正在做一个checkout
的操作。
你现在正在处于分离头指针的状态,你可以做一些变更,产生一些commit
,或者你也可以把你自己生成的这个commit
丢弃掉,或者你可以继续做开发,并不会影响其他分支!
那么说的明白点就是:
我们现在正工作在没有分支的情况下,那么就是说现在没有branch跟它挂钩对应,那么如果当我们在这种情况下做了一些功能的开发后又切换到了其他分支后,最后很可能会被git当做垃圾清理掉,所以这就是分离头指针危险的地方!
但话又说回来,事物都具有两面性,用的不好或者在不知情的情况下使用肯定会对我们产生危害,但假设我们知道的他会有什么影响后,说不定多想想,还可能会带给我们好处呢。
好处
场景举例:有时候变更只是尝试性的变更,如果做出来感觉不好或者不想要了,那我们就可以随时把它扔掉(直接checkout
到其他分支,不理会他,过段时间就会自动被git
清理掉)!那假设我们坐下来感觉还不错,那么我们就可以使用
$ git commit -am '提交信息' #这条命令意思是直接生成commit不用add,但不推荐
我们提交后,准备使用git log看下commit记录,然后就会发现一件奇怪的事情发生:
我们仔细看下图片,右边只有一个HEAD,正常情况下,HEAD总会跟一个分支挂钩,但现在怎么没有分支啦?
说明现在我们还处于分离头指针状态!
我们现在尝试切换一下分支到master分支!
切换后git可能会出来如下提示
它说有一个commit在后面还没有加到master分支里面去,那么这个其实就是分离头指针导致的!
然后下面它还会再次提醒你,如果你想保存这次的commit
记录,那么你可以新建一个分支和这个3d4731d
这个commit
相关联!
如果你看都不看一眼这个提示,继续任性的往下随心操作,那么你刚刚在分离头指针状态下做的操作会统统丢掉!所以git的提示要多看
比较两个commit之间的差异
$ git diff commitId1 commitId2
$ git diff HEAD HEAD~1
$ git diff HEAD HEAD^
**HEAD可以指代最新的commit记录
^是指最新的commit的上一个commit
^^就是指上上一个
~1也是指上一个 ~2就是上上一个
所以这三条命令效果是一样的**
commit相关操作
修改最新commit的message
有时候我们提交的commit了发现描述的信息不全面,想进行修改,那么我们可以使用下面这条命令
$ git commit --amend
然后git
会弹出一个新界面,让我们调整之前的message,修改后我们可以使用:wq!来保存这个新修改的message并且退出这个窗口
修改前几次的commit的message
我们先来看张图
这里我们用到了git
中的变基
指令
那么本次我们想对图中标2的commit的message进行变更,那么我们该怎么做?
这里强调下,参数i是指交互式变基
就是指会弹出窗口让我们更方便操作的方式进行变基
还有就是被变基的commit的commitId会发生改变哦!
重点来喽
这里我们需要选择一个基
,我们这次要变更第二个commit,那么这个基就要选择被变(第二个commit)的这个commit的父级(第三个commit),父级的commitId是(27d2f814开头的那个),自己的commitId是(429243060b开头的那个),所以要基于父级(27d2f814开头的那个commit)去做变基
操作!
这块比较绕,大家自己先捋一捋
接下来看命令操作!
$ git rebase -i 27d2f814
敲下回车后我们发现弹出来了一个交互式的窗口
如图:
我们把4292430
开头的那个commit
的message
修改成 Add a refering projects
所以我们把pick
指令改成reword
指令
所以最终交互式窗口里的内容就会被我们修改为
$ reword 4292430 Add refering projects #这里我们只把刚刚的pick修改为了reword
$ pick a7dc188 Move filename readme.md to readme #本句可以无视,本例中只修改了第一句
修改完毕后我们使用:wq!
保存并退出交互式控制台
然后接着git
又会弹出另一个新窗口
那么我们在这里把Add refering projects
修改为Add a refering project
修改完毕后我们使用:wq!
保存并退出交互式控制台
然后git
会做出如下提示:
说明我们的变基
操作顺利完成了
变基
操作其实是用到了分离头指针去完成的,
其实git
先分离头指针,然后在上面做了调整,调整完毕后git
还把新的commit产生后用一个指针指向了它!
但这里需要注意:这只是本地的变基行为,如果有多人已经在线上操作正式项目,切不可盲目用该命令随意操作,不然后果很严重!
差异比较
暂存区和HEAD差异比较
说白了就是add
后的文件和最新commit
做比较
$ git diff --cached
工作区和暂存区的差异比较
说白了就是自己最新写的代码和add
里的对比
$ git diff -- 文件名
$ git diff #比较所有工作区和暂存区的差异
对比不同分支的相同文件的差异
$ git diff 分支一 分支二 -- 文件名
恢复相关
暂存区恢复为和HEAD(最新的commit)的内容一样
有时候我们add后突然发现我们不要暂存区的东西了,所以就要使用到如下命令了
$ git reset HEAD 或 git reset HEAD -- 文件名 #(如果没有写文件名就是全部恢复)
暂存区工作区都恢复为和HEAD(最新的commit)的内容一样
$ git reset --hard HEAD 或 git reset --hard HEAD -- 文件名 #(如果没有写文件名就是全部恢复)
这里补充说明下 --hard代表的是工作区
工作区的文件恢复为和暂存区的一样
有些时候做了一些变更,我们已经把这部分的代码放到了暂存区,然后我们又继续在工作区做了一些变更,做完之后,思前想后,发现工作区的变更还不如暂存区的好,所以我们就希望把工作区的内容扔掉,变成和暂存区的一模一样。
$ git checkout . #丢掉工作区全部的变更
$ git checkout -- 文件名 #丢弃这个文件的变更
这条命令也要慎用!一旦误操作,工作区最新的代码也就丢失啦!
stash
有时候我们正在写代码,突然加派紧急任务,要修改其他地方的bug
,但我们又不想提交正在修改的,所以我们就需要是使用一个命令把当前的状态临时保存起来
$ git stash #存储
$ git stash list #查看存储好的stash
存储好之后我们会发现工作区变成了干净的了。
那么假设我们的bug已经修改好了,我们想回到刚刚存储前的状态继续做之前我们做的事情,该怎么办?
$ git stash apply #把stash里面的东西取出来放到工作区,且他不会删除stash里的记录
$ git stash pop #把stash里面的东西取出来放到工作区,但他会删除stash里的记录
以上两个命令随便挑选一个使用都可以恢复,看情况而定
.gitignore
我们只需要在项目中新建一个名字为:.gitignore的文件
我们可以在.gitignore里配置自己想exclude(排除)的文件或文件夹。
远程相关
这里默认大家都会建立远程仓库,还不会的童鞋可以先去学习学习!
git push origin 分支名
把本地的某个分支推送到远程仓库
git push origin -d 分支名
# 用 -d 参数把远程仓库的分支也删了
假如是某个你自己独立开发的branch
出错了,出错的内容已经合并到 master
同事的工作都在 master
上,你永远不知道你的一次强制 push 会不会洗掉同事刚发上去的新提交。所以除非你是人员数量和行为都完全可控的超小团队,可以和同事做到无死角的完美沟通,不然一定别在 master
上强制 push
。
在这种时候,你只能退一步,选用另一种策略:增加一个新的提交,把之前提交的内容抹掉。例如之前你增加了一行代码,你希望撤销它,那么你就做一个删掉这行代码的提交;如果你删掉了一行代码,你希望撤销它,那么你就做一个把这行代码还原回来的提交。这种事做起来也不算麻烦,因为 Git
有一个对应的指令:revert
。
它的用法很简单,你希望撤销哪个 commit
,就把它填在后面:
$ git revert HEAD^
上面这行代码就会增加一条新的 commit
,它的内容和倒数第二个 commit
是相反的,从而和倒数第二个 commit
相互抵消,达到撤销的效果。
在 revert
完成之后,把新的 commit
再 push
上去,这个 commit
的内容就被撤销了。它和前面所介绍的撤销方式相比,最主要的区别是,这次改动只是被「反转」了,并没有在历史中消失掉,你的历史中会存在两条 commit
:一个原始 commit
,一个对它的反转 commit
。
总结
git常用的也就这么多,大家只要常用,记住它们不是啥大问题(当然我也要多记?),大家加油!
声明:
本文所有文字纯手打,远程相关中的revert命令参考了掘金小册
扔物线
大佬创作的小册,其余部分都是原创!码字不易,举起小手点个赞,你的赞就是作者最大的写作动力
文中如果出现错误,请大家在评论区指正,我会及时修改!
祝大家五一假期玩的愉快!