三个工做区域:git
git 中文件的状态:github
三个配置文件:正则表达式
每个级别覆盖上一级别的配置,因此 .git/config 的配置变量会覆盖 /etc/gitconfig 中的配置变量。算法
git config --list : 检查当前应用的配置信息 git config <key> :来检查 Git 的某一项配置
$ git help <verb> $ git <verb> --help $ man git-<verb>
在学习完本章以后,你应该可以配置并初始化一个仓库(repository)、开始或中止跟踪 (track)文件、暂存(stage)或提交(commit)更改。本章也将向你演示如何配置 Git 来忽略指定的文件和文 件模式、如何迅速而简单地撤销错误操做、如何浏览你的项目的历史版本以及不一样提交(commits)间的差别、 如何向你的远程仓库推送(push)以及如何从你的远程仓库拉取(pull)文件。shell
git init #该命令将建立一个名为 .git 的子目录,这个子目录含有你初始化的 Git 仓库中全部的必须文件, #这些文件是Git仓库的骨干。可是,在这个时候,咱们仅仅是作了一个初始化的操做,你的项目里的文件尚未被跟踪。
git clone [url] # 当你执行 git clone 命令的时候,默认配置下远程 Git 仓库中的每个文件的每个版本都将被拉取下来。
好比,要克隆 Git 的可连接库 libgit2,能够用下面的命令:数据库
$ git clone https://github.com/libgit2/libgit2
说明:这会在当前目录下建立一个名为 “libgit2” 的目录,并在这个目录下初始化一个 .git 文件夹,从远程仓库拉 取下全部数据放入 .git 文件夹,而后从中读取最新版本的文件的拷贝。vim
Git 支持多种数据传输协议。上面的例子使用的是 https:// 协议,不过你也可使用 git:// 协议或者使用 SSH 传输协议,好比 user@server:path/to/repo.git 。安全
工做目录下的每个文件都不外乎这两种状态: 已跟踪 :已跟踪的文件是指那些被归入了版本控制的文件,在上一次快照中有它们的记录,在工做一段时间后,它们的状态可能处于未修改,已修改或已放 入暂存区。 未跟踪 :工做目录中除已跟踪文件之外的全部其它文件都属于未跟踪文件,它们既不存在于上次快照的记录中,也没有放入暂存区。初次克隆某个仓库的时 候,工做目录中的全部文件都属于已跟踪文件,并处于未修改状态。服务器
git status # 查看哪些文件处于什么状态 git status -s # 状态简览 == git status --short
命令结果分析:编辑器
$ git status -s M README MM Rakefile A lib/git.rb M lib/simplegit.rb ?? LICENSE.txt
- ?? : 新添加的未跟踪文件;
- A : 新添加到暂存区中的文件;
- M : 修改过的文件; 出如今右边的 M 表示该文件被修改了可是还没放入暂存区,出如今靠左边的 M 表示该文件被修改了并放入了暂存区
- D :
git add <fileName> | <path> # 使用文件或目录的路径做为参数;若是参数是目录的路径,该命令将递归地跟踪该目录下的全部文件。
通常咱们总会有些文件无需归入 Git 的管理,也不但愿它们总出如今未跟踪文件列表。一般都是些自动生成的文 件,好比日志文件,或者编译过程当中建立的临时文件等。在这种状况下,咱们能够建立一个名为 .gitignore 的文件,列出要忽略的文件模式。
例如:
$ cat .gitignore *.[oa] *~
说明: 第一行告诉 Git 忽略全部以 .o 或 .a 结尾的文件。通常这类对象文件和存档文件都是编译过程当中出现的。 第二行告诉 Git 忽略全部以波浪符(~)结尾的文件,许多文本编辑软件(好比 Emacs)都用这样的文件名保存副本。 此外,你可能还须要忽略 log,tmp 或者 pid 目录,以及自动生成的文档等等。要养成一开始就设置好.gitignore 文件的习惯,以避免未来误提交这类无用的文件。
文件 .gitignore 的格式规范以下:
说明:
glob 模式:指 shell 所使用的简化了的正则表达式。 星号(*)匹配零个或多个任意字符; [abc] 匹配任何一个列在方括号中的字符(这个例子要么匹配一个 a,要么匹配一个 b,要么匹配一个 c); 问号(?)只匹配一个任意字符; 若是在方括号[]中使用短划线分隔两个字符,表示全部在这两个字符范围内的均可以匹配(好比[0-9] 表示匹配全部 0 到 9 的数字); 使用两个星号(*)表示匹配任意中间目录,好比
a/**/z
能够匹配 a/z,a/b/z 或a/b/c/z
等。
举个例子:
# no .a files ,忽略.a结尾的文件 *.a # but do track lib.a, even though you're ignoring .a files above ,在第一个忽略文件中排出lib.a文件 !lib.a # only ignore the TODO file in the current directory, not subdir/TODO,仅仅只忽略当前/TODO目录下的文件 /TODO # ignore all files in the build/ directory,忽略build目录下的全部文件或者文件夹,包括子文件或者文件夹 build/ # ignore doc/notes.txt, but not doc/server/arch.txt,仅仅只忽略当前doc目录下的文件的后缀为.txt文件,可是不包括子文件夹下的文件 doc/*.txt # ignore all .pdf files in the doc/ directory,忽略doc目录下的全部.pdf后缀文件,包括子文件夹中的后缀为.pdf的文件 doc/**/*.pdf TIP
git diff # 此命令比较的是工做目录中当前文件和暂存区域快照之间的差别 git diff --staged # 查看已暂存的将要添加到下次提交里的内容【暂存区和本分支的repo最后一次的commit的比较】 git diff --cached # 这个是git diff --staged 的旧版本的命令,可是git一直向下兼容;
Git Diff 的插件版本 使用 git diff 来分析文件差别。可是,若是你喜欢经过图形化的方式或其 它格式输出方式的话,可使用 git difftool 命令来用 Araxis ,emerge 或 vimdiff 等软 件输出 diff 分析结果。使用 git difftool --tool-help 命令来看你的系统支持哪些 Git Diff 插件。
git commit # 把暂存区的文件所有提交到repo仓库中
这种方式会启动文本编辑器以便输入本次提交的说明。(默认会启用 shell 的环境变量 $EDITOR 所指定的软件, 通常都是 vim 或 emacs。固然也能够按照 起步 介绍的方式,使用 git config --global core.editor 命 令设定你喜欢的编辑软件。)
编辑器会显示相似下面的文本信息(本例选用 Vim 的屏显方式展现):
# Please enter the commit message for your changes. Lines starting # with '#' will be ignored, and an empty message aborts the commit. # On branch master # Changes to be committed: # new file: README # modified: CONTRIBUTING.md #~~~ ".git/COMMIT_EDITMSG" 9L, 283C
能够看到,默认的提交消息包含最后一次运行 git status 的输出,放在注释行里,另外开头还有一空行,供 你输入提交说明。你彻底能够去掉这些注释行,不过留着也不要紧,多少能帮你回想起此次更新的内容有哪些。 (若是想要更详细的对修改了哪些内容的提示,能够用 -v 选项,这会将你所作的改变的 diff 输出放到编辑器中从 而使你知道本次提交具体作了哪些修改。)退出编辑器时,Git 会丢掉注释行,用你输入提交附带信息生成一次 提交。
git commit -m "<message>" # 提交的信息
[master 463dc4f] Story 182: Fix benchmarks for speed 2 files changed, 2 insertions(+) create mode 100644 README
能够看到,提交后它会告诉你,当前是在哪一个分支(master)提交的,本 次提交的完整 SHA-1 校验和是什么(463dc4f),以及在本次提交中,有多少文件修订过,多少行添加和删改 过。
git commit -a -m "<message>" # Git 就会自动把全部已经**跟踪过的**文件暂存起来一并提交
- 要从 Git 中移除某个文件,就必需要从已跟踪文件清单中移除(确切地说,是从暂存区域移除),而后提交。 能够用 git rm 命令完成此项工做,并连带从工做目录中删除指定的文件,这样之后就不会出如今未跟踪文件清单中了。
git rm <fileName> # 把暂存区和工做目录中的文件所有删除,注意这个文件要有commit操做,要否则是要强力删除的
下一次提交时,该文件就再也不归入版本管理了。若是删除以前修改过而且已经放到暂存区域的话,则必需要用强 制删除选项 -f(译注:即 force 的首字母)。这是一种安全特性,用于防止误删尚未添加到快照的数据,这 样的数据不能被 Git 恢复。
- 另一种状况是,咱们想把文件从 Git 仓库中删除(亦即从暂存区域移除),但仍然但愿保留在当前工做目录 中。换句话说,你想让文件保留在磁盘,可是并不想让 Git 继续跟踪。当你忘记添加 .gitignore 文件,不小 ? 心把一个很大的日志文件或一堆 .a 这样的编译生成文件添加到暂存区时,这一作法尤为有用。为达到这一目 的,使用 --cached 选项:
git rm --cached <fileName> # 只是单纯的把文件从暂存区删除,不删除工做目录下的文件
git rm 命令后面能够列出文件或者目录的名字,也可使用 glob 模式
例如:
git rm log/\*.log
注意到星号 * 以前的反斜杠 \,由于 Git 有它本身的文件模式扩展匹配方式,因此咱们不用 shell 来帮忙展开。 此命令删除 log/ 目录下扩展名为 .log 的全部文件。
不像其它的 VCS 系统,Git 并不显式跟踪文件移动操做。若是在 Git 中重命名了某个文件,仓库中存储的元数据 并不会体现出这是一次更名操做。不过 Git 很是聪明,它会推断出究竟发生了什么,至于具体是如何作到的,我 们稍后再谈。
git mv file_from file_to #
它会恰如预期般正常工做。实际上,即使此时查看状态信息,也会明白无误地看到关于重命名操做的说明:
$ git mv README.md README $ git status On branch master Changes to be committed: (use "git reset HEAD <file>..." to unstage) renamed: README.md -> README
其实,运行 git mv 就至关于运行了下面三条命令:
$ mv README.md README $ git rm README.md $ git add README
如此分开操做,Git 也会意识到这是一次更名,因此无论何种方式结果都同样。二者惟一的区别是,mv 是一条命 令而另外一种方式须要三条命令,直接用 git mv 轻便得多。不过有时候用其余工具批处理更名的话,要记得在提 交前删除老的文件名,再添加新的文件名。
git log # 查看当前分支的日志
$ git log commit ca82a6dff817ec66f44342007202690a93763949 Author: Scott Chacon <schacon@gee-mail.com> Date: Mon Mar 17 21:52:11 2008 -0700 changed the version number commit 085bb3bcb608e1e8451d4b2432f8ecbe6306e7e7 Author: Scott Chacon <schacon@gee-mail.com> Date: Sat Mar 15 16:40:33 2008 -0700 removed unnecessary test commit a11bef06a3f659402fe7563abf99ad00de2209e6 Author: Scott Chacon <schacon@gee-mail.com> Date: Sat Mar 15 10:31:28 2008 -0700 first commit
默认不用任何参数的话: git log 会按提交时间列出全部的更新,最近的更新排在最上面;
- 这个命令会列出每一个提交的 SHA-1 校验;
- 做者的名字和电子邮件地址;
- 提交时间;
- 提交说明;
$ git log -p -2 commit ca82a6dff817ec66f44342007202690a93763949 Author: Scott Chacon <schacon@gee-mail.com> Date: Mon Mar 17 21:52:11 2008 -0700 changed the version number diff --git a/Rakefile b/Rakefile index a874b73..8f94139 100644 --- a/Rakefile +++ b/Rakefile @@ -5,7 +5,7 @@ require 'rake/gempackagetask' spec = Gem::Specification.new do |s| s.platform = Gem::Platform::RUBY s.name = "simplegit" - s.version = "0.1.0" + s.version = "0.1.1" s.author = "Scott Chacon" s.email = "schacon@gee-mail.com" s.summary = "A simple gem for using Git in Ruby code." commit 085bb3bcb608e1e8451d4b2432f8ecbe6306e7e7 Author: Scott Chacon <schacon@gee-mail.com> Date: Sat Mar 15 16:40:33 2008 -0700 removed unnecessary test diff --git a/lib/simplegit.rb b/lib/simplegit.rb index a0a60ae..47c6340 100644 --- a/lib/simplegit.rb +++ b/lib/simplegit.rb @@ -18,8 +18,3 @@ class SimpleGit end end - -if $0 == __FILE__ - git = SimpleGit.new - puts git.show -end \ No newline at end of file
该选项除了显示基本信息以外,还在附带了每次 commit 的变化。当进行代码审查,或者快速浏览某个搭档提交 的 commit 所带来的变化的时候,这个参数就很是有用了。你也能够为 git log 附带一系列的总结性选项。比 如说,若是你想看到每次提交的简略的统计信息,你可使用 --stat 选项:
$ git log --stat commit ca82a6dff817ec66f44342007202690a93763949 Author: Scott Chacon <schacon@gee-mail.com> Date: Mon Mar 17 21:52:11 2008 -0700 changed the version number Rakefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit 085bb3bcb608e1e8451d4b2432f8ecbe6306e7e7 Author: Scott Chacon <schacon@gee-mail.com> Date: Sat Mar 15 16:40:33 2008 -0700 removed unnecessary test lib/simplegit.rb | 5 ----- 1 file changed, 5 deletions(-) commit a11bef06a3f659402fe7563abf99ad00de2209e6 Author: Scott Chacon <schacon@gee-mail.com> Date: Sat Mar 15 10:31:28 2008 -0700 first commit README | 6 ++++++ Rakefile | 23 +++++++++++++++++++++++ lib/simplegit.rb | 25 +++++++++++++++++++++++++ 3 files changed, 54 insertions(+)
正如你所看到的,--stat 选项在每次提交的下面列出额全部被修改过的文件、有多少文件被修改了以及被修改 过的文件的哪些行被移除或是添加了。在每次提交的最后还有一个总结。
另一个经常使用的选项是 --pretty。这个选项能够指定使用不一样于默认格式的方式展现提交历史。这个选项有一 些内建的子选项供你使用。好比用 oneline 将每一个提交放在一行显示,查看的提交数很大时很是有用。另外还 有 short,full 和 fuller 能够用,展现的信息或多或少有些不一样,请本身动手实践一下看看效果如何。
$ git log --pretty=oneline ca82a6dff817ec66f44342007202690a93763949 changed the version number 085bb3bcb608e1e8451d4b2432f8ecbe6306e7e7 removed unnecessary test a11bef06a3f659402fe7563abf99ad00de2209e6 first commit
但最有意思的是 format,能够定制要显示的记录格式。这样的输出对后期提取分析格外有用 — 由于你知道 输出的格式不会随着Git的更新而发生改变:
$ git log --pretty=format:"%h - %an, %ar : %s" ca82a6d - Scott Chacon, 6 years ago : changed the version number 085bb3b - Scott Chacon, 6 years ago : removed unnecessary test a11bef0 - Scott Chacon, 6 years ago : first commit
git log --pretty=format #经常使用的选项 列出了经常使用的格式占位符写法及其表明的意义。
git log --pretty=format 经常使用的选项
选项 | 说明 |
---|---|
%H | 提交对象(commit)的完整哈希字串 |
%h | 提交对象的简短哈希字串 |
%T | 树对象(tree)的完整哈希字串 |
%t | 树对象的简短哈希字串 |
%P | 父对象(parent)的完整哈希字串 |
%p | 父对象的简短哈希字串 |
%an | 做者(author)的名字 |
%ae | 做者的电子邮件地址 |
%ad | 做者修订日期(能够用 --date= 选项定制格式) |
%ar | 做者修订日期,按多久之前的方式显示 |
%cn | 提交者(committer)的名字 |
%ce | 提交者的电子邮件地址 |
%cd | 提交日期 |
%cr | 提交日期,按多久之前的方式显示 |
%s | 提交说明 |
你必定奇怪 做者 和 提交者 之间究竟有何差异,其实做者指的是实际做出修改的人,提交者指的是最后将此工做 成果提交到仓库的人。因此,当你为某个项目发布补丁,而后某个核心成员将你的补丁并入项目时,你就是做 者,而那个核心成员就是提交者。
当 oneline 或 format 与另外一个 log 选项 --graph 结合使用时尤为有用。这个选项添加了一些ASCII字符串来形 象地展现你的分支、合并历史:
$ git log --pretty=format:"%h %s" --graph * 2d3acf9 ignore errors from SIGCHLD on trap * 5e3ee11 Merge branch 'master' of git://github.com/dustin/grit |\ | * 420eac9 Added a method for getting the current branch. * | 30e367c timeout code and tests * | 5a09431 add timeout protection to grit * | e1193f8 support for heads with slashes in them |/ * d6016bc require time for xmlschema * 11d191e Merge branch 'defunkt' into local
这种输出类型会在咱们下一张学完分支与合并之后变得更加有趣。
git log 的经常使用选项
选项 | 说明 |
---|---|
-p | 按补丁格式显示每一个更新之间的差别。 |
--stat | 显示每次更新的文件修改统计信息。 |
--shortstat | 只显示 --stat 中最后的行数修改添加移除统计。 |
--name-only | 仅在提交信息后显示已修改的文件清单。 |
--name-status | 显示新增、修改、删除的文件清单。 |
--abbrev-commit | 仅显示 SHA-1 的前几个字符,而非全部的 40 个字符。 |
--relative-date | 使用较短的相对时间显示(好比,“2 weeks ago”)。 |
--graph | 显示 ASCII 图形表示的分支合并历史。 |
--pretty | 使用其余格式显示历史提交信息。可用的选项包括 oneline,short,full,fuller 和format(后跟指定格式)。 |
除了定制输出格式的选项以外,git log 还有许多很是实用的限制输出长度的选项,也就是只输出部分提交信 息。以前你已经看到过 -2 了,它只显示最近的两条提交,实际上,这是 -<n> 选项的写法,其中的 n 能够是任 何整数,表示仅显示最近的若干条提交。不过实践中咱们是不太用这个选项的,Git 在输出全部提交时会自动调 用分页程序,因此你一次只会看到一页的内容。
另外还有按照时间做限制的选项,好比 --since 和 --until 也颇有用。例如,下面的命令列出全部最近两周 内的提交:
$ git log --since=2.weeks
这个命令能够在多种格式下工做,好比说具体的某一天 "2008-01-15",或者是相对地多久之前 "2 years 1 day 3 minutes ago"。
还能够给出若干搜索条件,列出符合的提交。用 --author 选项显示指定做者的提交,用 --grep 选项搜索提 交说明中的关键字。(请注意,若是要获得同时知足这两个选项搜索条件的提交,就必须用 --all-match 选 项。不然,知足任意一个条件的提交都会被匹配出来) 另外一个很是有用的筛选选项是 -S,能够列出那些添加或移除了某些字符串的提交。好比说,你想找出添加或移 除了某一个特定函数的引用的提交,你能够这样使用:
$ git log -Sfunction_name
最后一个很实用的 git log 选项是路径(path),若是只关心某些文件或者目录的历史提交,能够在 git log 选项 的最后指定它们的路径。由于是放在最后位置上的选项,因此用两个短划线(--)隔开以前的选项和后面限定的 路径名。
限制 git log 输出的选项
选项 | 说明 |
---|---|
-(n) | 仅显示最近的 n 条提交 |
--since, --after | 仅显示指定时间以后的提交。 |
--until, --before | 仅显示指定时间以前的提交。 |
--author | 仅显示指定做者相关的提交。 |
--committer | 仅显示指定提交者相关的提交。 |
--grep | 仅显示含指定关键字的提交 |
-S | 仅显示添加或移除了某个关键字的提交 |
注意,有些撤消操做是不可逆的.
有时候咱们提交完了才发现漏掉了几个文件没有添加,或者提交信息写错了。此时,能够运行带有 --amend 选 项的提交命令尝试从新提交:
$ git commit --amend # 修改最后一次提交的信息
这个命令会将暂存区中的文件提交。若是自上次提交以来你还未作任何修改(例如,在上次提交后立刻执行了此命令),那么快照会保持不变,而你所修改的只是提交信息。
接下来的两个小节演示如何操做暂存区域与工做目录中已修改的文件。
git reset HEAD <file> # 来取消暂存
例如,你已经修改了两个文件而且想要将它们做为两次独立的修改提交,可是却意外地输入了 git add * 暂存了它们两个。如何只取消暂存两个中的一个呢?git status 命令提示了你:
$ git add * $ git status On branch master Changes to be committed: (use "git reset HEAD <file>..." to unstage) renamed: README.md -> README modified: CONTRIBUTING.md
$ git reset HEAD CONTRIBUTING.md Unstaged changes after reset: M CONTRIBUTING.md $ git status On branch master Changes to be committed: (use "git reset HEAD <file>..." to unstage) renamed: README.md -> README Changes not staged for commit: (use "git add <file>..." to update what will be committed) (use "git checkout -- <file>..." to discard changes in working directory) modified: CONTRIBUTING.md
虽然在调用时加上 --hard 选项能够令 git reset 成为一个危险的命令(译注:可能致使 工做目录中全部当前进度丢失!),但本例中工做目录内的文件并不会被修改。不加选项地 调用 git reset 并不危险 — 它只会修改暂存区域。
git checkout -- [file] # 把暂存区的信息覆盖工做区的内容
你须要知道 git checkout -- [file] 是一个危险的命令,这很重要。你对那个文 件作的任何修改都会消失 - 你只是拷贝了另外一个文件来覆盖它。除非你确实清楚不想 要那个文件了,不然不要使用这个命令。
git remote # 查看你已经配置的远程仓库服务器
origin - 这是 Git 给你克隆的仓库服务器的默认名字
git remote -v # 会显示须要读写远程仓库使用的 Git 保存的简写与其对应的 URL
git remote add <shortname> <url> # 添加一个新的远程 Git 仓库,同时指定一个你能够轻松引用的简写(shortname)
例如:
$ git remote origin $ git remote add pb https://github.com/paulboone/ticgit $ git remote -v origin https://github.com/schacon/ticgit (fetch) origin https://github.com/schacon/ticgit (push) pb https://github.com/paulboone/ticgit (fetch) pb https://github.com/paulboone/ticgit (push)
如今你能够在命令行中使用字符串 pb 来代替整个 URL。例如,若是你想拉取 Paul 的仓库中有但你没有的信 息,能够运行 git fetch pb:
$ git fetch pb remote: Counting objects: 43, done. remote: Compressing objects: 100% (36/36), done. remote: Total 43 (delta 10), reused 31 (delta 5) Unpacking objects: 100% (43/43), done. From https://github.com/paulboone/ticgit * [new branch] master -> pb/master * [new branch] ticgit -> pb/ticgit
git fetch [remote-name] # 这个命令会访问远程仓库,从中拉取全部你尚未的数据。 # 执行完成后,你将会拥有那个远程仓库中全部分支的引用,能够随时合并或查看。
若是你使用 clone 命令克隆了一个仓库,命令会自动将其添加为远程仓库并默认以 “origin” 为简写。所 以,git fetch origin 会抓取克隆(或上一次抓取)后新推送的全部工做。必须注意 git fetch 命令会将 数据拉取到你的本地仓库 - 它并不会自动合并或修改你当前的工做。当准备好时你必须手动将其合并入你的工 做。
若是你有一个分支设置为跟踪一个远程分支,可使用 git pull 命令来自动的抓取而后合并远程分支到当前分支。 这对你来讲多是一个更简单或更舒服的工做流程;默认状况下,git clone 命令会自动设置本地 master 分支跟踪 克隆的远程仓库的 master 分支(或无论是什么名字的默认分支)。运行 git pull 一般会从最初克隆的服务器上抓 取数据并自动尝试合并到当前所在的分支。
git push [remote-name] [branchname] # 将本分支的仓库推送到上游
当你想要将 master 分支推送到 origin 服务器时(再次说明,克隆时一般会自动帮你设置好那两个名 字),那么运行这个命令就能够将你所作的备份到服务器:
$ git push origin master
<font color=red>push前必定先要fetch和merge,要否则远程服务器会拒绝</font> 只有当你有所克隆服务器的写入权限,而且以前没有人推送过期,这条命令才能生效。当你和其余人在同一时间 克隆,他们先推送到上游而后你再推送到上游,你的推送就会毫无疑问地被拒绝。你必须先将他们的工做拉取下 来并将其合并进你的工做后才能推送。
git remote show [remote-name] # 查看某一个远程仓库的更多信息
$ git remote show origin * remote origin Fetch URL: https://github.com/schacon/ticgit Push URL: https://github.com/schacon/ticgit HEAD branch: master Remote branches: master tracked dev-branch tracked Local branch configured for 'git pull': master merges with remote master Local ref configured for 'git push': master pushes to master (up to date)
它一样会列出远程仓库的 URL 与跟踪分支的信息。这些信息很是有用,它告诉你正处于 master 分支,而且若是 运行 git pull,就会抓取全部的远程引用,而后将远程 master 分支合并到本地 master 分支。它也会列出拉取到 的全部远程引用。
这个命令列出了当你在特定的分支上执行 git push 会自动地推送到哪个远程分支。它也一样地列出了哪些 远程分支不在你的本地,哪些远程分支已经从服务器上移除了,还有当你执行 git pull 时哪些分支会自动合 并。
git remote rename [oldname] [newname] #
若是由于一些缘由想要移除一个远程仓库 - 你已经从服务器上搬走了或再也不想使用某一个特定的镜像了,又或者 某一个贡献者再也不贡献了 - 可使用 git remote rm
git remote rm [name]
git tag # 以字母顺序列出标签
你也可使用特定的模式查找标签。例如,Git 自身的源代码仓库包含标签的数量超过 500 个。若是只对 1.8.5 系列感兴趣,能够运行:
$ git tag -l 'v1.8.5*' v1.8.5 v1.8.5-rc0 v1.8.5-rc1 v1.8.5-rc2 v1.8.5-rc3 v1.8.5.1 v1.8.5.2 v1.8.5.3 v1.8.5.4 v1.8.5.5
Git 使用两种主要类型的标签:
- 轻量标签(lightweight) : 不会改变的分支 - 它只是一个特定提交的引用
- 附注标签(annotated) : 存储在 Git 数据库中的一个完整对象 它们是能够被校验的;其中包含打标签者的名字、电子邮件地址、日期时间;还有一个标签信息;而且可使用 GNU Privacy Guard (GPG)签名与验证。
一般建议建立附注标签,这样你能够拥有以上全部信息;可是若是你只是想用一个临时的 标签,或者由于某些缘由不想要保存那些信息,轻量标签也是可用的。
git tag -a [tagName] -m [message] : 建立附注标签
-m 选项指定了一条将会存储在标签中的信息。若是没有为附注标签指定一条信息,Git 会运行编辑器要求你输入信息。
git show [tagName] : 命令能够看到标签信息与对应的提交信息
输出显示了打标签者的信息、打标签的日期时间、附注信息,而后显示具体的提交信息。
轻量标签本质上是将提交校验和存储到一个文件中 - 没有保存任何 其余信息。建立轻量标签,不须要使用 -a、-s 或 -m 选项,只须要提供标签名字:
git tag [tagName] : 建立 轻量标签
git tag -a [tagName] [commit id] # 为特定的commit建立标签
假设提交历史是这样的:
$ git log --pretty=oneline 15027957951b64cf874c3557a0f3547bd83b3ff6 Merge branch 'experiment' a6b4c97498bd301d84096da251c98a07c7723e65 beginning write support 0d52aaab4479697da7686c15f77a3d64d9165190 one more thing 6d52a271eda8725415634dd79daabbc4d9b6008e Merge branch 'experiment' 0b7434d86859cc7b8c3d5e1dddfed66ff742fcbc added a commit function 4682c3261057305bdd616e23b64b0857d832627b added a todo file 166ae0c4d3f420721acbb115cc33848dfcc2121a started write support 9fceb02d0ae598e95dc970b74767f19372d61af8 updated rakefile 964f16d36dfccde844893cac5b347e7b3d44abbc commit the todo 8a5cbc430f1a9c3d00faaeffd07798508422908a updated readme
如今,假设在 v1.2 时你忘记给项目打标签,也就是在 “updated rakefile” 提交。你能够在以后补上标签。要 在那个提交上打标签,你须要在命令的末尾指定提交的校验和(或部分校验和):
$ git tag -a v1.2 9fceb02
** git push 命令并不会传送标签到远程仓库服务器上 **
建立完标签后你必须显式地推送标签到共享服务器上。这个过程就像共享远程分支同样 - 你能够运行:
git push origin [tagname] # 共享标签到远程服务器
若是想要一次性推送不少标签,也可使用带有 --tags 选项的 git push 命令。这将会把全部不在远程仓库 服务器上的标签所有传送到那里。
例如:
$ git push origin --tags Counting objects: 1, done. Writing objects: 100% (1/1), 160 bytes | 0 bytes/s, done. Total 1 (delta 0), reused 0 (delta 0) To git@github.com:schacon/simplegit.git * [new tag] v1.4 -> v1.4 * [new tag] v1.4-lw -> v1.4-lw
在 Git 中你并不能真的检出一个标签,由于它们并不能像分支同样来回移动。若是你想要工做目录与仓库中特定 的标签版本彻底同样,可使用 git checkout -b [branchname] [tagname] 在特定的标签上建立一个新分支:
git checkout -b [branchname] [tagname] # 在特定的标签上建立一个新分支
$ git checkout -b version2 v2.0.0 Switched to a new branch 'version2'
固然,若是在这以后又进行了一次提交,version2 分支会由于改动向前移动了,那么 version2 分支就会和 v2.0.0 标签稍微有些不一样,这时就应该小心了。
Git 并不会在你输入部分命令时自动推断出你想要的命令。若是不想每次都输入完整的 Git 命令,能够经过 git config 文件来轻松地为每个命令设置一个别名。
git config --global alias.[aliasname] [name] # 为某个命令建立别名
$ git config --global alias.co checkout $ git config --global alias.br branch $ git config --global alias.ci commit $ git config --global alias.st status
Git 保存的不是文件的变化或者差别,而是一系列不一样时刻的文件快照。这个特性是Git快速建立分支和快速切换分支的基础。 这就是用空间来换时间的原理。固然空间Git也优化的很好。
在进行提交操做时,Git 会保存一个提交对象(commit object)。知道了 Git 保存数据的方式,咱们能够很自 然的想到——该提交对象会包含一个指向暂存内容快照的指针。但不只仅是这样,该提交对象还包含了做者的姓 名和邮箱、提交时输入的信息以及指向它的父对象的指针。首次提交产生的提交对象没有父对象,普通提交操做 产生的提交对象有一个父对象,而由多个分支合并产生的提交对象有多个父对象,为了说得更加形象,咱们假设现 在有一个工做目录,里面包含了三个将要被暂存和提交的文件。暂存操做会为每个文件计算校验和SHA-1 哈希算法, 而后会把当前版本的文件快照保存到 Git仓库中(Git 使用 blob 对象来保存它们),最终将校验和加入到暂存区域等待提交:
$ git add README test.rb LICENSE $ git commit -m 'The initial commit of my project'
当使用 git commit 进行提交操做时,Git 会先计算每个子目录(本例中只有项目根目录)的校验和,而后在 Git 仓库中这些校验和保存为树对象。随后,Git 便会建立一个提交对象,它除了包含上面提到的那些信息外, 还包含指向这个树对象(项目根目录)的指针。如此一来,Git 就能够在须要的时候重现这次保存的快照。
如今,Git 仓库中有五个对象:三个 blob 对象(保存着文件快照)、一个树对象(记录着目录结构和 blob 对象 索引)以及一个提交对象(包含着指向前述树对象的指针和全部提交信息)。
graph LR commit-->tree tree-->blob1 tree-->blob2 tree-->blob3
graph RL commitA-->snapshotA commitB-->snapshotB commitC-->snapshotC commitC-->commitB commitB-->commitA
Git 的分支,其实本质上仅仅是指向提交对象的可变指针。Git 的默认分支名字是 master。在屡次提交操做之 后,你其实已经有一个指向最后那个提交对象的 master 分支。它会在每次的提交操做中自动向前移动。