Git 指令记录

配置

git config

选项:

  1. –system:当前系统所有用户;
  2. –global:当前用户所有仓库;
  3. –list:查看所有配置
  4. 无:当前仓库

参数:

  1. 用户信息:user.name/user.email配置姓名和邮箱;
  2. 颜色:color配置主题

如果只传参数名不传值,表示查看该参数的配置信息。

帮助

帮助有两个命令:

1
2
git help <command>
git <command> --help

克隆

git clone

参数:

  1. 第一个参数是远程仓库的url
  2. 第二个参数是本地仓库的自定义名称,可省略。

文件状态

git中的文件状态有

  1. 未跟踪:之前的版本库或暂存区中没有该文件快照;
  2. 已暂存未修改:处于暂存区中;
  3. 已修改未暂存:跟踪过但本次修改未被暂存的文件;
  4. 已修改并暂存:处于暂存区中的被修改文件

状态间跳转如图所示:
状态图

查看状态

git status

选项:

  1. –short:简略版状态(1–??,2–A,3– M,4–M ),M出现在左侧表示被修改并暂存,出现在右侧表示已修改未暂存,同时出现2个M表示修改暂存后又被修改。

文件比较

git diff

用途:

  1. 获取没有被暂存的更新文件差异
  2. 获取没有被提交的更新文件差异

参数:

  1. 不加参数:处理用途一;
  2. –staged:处理用途二;
  3. –check:检测空白符错误。

暂存

git add

暂存指定文件或目录

选项:

  1. -i:进入交互式add界面,可以选择暂存某些文件。

提交到仓库

git commit

选项:

  1. 无:打开编辑器,如vi,输入提交信息;
  2. -m:输入提交信息;
  3. -a:将所有已修改未暂存的文件都提交,省去了git add。相当于git add .

删除文件

git rm

当删除一个文件后,使用git rm <文件名>来将文件保存到暂存区。也可以使用git add,但是不建议,语义不好。

选项:

  1. -f:强制删除已经修改过并暂存的文件。
  2. –cached:删除暂存区中的文件,但保留工作区中的该文件。

修改文件名

git mv

相当于:

1
2
3
mv <old file> <new file>
git rm <old file>
git add <new file>

运行git status:

1
renamed:    <old name> -> <new name>

查看日志

git log

选项:

  1. -p:显示每次提交的内容差异;
  2. -n:n是一个数字,用来显示最后n条提交记录。如-2表示显示最后两条记录;
  3. –stat:显示每次提交的简略信息,如被修改的文件数以及修改的具体行数。类似于:

    1
    2
    3
    4
    README           |  6 ++++++
    Rakefile | 23 +++++++++++++++++++++++
    lib/simplegit.rb | 25 +++++++++++++++++++++++++
    3 files changed, 54 insertions(+)
  4. –pretty:这个选项有许多值让你选择来显示log的格式,如oneline:

    1
    2
    3
    4
    $ git log --pretty=oneline
    ca82a6dff817ec66f44342007202690a93763949 changed the version number
    085bb3bcb608e1e8451d4b2432f8ecbe6306e7e7 removed unnecessary test
    a11bef06a3f659402fe7563abf99ad00de2209e6 first commit

    log将在一行中显示。此外还有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|提交说明

  5. –graph:图形化提交历史,可以与–pretty结合显示美观的log。

  6. 其他常用格式选项:

    选项|说明
    –|–
    –stat|显示每次更新的文件修改统计信息。
    –shortstat|只显示 –stat 中最后的行数修改添加移除统计。
    –name-only|仅在提交信息后显示已修改的文件清单。
    –name-status|显示新增、修改、删除的文件清单。
    –abbrev-commit|仅显示 SHA-1 的前几个字符,而非所有的 40 个字符。
    –relative-date|使用较短的相对时间显示(比如,“2 weeks ago”)。

  7. 限制输出选项:

    选项|说明
    –|–
    –since|从某个时间起,比如--since=2.weeks--since=2008-01-15
    –until|到某个时间为止,格式与–since相似。
    –author|指定作者
    –grep|搜索提交说明中的关键字
    –all-match|相当于选项的与操作
    -S|显示对某个关键字符串进行修改的提交

  8. –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

选项:

  1. -v:显示远程仓库的url;
  2. add :新增远程仓库。

远程仓库抓取

git fetch

将指定名称的远程仓库数据全部拉取到本地,包括所有的分支。

git pull

将远程仓库的最新版本拉取到本地分支。

选项:

  1. –allow-unrelated-histories:将两个没有相关历史的仓库合并。比如你在github上建立了一个仓库,编辑了一些内容。然后又在本地有一个仓库,编辑了一些内容。当你pull时会被告知fatal: refusing to merge unrelated histories。这时,加上这个选项就可以了。

两者最主要的区别在于fetch不会自动合并,而pull在拉取后会自动合并分支。相比较而已,fetch更安全一些,可以避免冲突。

相当于pull=fetch+merge。

推送

git push

推送本地提交到远程仓库。如果有多人同时提交,其中一些会被拒绝,直到合并他人的推送。

选项:

  1. –delete:删除远程某个指定分支

查看远程信息

git remote show
可以获取本地当前工作分支和远程所有分支等信息。

本地重命名远程仓库

git rename

将本地的远程别名修改为新名。

删除本地克隆的仓库

git rm

标签

git tag

显示所有标签。

选项:

  1. -l:git tag -l <正则匹配>可以列出匹配到的所有tag
  2. -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

创建分支就是创建一个新的指针。

