配置
git config
选项:
- –system:当前系统所有用户;
- –global:当前用户所有仓库;
- –list:查看所有配置
- 无:当前仓库
参数:
- 用户信息:user.name/user.email配置姓名和邮箱;
- 颜色:color配置主题
如果只传参数名不传值,表示查看该参数的配置信息。
帮助
帮助有两个命令:1
2git help <command>
git <command> --help
克隆
git clone
参数:
- 第一个参数是远程仓库的url
- 第二个参数是本地仓库的自定义名称,可省略。
文件状态
git中的文件状态有
- 未跟踪:之前的版本库或暂存区中没有该文件快照;
- 已暂存未修改:处于暂存区中;
- 已修改未暂存:跟踪过但本次修改未被暂存的文件;
- 已修改并暂存:处于暂存区中的被修改文件
状态间跳转如图所示:
查看状态
git status
选项:
- –short:简略版状态(1–??,2–A,3– M,4–M ),M出现在左侧表示被修改并暂存,出现在右侧表示已修改未暂存,同时出现2个M表示修改暂存后又被修改。
文件比较
git diff
用途:
- 获取没有被暂存的更新文件差异
- 获取没有被提交的更新文件差异
参数:
- 不加参数:处理用途一;
- –staged:处理用途二;
- –check:检测空白符错误。
暂存
git add
暂存指定文件或目录
选项:
- -i:进入交互式add界面,可以选择暂存某些文件。
提交到仓库
git commit
选项:
- 无:打开编辑器,如vi,输入提交信息;
- -m:输入提交信息;
- -a:将所有已修改未暂存的文件都提交,省去了git add。相当于
git add .
。
删除文件
git rm
当删除一个文件后,使用git rm <文件名>
来将文件保存到暂存区。也可以使用git add
,但是不建议,语义不好。
选项:
- -f:强制删除已经修改过并暂存的文件。
- –cached:删除暂存区中的文件,但保留工作区中的该文件。
修改文件名
git mv
相当于:1
2
3mv <old file> <new file>
git rm <old file>
git add <new file>
运行git status:1
renamed: <old name> -> <new name>
查看日志
git log
选项:
- -p:显示每次提交的内容差异;
- -n:n是一个数字,用来显示最后n条提交记录。如-2表示显示最后两条记录;
–stat:显示每次提交的简略信息,如被修改的文件数以及修改的具体行数。类似于:
1
2
3
4README | 6 ++++++
Rakefile | 23 +++++++++++++++++++++++
lib/simplegit.rb | 25 +++++++++++++++++++++++++
3 files changed, 54 insertions(+)–pretty:这个选项有许多值让你选择来显示log的格式,如oneline:
1
2
3
4$ git log --pretty=oneline
ca82a6dff817ec66f44342007202690a93763949 changed the version number
085bb3bcb608e1e8451d4b2432f8ecbe6306e7e7 removed unnecessary test
a11bef06a3f659402fe7563abf99ad00de2209e6 first commitlog将在一行中显示。此外还有short、full和fuller。
最重要的值应该是format。使用时格式如下:1
git log --pretty=format:"%h - %an,%ar:%s"
命令中的占位符说明如下:
选项|说明
–|–
%H|提交对象(commit)的完整哈希字串
%h|提交对象的简短哈希字串
%T|树对象(tree)的完整哈希字串
%t|树对象的简短哈希字串
%P|父对象(parent)的完整哈希字串
%p|父对象的简短哈希字串
%an|作者(author)的名字
%ae|作者的电子邮件地址
%ad|作者修订日期(可以用 –date= 选项定制格式)
%ar|作者修订日期,按多久以前的方式显示
%cn|提交者(committer)的名字
%ce|提交者的电子邮件地址
%cd|提交日期
%cr|提交日期,按多久以前的方式显示
%s|提交说明–graph:图形化提交历史,可以与–pretty结合显示美观的log。
其他常用格式选项:
选项|说明
–|–
–stat|显示每次更新的文件修改统计信息。
–shortstat|只显示 –stat 中最后的行数修改添加移除统计。
–name-only|仅在提交信息后显示已修改的文件清单。
–name-status|显示新增、修改、删除的文件清单。
–abbrev-commit|仅显示 SHA-1 的前几个字符,而非所有的 40 个字符。
–relative-date|使用较短的相对时间显示(比如,“2 weeks ago”)。限制输出选项:
选项|说明
–|–
–since|从某个时间起,比如--since=2.weeks
或--since=2008-01-15
。
–until|到某个时间为止,格式与–since相似。
–author|指定作者
–grep|搜索提交说明中的关键字
–all-match|相当于选项的与操作
-S|显示对某个关键字符串进行修改的提交–decorate:查看当前所有分支指向的commit对象。
撤销操作
git commit –amend
合并缓存区的修改和最近的一次commit, 然后用生成的新的commit替换掉老的. 如果缓存区没有内容, 那么利用amend可以修改上一次commit的描述.1
2
3
4
5
6
7# Edit hello.py and main.py
git add hello.py
git commit
# Realize you forgot to add the changes from main.py
git add main.py
git commit --amend --no-edit
–no-edit能让我们修复commit,而且不要修改commit描述。
远程仓库
git remote
选项:
- -v:显示远程仓库的url;
- add
:新增远程仓库。
远程仓库抓取
git fetch
将指定名称的远程仓库数据全部拉取到本地,包括所有的分支。
git pull
将远程仓库的最新版本拉取到本地分支。
选项:
- –allow-unrelated-histories:将两个没有相关历史的仓库合并。比如你在github上建立了一个仓库,编辑了一些内容。然后又在本地有一个仓库,编辑了一些内容。当你pull时会被告知
fatal: refusing to merge unrelated histories
。这时,加上这个选项就可以了。
两者最主要的区别在于fetch不会自动合并,而pull在拉取后会自动合并分支。相比较而已,fetch更安全一些,可以避免冲突。
相当于pull=fetch+merge。
推送
git push
推送本地提交到远程仓库。如果有多人同时提交,其中一些会被拒绝,直到合并他人的推送。
选项:
- –delete:删除远程某个指定分支
查看远程信息
git remote show
可以获取本地当前工作分支和远程所有分支等信息。
本地重命名远程仓库
git rename
将本地的远程别名修改为新名。
删除本地克隆的仓库
git rm
标签
git tag
显示所有标签。
选项:
- -l:
git tag -l <正则匹配>
可以列出匹配到的所有tag - -d:删除指定标签
打标签
标签一般默认打在最新的commit上。
附注标签
git tag -a
-m -s
这种标签被称为附注标签,拥有tag的所有信息。如果使用git show <tag-name>
命令可以看到该标签与相应提交的信息。推荐使用这种标签。
轻量标签
轻量标签只需要提供标签名称即可:
git tag
指定commit打标签
git tag -a
推送标签
git push
或是 git push –tags
删除远程标签
git push
:refs/tags/
分支
首先要讲一下Git的文件对象:blob对象、tree对象和commit对象。每个blob对象代表一个文件;tree对象代表一个目录,保存指向该目录下所有blob对象的指针;commit对象是指向每次提交的对象,而分支,比如master就是一个指向最新commit对象的指针。每一个commit对象保存一个指向上一个commit对象的指针,类似于链表的头插法。
HEAD指针是一个指向当前分支的指针,切换分支就是修改HEAD的值。
创建分支
git branch
创建分支就是创建一个新的指针。
选项:
- 无参数:显示所有分支,当前分支前有一个*号;
- -v:显示所有分支及其最后一次commit记录;
- –merged:显示所有已合并到当前分支的子分支;
- –no-merged:显示所有未合并到当前分支的子分支;
- -d:删除某分支,该分支必须已经被合并到当前分支;
- -D:强制删除分支,即使该分支中有未合并的内容;
切换分支
git checkout
选项:
- -b:创建并切换到新分支。如果要基于一个远程分支来创建本地分支,可以使用
git checkout -b <local-branch> <remote-name>/<branch-name>
命令。 - –track:
git checkout --track <remote-name>/<branch-name>
追踪一个远程分支,相当于-b选项的简写。 - –vv:列出所有分支与其跟踪的远程分支的落后或超前情况。
合并分支
git merge
流程:
git checkout -b dev
创建开发分支;- 修改需要处理的文件;
git commit -a
提交代码;git checkout master
切换到主分支;git merge dev
将dev分支合并到主分支。
上面如果没有冲突,将使用fast forward模式快速合并。也就是说,从master可以直接跳到dev分支时,只需要修改master指针等于dev指针即可。
问题:
- 如果新建dev分支后,又从master中新建一个issue分支,并且先合并了issue分支。那么再合并dev分支时,将自动选择master和dev分支的最优共同祖先进行合并。这时将不能使用fast forward模式。
- 如果产生冲突:
- 先解决冲突:使用git mergetool图形化工具或手动修改文件即可;
- 再提交代码。
变基
git rebase
变基与合并的作用类似,都是为了将两个分支的修改合并起来。变基是以某一分支为基础,将另一个分支的修改应用在这个分支上,再在基础分支上执行git merge
合并操作。
但是在提交历史中,不像merge有分叉口,相反,会表现成一条直线。
选项:
- –continue:如果变基过程中出现了冲突,在解决冲突后调用
git rebase --continue
继续执行变基操作。 - –skip:跳过冲突文件。
- –onto:
git rebase --onto master server client
表示取出 client 分支,找出处于 client 分支和 server 分支的共同祖先【之后的修改】,然后把它们在 master 分支上重放一遍。 - -i:交互式变基,能够修改多个提交信息。
注意:不要对别人仓库中也存在的分支进行变基操作。所以,建议的做法是:只对尚未推送或未分享给别人的本地修改执行变基操作清理历史,从不对已推送至别处的提交执行变基操作。
引用日志
git reflog
引用日志记录了最近几个月你的 HEAD 和分支引用所指向的历史。每当你的 HEAD 所指向的位置发生了变化,Git 就会将这个信息存储到引用日志这个历史记录里。
指针向前遍历
第n父分支
^
pointer是一次提交的SHA值或分支名或HEAD,n代表第n个父提交。n只在merge或show命令时有效。1
2
3
4
5
6
7
8
9* b712a16 merge f
|\
| * ed1f93f test
* e0ba82a test.txt
$ git show b712a16^
e0ba82a test.txt//第一父提交
$ git show b712a16^2
ed1f93f test//第二父提交
第n祖先
~
指定指针的前第n个commit对象,相当于<pointer>^^^^^^...
。如果有多个父分支,取第一个分支。
分支间的提交差集
双点
git show
..
使用..
可以获取<origin-branch>
上没有而<target-branch>
上有的提交记录。
三点
git show <1st-branch>…<2nd-branch>2nd-branch>1st-branch>
使用...
能够获取【两个分支的并集】与【两个分支的交集】的【差集】。
选项:
- –left-right:显示差集中每个元素所属分支方向。
多点
git show
–not
或
git show ^
分支前使用^
或--not
表示剔除<origin-branch>
中有的分支。与双点类似,但是可以处理两个及多个分支情况。
存储工作区和暂存区文件
把本地的项目文件夹想象成一个工作区,暂存区是一个盒子,Git本地仓库是另一个盒子。工作区和暂存区、仓库都是唯一的,不管创建了多少个分支,这三个区域都是共享的。
那么,想象一下,当前分支还没开发完成时,需要新建一个分支去处理bug。但是你并不想提交当前尚未完成的文件。那么,就需要将当前的工作区和暂存区存储起来,然后在切换分支修复bug。
git stash
存储当前所有【已跟踪的】文件到一个栈中。执行之后,工作区会回到上一次提交后的状态。相当于git checkout HEAD
。
选项:
- –index:应用存储时,保留所有状态:暂存的仍暂存,修改的仍修改。如果不加这个参数,原先暂存的修改被存储后,再应用时将不在暂存区。
- –keep-index:跟在
git stash
后面,表示不要存储暂存区里的文件,仅存储工作区文件。 - –include-untracked:将未跟踪的文件也存储起来。
- -u:同上。
- –all:存储所有文件。
参数:
- list:查询存储栈中所有stash;
- apply stash@{n}:应用栈中第n个存储,但应用后不会从栈中移除该存储。n从0开始;
- drop stash@{n}:移除栈中指定存储;
- pop stash@{n}:应用某个存储并从栈中移除它。
- branch
: 创建一个新分支,检出储藏工作时所在的提交,重新在那应用工作,然后在应用成功后扔掉储藏
清理文件
git clean
除了rm选项,还可以使用clean命令来删除未跟踪的,且不在【.gitignore】中的文件。
选项:
- -n:列出所有可以被清理的文件;
- -f:强制删除所有未跟踪文件;
- -d:可以删除未跟踪的目录;
git reset --hard
和git clean -f
是一对好基友。 结合使用他们能让你的工作目录完全回退到最近一次commit的时候。
查找
git grep
查找正则匹配到的字符。
选项:
- -n:匹配到的字符串所在行号;
- –count:文件内符合匹配的个数;
重置
git reset
重置HEAD指针到某个历史commit对象。
选项:
- –soft:仅回退HEAD指针,不回退工作区和暂存区。
- –mixed:回退HEAD指针,并且将回退后的文件内容覆盖暂存区内容。
- –hard:回退HEAD指针,并且覆盖暂存区和工作区。
相比较与checkout而言,reset会影响到工作区的文件,而checkout会单独开一个分支,将回退后的HEAD指针指向这个分支。所以checkout会比较安全。
打包
git bundle
在断网情况下,可以使用bundle命令将要push的文件都打包起来,然后将该包用其他方式交给其他用户解压。
Git的优点
- 分布式:每个成员都可以在本地电脑上修改、提交代码;
- 无需互联网:即使没有网络,项目成员依然能够开发自己的功能。等到网络条件较好时再合并。
- 分支的创建与切换十分方便:Git的文件都以对象保存,每次创建分支都是新建一个指向最新代码的指针,而切换分支也是改变HEAD指针的指向。相比较于SVN等版本控制系统每次创建分支都要复制所有代码,Git实在是太方便了。