Git 使用命令总结
git工具可以说是最近这段时间打交道最多的东西了。
除开常规的代码提交等命令,由于工作需要,我还需要写一些脚本工具,接触了更多的git命令。
补丁相关
1、自动给Android源码打入提供的安全补丁,输出多个安全补丁的打入结果等
给一个project打入安全补丁,首先需要提供安全补丁文件,并且通过git命令:
1 | git apply -p1 --directory=path xxx.patch |
当然,这只是最简单的,它还有许多参数,具体可以去看git的网页,我这里还会用到的是:
1 | --check |
这个是只检查这个patch是否可以打入这个仓库,而不真正的去做打入的动作
1 | --reverse |
反向应用补丁。可以用于判断这个补丁里面的代码是否已经存在
1 | -p1 |
这个的意义比较复杂,需要结合path文件来进行理解,可以看后面
1 | --directory= |
这个后面接的是一个路径,需要搭配-p1
来一起理解
当然,git也提供了另外一个命令去打入补丁:
1 | git am xxx.patch |
这个的参数和上面的apply也是大差不差的。这两个命令最主要的差别是,git apply命令是单纯的把补丁增减的内容应用在了代码文件中,修改的代码后续的git add 、git commit命令都是需要我们自己去做的。
git am命令就把上面这个流程全部都处理了。执行这个命令之后,这个patch修改的内容就会是一笔提交了。
patch文件的区别
上面有两种来打入补丁文件的命令,自然而然的就是有两种对应的补丁文件。补丁文件其实就是一个文本文件,它里面记录了那些变动的文件等。
一份patch文件可以通过命令:
1 | git diff commitId 1 commitId2 > xxx.patch |
注意这个顺序,是2次提交状态相对于1次提交状态的变化,这样生成的文件,是不包含的commit1的变更项的。
1 | git diff HEAD >xxx.patch |
把最新的一次提交修改生成为patch
通过 git diff命令生成的patch文件是不包含commit信息的,所以这也是为什么我们需要自己去做git add、git commit的原因。
1 | git format-patch HEAD 或者 git format-patch -1 |
这个命令也是用来生成补丁文件的,和上面的区别是,这个命令生成的补丁文件包含了作者、提交信息这些数据的,所以这个补丁文件通过git am命令打入后,直接可以生成一次提交。
还有一点,git diff命令生成的包含二进制数据(图片等)的patch打入后是错误的,也就是说git diff命令不支持二进制文件,只有git format-patch命令支持。
patch文件的结构
xxx(图)
我们可以看到,patch文件指明了修改的文件在仓库中的路径,打入时,git工具就会去解析这个路径,然后去这个路径下找需要修改的文件。
但是很多时候,别人的一个git 仓库和我们自己的git 仓库不是同一个仓库,例如我们可以把Android中的frameworks模块一整个作为一个git仓库,也可以把它路径里面的一些子路径作为一个个的仓库,这个时候,由于git仓库的层级不同,生成的patch里面包含的路径是不相同的。
同个文件修改项在不同层级的git仓库下生成的patch的路径图
这个时候,我们如何需要把子路径下的git仓库生成的patch应用到我们的里面,我们就需要用到之前说的-p1*和–directory=path* 这两个参数。
具体而言:xxxx
Git仓库状态以及一些参数获取命令
一个git仓库是有很多参数来表达的,最常见的例如:
1 | git branch |
显示当前我们这个仓库有那些分支,并且在当前的分支前会有一个*
符号
但是我们在写脚本的时候,不需要这种包含了很多信息的命令,我只想准确知道,当前是在哪个分支上,那么可以使用命令:
1 | git branch --show-current |
当然,这个命令需要的git版本好像是2.2,低版本使用不了(比如公司的服务器上的git版本好低)
和这个相同的一些命令如下:
1 | git rev-parse HEAD |
获取当前HEAD指针指向的commit id值
1 | git rev-parse --is-shallow-repository |
查看这个仓库是不是浅拷贝仓库。关于浅拷贝仓库:即使用命令:git clone xxx clone-depth=n下载下来的仓库,它只包含了最近的n笔提交记录,之前的提交记录都被省去了,这样的好处是降低了clone需要下载的数据量。但是这种仓库被认为是不完整的,是不能再被重新push到其他的远程仓库里
1 | git clean -fd |
删除本地git仓库中,没有添加到追踪项里的文件。
1 | git filter-branch -f -- --all |
去掉git仓库的grafted 标签。我们之前说浅拷贝仓库无法push到其他远程仓库,那么做这个判定的,就是这个标签,我们强制去除这个标签,使得我们的浅拷贝仓库也可以push到远程仓库,当然这会改变这个仓库的commit id值。git filter-branch这个命令十分的强大,它的作用是修改你这个仓库的所有提交记录,当你不想你之前的一个文件继续存在你的仓库里面,并且你想把它从你的整个提交历史中去除是,可以使用这个命令,它会修改所有的提交记录的sha值
git仓库的的状态
在git 仓库中,我们可以通过命令:
1 | git status |
来查看现在仓库处于什么状态。
我们常见的是用来查看我们修改了哪些文件、哪些文件通过git add命令追踪了,哪些可以commit了
但是git 仓库也存在一些特殊的状态
detached 状态
中文翻译为:游离态
经常使用repo命令来更新多个仓库的,可能对于这个状态比较熟悉,这个状态下,HEAD指针不是指在一个分支的最新的点,而是只在一个独立的commit id 上。我们可以通过命令:
1 | git checkout commit id |
来使得切换到detached状态。这只是一个临时状态,我们如果再切换到其他分支,那么这个状态就失去了。如果我们想保留当前的这个commit id状态下的仓库,我们可以在这个状态下,创建新的分支:
1 | git checkout -b new_branch |
没有分支的状态
这个状态,应该是才把仓库从远端clone下来,这时,我们需要的是创建第一个本地分支。
孤儿分支(orphan branch)
1 | git branch --orphan branch-name |
当我们在一个仓库里面(本地)创建一个孤儿分支,这个分支是没有任何提交记录的,我们可以任意选择仓库里面的某些文件,加入到追踪项里,然后把这些文件作为一次提交。