1 git配置文件
1.1 git权限控制
git有三个不同的权限控制文件,高优先权的设置会覆盖低优先权的设置项,以下按照优先权从高到低介绍:
- 文件夹中”.git” 子文件夹中的confiig文件,这个配置具有最高优先权,但是这个配置文件只对他所在的文档有效。
- 登录账的home directory中的.gitconfig文件。这个配置文件只对此登陆账号有效。
- git程序按照目录中的etc/gitconfig文件。
只有在前两个配置文件中没有设置的项这个配置传文件才会生效。这是公用的配置传文件,它对所有登录账号和所有git文档库都有效。
1.2 git config 指令的用法
要显示当前git的设置可以执行下面的指令:
git config -l
这个指令会显示三个配置文件中的所有设置项。他的顺序是先显示优先权最低的设置然后再显示高的。
当然我们也可以设置指定显示单一配置文件的内容:
git config --system -l #显示git安装目录中的etc/gitconfig的设置
git config --global -l #显示登录账号 home directory 中的.gitconfig文件的配置
我们可以在配置文件中增加配置项,比如在执行”git commit” 的时候会提示你输入操作者的姓名和email,我们可以通过配置文件来设置以后就不用再输入,如果要记录在文档库中的配置文件,可以使用如下命令:
git config user.name 'your name'
git config user.email 'your email'
如果要记录在登录账号的home directory中的.gitconfig文件内可以使用如下指令:
git config --global user.name 'your name'
git config --global user.email 'your email'
如果要记录在git安装目录etc/gitconfig内可以执行如下指令:
git config --system user.name 'your name'
git config --system user.email 'your email'
如果要删除配置传文件中的配置项可以使用“–unset”命令:
git config --unset user.name
如果要删除的是其他配置文件中的设置项,则视情况加入”–global”或者”system”选项。
补充说明:git指令的长和短
我们会发现有的指令使用一个连字符比如:”-m”有的却是两个,比如:”–author”,这是为啥呢。
其实使用一个连字符是简单表达形式的意思。我们也可以把它换成完整形式。比如”git commit -m ‘comment’”的完整形式是”git commit –message=’comment’”。”git config –list”的完整形式是”git config –list”。
2 把git文件存入仓库
2.1 排除不需要加入文档库的文件
我们在上传文件到git仓库的时候并不能保证所有上传的文件都是我们需要的,比如编译器编译的文件以及一些资源文件,那么如何保证不把这些文件上传到git仓库呢。git为我们提供了一个文件:.gitignore。我们把需要忽略的文件一一列在这里即可。
比如我们不想上传.txt为结尾的文件到仓库,那么在.gitignore文件中写入”.txt”即可。.gitignore文件可以使用“#”表示注释,文件夹路径使用“/”,文件名可以使用通配符”*”。使用”!”表示排除。比如以下设置表示排除所有txt文件但是不包含note.txt 文件。
*.txt
!note.txt
2.2 控制commit
我们知道在本地仓库修改完文件之后提交仓库有两个步骤:
git add #提交修改文件到git索引
git commit #从本地git索引推到git仓库
但是如果我们在执行git add之后反悔了怎么办呢。这时候我们的分两种情况采取以下操作:
文档库中还没有任何文件,即执行”git init”之后没有执行过”git commit”:
使用git rm --cached 文件名
文档库中已经有文件,即我们已经执行过”git commit”命令:
git reset HEAD 文件名
2.3 查看commit节点
git #启动图形查看模式
除了使用gitk查看commit节点信息,也可以使用”git log”命令达到同样目的。如果再加上”–graph”选项,会使用文本模式排列出commit节点的演进图。
显示最近一次代码提交记录:
git show head
3 比较文件的差异和从git文档库取回文件
3.1 取出指定文件
git checkout commit 节点标识符或标签 文件名1 文件名2 #从文档库的任何一个节点取出指定文件
Tips:
文件夹中的文件会被取出的文件覆盖
注意:
如果执行 git checkout 的文件与当前库中最新commit的文件内容不同,那么这个文件会自动记录在git索引中。稍后如果我们执行了git commit命令,那么这个取出的文件会成为新的版本被存入仓库中。为了避免这种情况的发生我们在执行git checkout之后立刻执行”git reset head”命令清除git索引。
3.2 使用git mv命令改变文件或文件夹名字
git mv 原来的文件名 新文件名
4 获取git文档库的统计数据
4.1 git log 指令
这个指令会按照时间顺序从最近一次的commit接单开始往前列出每一次commit的数据,包括标识符、执行人、日期以及说明。该指令后面可以接参数,比如:–author=’A’,即只列出提交人为A的提交记录。
指定显示某位提交者的提交信息:
git log --author='A'
指定显示某一段时间内的提交信息:
$ git log --after='2017-10-01 00:00:00' --before='2017-11-01 00:00:00'
after表示指定的日期之后,before表示指定的日期之前,注意使用方式!
以上指令只会显示指定日期期间的commit,如果加上”–stat”,或者”–numstat”或者”–shortstat”还可以显示每一个commit变更的情况。
比如我们执行:
git log shortstat
可以看到会显示该次提交变更的基本信息。
Tips:
如果git指令显示的信息炒过了屏幕大小,屏幕会自动暂停,这时候可以使用如下按键继续操作:
- 按键 j 表示显示下一行;
- 空格表示显示下一页;
- 按键 h 表示显示操作说明;
- 按键 q 表示结束。
4.2 git shortlog指令
这个指令会按照名字的字母顺序,列出每一个人执行commit的次数和说明。
我们也可以按照commit的次数从高到低排列,只要加上”–commit”或者是使用缩写:”-n” 即可。如果不需要显示commit说明可以再加上”–summary”或者是使用缩写:”-s”。
git shortlog -n -s
4.3 git ls-files 指令
这个指令会列出当前git文档库中的文件列表:
我们也可以搭配”xargs”和”wc”这两个指令来计算程序中的代码行数:
git ls-files | xargs wc -l
前面的数字就是该文件中的代码行数,如果你要计算行数总和可以使用如下指令:
git ls-files | xargs cat | wc -l
5 建立分支和解决冲突
5.1 创立分支
创立分支使用git branch 指令:
git branch <new branch name> commit <节点标识符或者是标签>
这个指令会根据后边参数的不同发挥不同的作用:
- 如果最后指定了commit节点标识符或者是标签就会从该节点开始的位置长出分支,即该节点之前提交的代码新分支都有,之后的代码新分支是没有的。如果没有指定commit标签那么默认是从最新节点的位置创立分支。
- “git branch” 指令后面没有任何参数的时候会列出当前文档库中正在开发的所有分支。
建立分支之后可以使用”git checkout <分支名>” 这个指令来切换当前操作的分支。
5.2 删除分支
删除分支我们要注意的是在删除当前分支之前必须先切换到另外的分支,不然不能删除当前分支,删除分支使用如下指令:
git branch -d <要删除的分支>
使用该命令需要保证要删除的分支已经合并到别的分支过,不然会报错
值得注意的是:
我们知道如果我们新建了一个分支一般都是为了方便多人协作,开发者分别在自己的dev分支上开发然后合并到master,上面这个命令有些反人类,如果当前要删除的分支没有合并到另一个分支,使用上面的命令会报错。需要把”-d”换成”-D”。
5.3 修改分支名
修改分支名需要注意的是你必须的先切换到要修改的分支之后才能操作:
git branch -m <新的分支出名>
5.4 合并分支
合并分支使用如下命令:
git merge 分支名
该命令会把指定的分支合并到当前分支。比如当前在master分支,想把A分支的代码合并到master使用命令:
git merge A
即可。
如果合并之后你后悔了,想撤回可以使用”git reset”命令。我们想恢复到合并之前的状态执行如下操作:
git reset --hard HEAD^
“–hard” 选项表示文件夹中的文件也要一起恢复。
5.5 解决冲突
我们先来想一下什么情况会发生冲突:
- 假如有个一master分支,你在master节点的最新节点新建了一个分支branch1;
- 然后你在branch1分支上新增了一个文件:1.txt,修改了一个文件:test.txt;
- 在你准备合并branch1到master之前,你的工友小B合并了他的分支branch2到master,新增了4个文件,也修改了test.txt文件;
然而你并不知情,你也提交了你的分支到master,这时候系统会告诉你你合并不了,因为检测目前的master和你当时新建分支branch1的时候从master最新节点上得到的那一版不一样,这个时候就代表你发生冲突了,需要手动合并。
git checkout master
git merge branch1
然后就会提示代码冲突了。
一般冲突的部分会用:
<<<<<<<HEAD
冲突内容
=======
>>>>>>>draft
来表示,所以需要你手动的去合并冲突,解决完了冲突之后执行如下指令提交代码:
git diff
执行完成如果没有报错说明已经解决冲突。之后我们可以执行如下指令把我们的代码提交到master分支:
git add .
git commit -m '合并branch1到master'
6 使用Rebase指令更新分支的起始点
之前我们说的合并分支的时候都在说这样的情况:
- 有主分支master,我们在master的最新节点上创建了新分支AAA。
- 我们在AAA分支上做了更新,然后推送到master节点与master节点合并。
那么现在我们要说的是另一种情况:
- 有主分支master,我们在master的最新节点上创建了新分支AAA;
- 我们一直在AAA分支上做开发,这个过程的持续很久;
- 在AAA上做开发的过程中,别的程序员也在master的最新节点上创建了新的分支BBB,他开发完成很快就提交代码到master;
- 这个时候你在AAA分支上开发,为了保证代码的实效性,你必须的拉master的最新代码到你这里。
见下图:
我们执行如下命令将master合并到AAA:
# git checkout AAA
# git merge master
执行合并以后可能master会继续有更新,而我们的AAA分支也一直在开发,那么我们的节点图可能一直跟上图这样不停的交叉,到最后可能会看起来越来越复杂。当然这样并没有错,只是看起来不是那么简洁。我们可以用另一种方式让我们的节点图看起来更加简洁和直观:用rebase指令取代merge指令。
rebase指令的功能和merge一样,但是他在节点的处理上略有不同,我们用一个图来说明:
这幅图我们对比上一幅可以看出:
rebase指令执行的合并会把以前从commit节点长出来的分支AAA合并到master的最新节点,然后从master的最新节点长出来。但是master和AAA节点的代码其实还是各自不同,AAA包含master的所有代码,master不包含AAA从master最新节点”长出来”之后的代码。图虽然不同,但是功能没有任何区别。
通过上面这两幅图大家是不是更加清楚这两个指定的区别。下面我们来说一下rebase指令的用法。
使用rebase很简单,就把以前使用merge的地方换成rebase即可:
# git checkout AAA
# git rebase master
与merge一样rebase也会面临发生冲突的情况,你可以使用上面提供的方法手动修改冲突然后执行 “git diff” 检测是否修改完成所有的冲突,最后提交合并。
假如你在使用rebase提交合并的时候发生冲突,这时候你决定取消合并,你可以执行如下命令:
# git rebase --abort
执行如上命令一定是在还没有完成rebase之前,如果你提交合并成功了执行上述命令是不生效的。
接下来我们说如果执行rebase完全没有错误但是你又反悔了该如何操作。
如果是上述情况,我们可以使用”git reset”命令来恢复,但是有一个条件是:我们必须先找到执行rebase指令之前head所在的commit节点。我们知道head表示当前工作分支的最新commit节点,那我们如何找到历史的那个head节点呢?
git提供了一个指令:
# git reflog head或者是任何分支的分支名
我们可以使用这个指令查询head或是任何分支的变动情况。该命令得出的结果是按照时间倒序排列。