整理一些git常用的命令和一些骚操作~
git log
查看提交历史,默认不包含任何参数,或按照提交时间列出所有的更新,最新的排在上面。
查看提交的差异(diff)
可以用-p
选项来展开每次提交的内容差异,用-2
显示最近的两条更新:
1 | git log -p -2 |
还可以使用—stat
来简要显示增改的行数统计:
1 | git log -p --stat |
精简显示log
--pretty=<format>
可以以给定的格式打印提交的日志。其中<format>
可以是:
oneline
short
mediu
full
raw
查看某个文件的改动
可以在git log
后面直接跟上文件名,来查看针对这个文件的改动(当前分支),加上-p
显示具体改动:
1 | git log -p file |
如果该文件不在当前目录,需要先切换到目录的文件夹。
中文文件名乱码
git 默认中文文件名是\xxx\xxx
等八进制形式。是因为对0x80
以上的字符进行quote
。
只需要将core.quotepath
设置为false,即可对中文文件名不再转码。
设置的命令:
1 | git config --global core.quotepath false |
然后在查看git log
,文件名将显示正常。
搜索
搜索git记录里面author包含zhang
:
1 | git log --author zhang |
搜索git记录提交说明message里面包含table
的提交:
1 | git log --grep table |
只要满足任意条件即可显示出来:
1 | git log --author zhang --grep table |
同时满足两者才可显示:
1 | git log --author zhang --grep table --all-match |
查看文件的改动
git log --name-status
查看每次修改的文件列表,并显示状态git log --name-only
查看每次修改的文件列表git log --stat
查看每次修改文件的列表,以及文件修改行数的统计。
log显示的时间
默认状态下的时间显示为:Date: Thu Sep 3 14:53:25 2020 +0800
,这样很不直观,我们需要更直观的表现形式。
可以设置git config log.date ios
这样将时间格式设置为iso
的形式:Date: 2020-09-25 13:48:04 +0800
。
可以全局设置下:
1 | git config --global log.date iso |
常用的时间格式有:
- relative 显示为与当前时间相对的时间,比如:
2 hours ago
。 - local 显示为本地时区的时间。
- iso iso格式的时间
- short 剪短的只展示日期,不显示时间
git blame
git log
可以查看当前所有的改动,后面加上文件参数可以查看对于这个文件的所有改动,那么我们想看一个文件的某一行的改动的话怎么看?
可以使用git blame
。
git blame
可以显示一个文件的每一行的最后一次改动的作者和提交hash。然后我们可以根据hash去查看对应的更改。
重要的参数有:
-L <start, end>
比如,想查询某个文件的122行到133行的记录,可以:git blame -L 122,133 login.page.ts
-t
显示原始时间戳,即不格式化时间,可以节省横向空间。-S
使用resv-file中的修订,而不是调用git-rev-list
,更简化的输出。-color-lines
提交的记录的元数据不同的话就颜色不同区分
git branch
git branch
如果不加参数,直接执行,输出本地所有分支。当前所在的分支前会加上*
号来标记。
git branch -v
加上 -v
参数,可以查看各个分支最后一个提交对象的信息。
git branch --merged
加上--merged
参数,可以查看哪些分支已被合并入当前分支
git branch --no-merged
加上--no-merged
参数,可以查看哪些分支还没有合并进当前分支
筛选本地分支
我们可以通过grep
参数筛选分支名:
1 | git branch | grep 'hotfix' |
上面通过grep
参数筛选分支里面包含hotfix
字符串的分支,并显示。
可以加上grep -v 'name'
的方式,来反向排除:
1 | git branch | grep -v 'hotfix' |
上面可以展示除过包含’hotfix’字符串的分支。
其实| grep
这种用法并不是git的,而是linux中的标准输入输出的管道操作符。grep
的选项常用的还有:
-i
忽略字符串大小写的差别-v
反转查找-x
只显示全符合的列
批量删除本地分支
有时候本地分支太多了,太乱,需要删除,但不可能一个个删除,那样也太繁琐了,我们怎么批量删除本地分支?
结合上面的过滤分支,我们可以使用linux管道xargs
组合起来实现我们的想法。
xargs
命令是给命令传递参数的一个管道,也是组合多个命令的一个工具。思路分两步:
- 通过
git branch | grep
获得要删除的分支名称 - 将分支名称通过
| xargs
传递给git branch -D
进行删除
具体实现:
- 切换到不用删除的分支(比如master:
git checkout master
) - 删除
- 运行:
git branch | grep -v 'master' | xargs branch -d
(删除本地已提交的分支) - 全部舍弃本地分支:
git branch | grep -v 'master' | xargs branch -D
:
- 运行:
这样,除过master分支之外,其他分支都被删除了。
本地分支跟踪远程分支
在本地创建分支,然后推送到远程,然后拉取的时候,会说本地分支没有跟踪远程分支,需要建立下连接:
1 | git branch --set-upstream-to=origin/<branch> you-local-branch |
省去这一步,可以在推送远程分支的时候直接加上跟踪当前分支的参数:
1 | git push --set-upstream origin you-local-branch |
这样,既把本地分支推送到了远程,同时也将本地分支跟踪了远程分支。
查看某个提交属于哪个分支
有时候代码合并之后,忘记了需要去追踪这个提交在哪个分支上存在
1 | git branch --contains commitID |
git show
对于一次提交来讲,它展示日志消息和文本差异。
1 | git show d28737d250651514d629ba8e4e240530505c98dc |
remote 远程库的操作
查看远程url
1 | git remote show origin |
显示远程库的源地址, 例如:
1 | ╰─$ git remote show origin |
可以列出当前库的远程url,以及本地分支和远程跟踪分支的状态。
或者可以直接简单的查看远程url:
1 | git remote -v |
输出:
1 | ╰─$ git remote -v |
修剪远程已删除的分支
prune
的意思是清理、修剪。有时候我们在远程上删除某些分支,但是在本地工程里,例如使用git checkout
的时候还是会看到远程已删除的分支。
1 | git remote prune |
查看远程库里已经删除的分支:
1 | git remote prune origin --dry-run |
注:后面带着参数dry-run
是为了只列出,不删除
如果要列出并删除,那么不带dry-run
参数即可:
1 | git remote prune origin |
修改远程的url
1 | git remote set-url origin new-url |
比如我们的git是用ssh拉取的,但是ssh太慢了,需要换成http的,那我们只需要:
1 | git remote set-url origin http://xxxxxxxxx.git |
然后查看换了的url:
1 | git remote -v |
查看branch的提交信息
当本地有很多分支的时候,我们想找到某个分支,但是又会混乱到底哪个分支的内容是啥,这时候就比较捉急了.
我们一般用git branch
这个命令,但是会单独的跳出一个新的窗口,然后只能看到branch的名字.只有我们切过去后才能通过git log
查看这个分支对应的commitl信息,这样很不方便.
我们可以用for-each-ref
结合shell命令来做一个集成的命令,快速展示各个分支的最后一个提交信息.
在~/.gitconfig
中配置我们的命令:
1 | [alias] |
这样我们就可以使用git branchs-info
这个命令来快速的查看当前每个分支的信息:
1 | git branchs-info |
这样能够方便快速的找到我们需要的branch,并切在删掉长久不用的分支的时候也很有用.
git tag
打tag
可以方便快速的打tag:
1 | git tag v1.0.0 |
也可以带上描述信息:
1 | git tag -a v1.0.0 -m '测试打tag' |
将本地tag推送远程:
1 | git push origin v1.0.0 |
删除tag
有时候tag打错了,需要删除:
1 | git tag -d v1.0.0 |
同时也要删除远程的tag:
1 | git push origin --delete v1.0.1 |
获得最近打的tag
获得sit上的最后一个tag:
1 | git describe --tags `git rev-list --tags --grep prod --max-count=1` |
回滚
最麻烦的莫过于合错了或是提交错了,这种情况需要回滚。
本分支修改,还没提交
可以用checkout
来将本地未commit的记录丢弃。
git checkout .
将本地所有未暂存的记录丢弃git checkout file-path
将固定路径的文件的未暂存的修改丢弃git checkout HEAD
将本地分支还原到当前的HEAD,已暂存的也会被丢弃
本分支修改,已经提交了
这个时候还没有推送,还是可以挽回的,所以直接找到想要回退的commit的hash,然后使用reset
命令:
1 | git reset commit-hash |
可以传递参数来标记重置的操作:
- –soft 缓存区和工作目录都不会改变
- –mixed 默认选项,缓存区和你指定的提交同步,但工作目录不受影响
- –hard 缓存区和工作目录都同步到你指定的提交
如果想直接舍弃当前的提交,那么就直接用--hard
参数即可全部丢弃。
本分支修改,并已经推送到了远程
这种情况就比较麻烦,可以使用Revert
命令
1 | git revert commit-hash |
Revert
撤销一个提交的同时会创建一个新的提交,这是一种安全的做法,它不会重写提交历史。
也可以使用reset
命令:
1 | git reset --hard commit-hash |
一定要确认好,一旦执行了reset并push --force
之后,提交记录就抹去了。修改的东西也会没有了。
相比git reset
,git revert
不会改变现在的提交历史,可以用在公共分支上,而git reset
会将前面的记录抹去,应该用在私有分支上执行。
git commit 提交
常用的提交暂存区到仓库区:
1 | git commit -m 'xxx' |
多行信息提交:
1 | git commit |
回车后是在vim中编辑提交信息,这里可以提交多行,编辑好后按照vim的保存退出即可。
提交工作区自上次commit之后的变化,直接到仓库区(即不用先git add
):
1 | git commit -a |
将暂存区的文件提交时在vim中的注释中显示所有diff信息:
1 | git commit -v |
git diff 查看差异
在未提交的情况下,可以直接使用git diff
查看我们修改了啥。或者可以加上文件名称来查看具体某个文件的修改:
1 | $ git diff |
在已经暂存(staged)的情况下,我们可以加上参数--staged
来查看已暂存的文件的比较:
1 | $ git diff --staged |
.gitconfig 文件
git 会在安装好后自带一个git config
工具来帮助设置控制Git的外观和行为配置变量。这些变量会存在三个不同的位置:
/etc/gitconfig
包含系统上每一个用户以及他们仓库的通用配置。如果在执行git config
时带上--system
选项,那么就会读写该文件中的配置变量。(需要管理员或超级用户权限来修改它)~/.gitconfig
或~/.config/git/config
,只针对当前用户,可以传递--global
选项来读写该文件,这会对你系统上所有的仓库生效。- 当前项目仓库的git目录中的
config
文件(即.git/config
),针对该仓库,可以传递--local
选项让git强制读写此文件。
每一个级别会覆盖上一级别的配置。
我们主要常用的是当前用户的配置。需要在当前用户的目录下找是否有~/.gitconfig
文件,如果没有就新建:
1 | touch ~/.gitconfig |
然后在.gitconfig
文件中编辑我们的一些特定设置:
1 | [alias] |
克隆固定分支
因为特定情景需要,我们可能需要clone一个项目的特定分支,然后去做对应的业务.但是如果项目很庞大,直接用git clone
这样下来的话会将整个项目每个分支都拉下来,文件很多,遇到网络问题可能拉取速度只有几十kb,这样会很慢.
因为我们需要的是特定分支的代码,所以我们可以在clone的时候将分支参数带上,就只拉取特定分省去很多不必要的文件:
1 | git clone --depth=1 --branch orderly-prod --single-branch git@gitlab.com:xxx.git |
一对比真的会省去很多资源文件,速度也变快了.
git clean 清理
有时候搞了很多新文件并且有修改的地方,但是需要舍弃全部,这时候我们用git checkout .
只能还原已经跟踪的文件,如果是新建的文件或文件夹,是不会动的.之前是手动一个个使用rm -rf
来删除,很傻.
我们可以使用git clean
命令来清除未track的文件和文件夹.
git clean -n
传递-n
参数会显示将要删除的文件,但只是显示,不会删除.git clean -f
传递-f
参数会删除新增的未track的文件,但不会删除新增文件夹和文件夹里面的文件.git clean -df
传递-df
参数会删除新增的未track的文件和文件夹(包括文件夹下面的文件).git clean -xdf
传递-xdf
参数会删除新增的未track的文件和文件夹(包括文件夹下面的文件),还包括被.gitignore
文件过滤的文件或文件夹,所以这个命令是一般不用.
git ignore 已经track的文件
假设在项目刚开始的时候,就将编辑器配置文件,比如vscode 对应.vscode
; webstorm 对应.idea
将这些文件已经提交到git,并推送了远程了.
现在发现了,需要将这些文件从git中删除,或者需要将这个track的状态设为不跟踪,需要忽略.
那么就需要:
- 删除已经track的文件:
git rm -rf ./.vscode
- 提交删除的记录:
git commit -m 'delete ide config fie'
- 在gitnore文件里面加上对应的ignore
- 提交并推送到远程.
这样,针对已经commit的文件,忽略规则就生效了,当再有修改到这些文件的时候,也不会track.