选项:

  1. 无参数:显示所有分支,当前分支前有一个*号;
  2. -v:显示所有分支及其最后一次commit记录;
  3. –merged:显示所有已合并到当前分支的子分支;
  4. –no-merged:显示所有未合并到当前分支的子分支;
  5. -d:删除某分支,该分支必须已经被合并到当前分支;
  6. -D:强制删除分支,即使该分支中有未合并的内容;

切换分支

git checkout

选项:

  1. -b:创建并切换到新分支。如果要基于一个远程分支来创建本地分支,可以使用git checkout -b <local-branch> <remote-name>/<branch-name>命令。
  2. –track:git checkout --track <remote-name>/<branch-name>追踪一个远程分支,相当于-b选项的简写。
  3. –vv:列出所有分支与其跟踪的远程分支的落后或超前情况。

合并分支

git merge

流程:

  1. git checkout -b dev创建开发分支;
  2. 修改需要处理的文件;
  3. git commit -a提交代码;
  4. git checkout master切换到主分支;
  5. git merge dev将dev分支合并到主分支。
    上面如果没有冲突,将使用fast forward模式快速合并。也就是说,从master可以直接跳到dev分支时,只需要修改master指针等于dev指针即可。

问题:

  1. 如果新建dev分支后,又从master中新建一个issue分支,并且先合并了issue分支。那么再合并dev分支时,将自动选择master和dev分支的最优共同祖先进行合并。这时将不能使用fast forward模式。
  2. 如果产生冲突:
    • 先解决冲突:使用git mergetool图形化工具或手动修改文件即可;
    • 再提交代码。

变基

git rebase

变基与合并的作用类似,都是为了将两个分支的修改合并起来。变基是以某一分支为基础,将另一个分支的修改应用在这个分支上,再在基础分支上执行git merge合并操作。

但是在提交历史中,不像merge有分叉口,相反,会表现成一条直线。

选项:

  1. –continue:如果变基过程中出现了冲突,在解决冲突后调用git rebase --continue继续执行变基操作。
  2. –skip:跳过冲突文件。
  3. –onto:git rebase --onto master server client表示取出 client 分支,找出处于 client 分支和 server 分支的共同祖先【之后的修改】,然后把它们在 master 分支上重放一遍。
  4. -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>

使用...能够获取【两个分支的并集】与【两个分支的交集】的【差集】。

选项:

  1. –left-right:显示差集中每个元素所属分支方向。

多点

git show –not

git show ^

分支前使用^--not表示剔除<origin-branch>中有的分支。与双点类似,但是可以处理两个及多个分支情况。

存储工作区和暂存区文件

把本地的项目文件夹想象成一个工作区,暂存区是一个盒子,Git本地仓库是另一个盒子。工作区和暂存区、仓库都是唯一的,不管创建了多少个分支,这三个区域都是共享的。

那么,想象一下,当前分支还没开发完成时,需要新建一个分支去处理bug。但是你并不想提交当前尚未完成的文件。那么,就需要将当前的工作区和暂存区存储起来,然后在切换分支修复bug。

git stash

存储当前所有【已跟踪的】文件到一个栈中。执行之后,工作区会回到上一次提交后的状态。相当于git checkout HEAD

选项:

  1. –index:应用存储时,保留所有状态:暂存的仍暂存,修改的仍修改。如果不加这个参数,原先暂存的修改被存储后,再应用时将不在暂存区。
  2. –keep-index:跟在git stash后面,表示不要存储暂存区里的文件,仅存储工作区文件。
  3. –include-untracked:将未跟踪的文件也存储起来。
  4. -u:同上。
  5. –all:存储所有文件。

参数:

  1. list:查询存储栈中所有stash;
  2. apply stash@{n}:应用栈中第n个存储,但应用后不会从栈中移除该存储。n从0开始;
  3. drop stash@{n}:移除栈中指定存储;
  4. pop stash@{n}:应用某个存储并从栈中移除它。
  5. branch : 创建一个新分支,检出储藏工作时所在的提交,重新在那应用工作,然后在应用成功后扔掉储藏

清理文件

git clean

除了rm选项,还可以使用clean命令来删除未跟踪的,且不在【.gitignore】中的文件。

选项:

  1. -n:列出所有可以被清理的文件;
  2. -f:强制删除所有未跟踪文件;
  3. -d:可以删除未跟踪的目录;

git reset --hardgit clean -f是一对好基友。 结合使用他们能让你的工作目录完全回退到最近一次commit的时候。

查找

git grep

查找正则匹配到的字符。

选项:

  1. -n:匹配到的字符串所在行号;
  2. –count:文件内符合匹配的个数;

重置

git reset

重置HEAD指针到某个历史commit对象。

选项:

  1. –soft:仅回退HEAD指针,不回退工作区和暂存区。
  2. –mixed:回退HEAD指针,并且将回退后的文件内容覆盖暂存区内容。
  3. –hard:回退HEAD指针,并且覆盖暂存区和工作区。

相比较与checkout而言,reset会影响到工作区的文件,而checkout会单独开一个分支,将回退后的HEAD指针指向这个分支。所以checkout会比较安全。

打包

git bundle

在断网情况下,可以使用bundle命令将要push的文件都打包起来,然后将该包用其他方式交给其他用户解压。

Git的优点

  1. 分布式:每个成员都可以在本地电脑上修改、提交代码;
  2. 无需互联网:即使没有网络,项目成员依然能够开发自己的功能。等到网络条件较好时再合并。
  3. 分支的创建与切换十分方便:Git的文件都以对象保存,每次创建分支都是新建一个指向最新代码的指针,而切换分支也是改变HEAD指针的指向。相比较于SVN等版本控制系统每次创建分支都要复制所有代码,Git实在是太方便了。