0%

Git进阶(1)

Main Takeaway

Git进阶(1)——了解Git是什么,Git的配置和所有 Git 基本的本地操作

希望通过Git - Book (git-scm.com)+Learn Git Branching来进一步掌握Git

Learn to love the command line. Leave the IDE behind.

Git是什么

Git特点

  • 直接记录快照,而非差异比较: 在 Git 中,每当你提交更新或保存项目状态时,它基本上就会对当时的全部文件创建一个快照并保存这个快照的索引。 为了效率,如果文件没有修改,Git 不再重新存储该文件,而是只保留一个链接指向之前存储的文件。 Git 对待数据更像是一个 快照流

  • 近乎所有操作都是本地执行,只有上传时才需联网

  • Git 保证完整性:Git 中所有的数据在存储前都计算校验和,然后以校验和来引用。Git 用以计算校验和的机制叫做 SHA-1 散列(hash,哈希)。 这是一个由 40 个十六进制字符(0-9 和 a-f)组成的字符串,基于 Git 中文件的内容或目录结构计算出来。

    Tips:Git 数据库中保存的信息都是以文件内容的哈希值来索引,而不是文件名。

  • Git 一般只添加数据:你执行的 Git 操作,几乎只往 Git 数据库中 添加 数据。 你很难使用 Git 从数据库中删除数据,也就是说 Git 几乎不会执行任何可能导致文件不可恢复的操作。

Git三种状态

Git 有三种状态:已提交(committed)已修改(modified)已暂存(staged)

  • 已修改表示修改了文件,但还没保存到数据库中。
  • 已暂存表示对一个已修改文件的当前版本做了标记,使之包含在下次提交的快照中。
  • 已提交表示数据已经安全地保存在本地数据库中。

这会让我们的 Git 项目拥有三个阶段:工作区、暂存区以及 Git 目录。

areas
  • 工作区是对项目的某个版本独立提取出来的内容。 这些从 Git 仓库的压缩数据库中提取出来的文件,放在磁盘上供你使用或修改。
  • 暂存区是一个文件,保存了下次将要提交的文件列表信息,一般在 Git 仓库目录中。 按照 Git 的术语叫做“索引”,不过一般说法还是叫“暂存区”。
  • Git 仓库目录是 Git 用来保存项目的元数据和对象数据库的地方。 这是 Git 中最重要的部分,从其它计算机克隆仓库时,复制的就是这里的数据。

Git工作流程

  1. 在工作区中修改文件。
  2. 将你想要下次提交的更改选择性地暂存,这样只会将更改的部分添加到暂存区。
  3. 提交更新,找到暂存区的文件,将快照永久性存储到 Git 目录。

如果 Git 目录中保存着特定版本的文件,就属于 已提交 状态。 如果文件已修改并放入暂存区,就属于 已暂存 状态。 如果自上次检出后,作了修改但还没有放到暂存区域,就是 已修改 状态。

Git获取帮助

Git命令的manpage

1
2
3
$ git help <verb>
$ git <verb> --help
$ man git-<verb>

or 可以用 -h 选项获得更简明的 "help'':

1
$ git add -h 

Git配置

Git 自带一个 git config 的工具来帮助设置控制 Git 外观和行为的配置变量。

查看所有的配置以及它们所在的文件:

1
$ git config --list --show-origin
  • 用户信息

安装完 Git 之后,要做的第一件事就是设置你的用户名和邮件地址。 这一点很重要,因为每一个 Git 提交都会使用这些信息,它们会写入到你的每一次提交中,不可更改:

1
2
$ git config --global user.name "John Doe"
$ git config --global user.email johndoe@example.com

Tips:如果使用了 --global 选项,那么该命令只需要运行一次,因为之后无论你在该系统上做任何事情, Git 都会使用那些信息。()

  • 文本编辑器

    既然用户信息已经设置完毕,你可以配置默认文本编辑器了,当 Git 需要你输入信息时会调用它。 如果未配置,Git 会使用操作系统默认的文本编辑器。

    如果你想使用不同的文本编辑器,例如 Emacs,可以这样做:

    1
    $ git config --global core.editor emacs

    在 Windows 系统上,如果你想要使用别的文本编辑器,那么必须指定可执行文件的完整路径。 它可能随你的编辑器的打包方式而不同。

  • 检查配置信息

    如果想要检查你的配置,可以使用 git config --list 命令来列出所有 Git 当时能找到的配置。

    你可以通过输入 git config <key>: 来检查 Git 的某一项配置

    1
    2
    $ git config user.name
    John Doe

Note: 由于 Git 会从多个文件中读取同一配置变量的不同值,因此你可能会在其中看到意料之外的值而不知道为什么。 此时,你可以查询 Git 中该变量的 原始 值,它会告诉你哪一个配置文件最后设置了该值:$ git config --show-origin rerere.autoUpdate file:/home/johndoe/.gitconfig false

Git基础

获取Git repository

通常有两种获取 Git 项目仓库的方式:

  • 将尚未进行版本控制的本地目录转换为 Git 仓库

    1
    2
    cd /home/user/my_project
    git init

    该命令将创建一个名为 .git 的子目录,这个子目录含有你初始化的 Git 仓库中所有的必须文件,这些文件是 Git 仓库的骨干。 但是,在这个时候,我们仅仅是做了一个初始化的操作,你的项目里的文件还没有被跟踪。

    如果在一个已存在文件的文件夹(而非空文件夹)中进行版本控制,你应该开始追踪这些文件并进行初始提交。 可以通过 git add 命令来指定所需的文件来进行追踪,然后执行 git commit

    1
    2
    3
    $ git add *.c
    $ git add LICENSE
    $ git commit -m 'initial project version'
  • 从其它服务器 克隆 一个已存在的 Git 仓库。

    克隆仓库的命令是 git clone <url>

    1
    $ git clone https://github.com/libgit2/libgit2

    这会在当前目录下创建一个名为 “libgit2” 的目录,并在这个目录下初始化一个 .git 文件夹, 从远程仓库拉取下所有数据放入 .git 文件夹,然后从中读取最新版本的文件的拷贝。

    如果你想在克隆远程仓库的时候,自定义本地仓库的名字,你可以通过额外的参数指定新的目录名:

    1
    $ git clone https://github.com/libgit2/libgit2 mylibgit

记录每次更新到仓库

每一个文件都有两种状态:已跟踪未跟踪。(已跟踪的文件就是 Git 已经知道的文件。)

lifecycle
  • 检查当前文件状态

    可以用 git status 命令查看哪些文件处于什么状态

  • 状态简览

    git status 命令的输出十分详细,但其用语有些繁琐。 Git 有一个选项可以帮你缩短状态命令的输出,这样可以以简洁的方式查看更改。 如果你使用 git status -s 命令或 git status --short 命令,你将得到一种格式更为紧凑的输出。

    1
    2
    3
    4
    5
    6
    $ git status -s
    M README
    MM Rakefile
    A lib/git.rb
    M lib/simplegit.rb
    ?? LICENSE.txt

    新添加的未跟踪文件前面有 ?? 标记,新添加到暂存区中的文件前面有 A 标记,修改过的文件前面有 M 标记。 输出中有两栏,左栏指明了暂存区的状态,右栏指明了工作区的状态。例如,上面的状态报告显示: README 文件在工作区已修改但尚未暂存,而 lib/simplegit.rb 文件已修改且已暂存。 Rakefile 文件已修改,暂存后又作了修改,因此该文件的修改中既有已暂存的部分,又有未暂存的部分。

  • 跟踪新文件

    使用命令 git add 开始跟踪一个文件,只要在 Changes to be committed 这行下面的,就说明是已暂存状态。

  • 暂存已修改的文件

    文件出现在 Changes not staged for commit 这行下面,说明已跟踪文件的内容发生了变化,但还没有放到暂存区。 要暂存这次更新,需要运行 git add 命令。 这是个多功能命令:可以用它开始跟踪新文件,或者把已跟踪的文件放到暂存区,还能用于合并时把有冲突的文件标记为已解决状态等。

    Tips:文件可能同时出现在暂存区(某一次修改被git add)和非暂存区(之后又修改了)。所以要重新git add

  • 忽略文件

    一般我们总会有些文件无需纳入 Git 的管理,也不希望它们总出现在未跟踪文件列表。 通常都是些自动生成的文件,比如日志文件,或者编译过程中创建的临时文件等。 在这种情况下,我们可以创建一个名为 .gitignore 的文件,列出要忽略的文件的模式

    1
    touch .gitignore
  • 文件 .gitignore 的格式规范如下:

    • 所有空行或者以 # 开头的行都会被 Git 忽略。
    • 可以使用标准的 glob 模式匹配,它会递归地应用在整个工作区中。
    • 匹配模式可以以(/)开头防止递归。
    • 匹配模式可以以(/)结尾指定目录。
    • 要忽略指定模式以外的文件或目录,可以在模式前加上叹号(!)取反。

    所谓的 glob 模式是指 shell 所使用的简化了的正则表达式。 星号(*)匹配零个或多个任意字符;[abc] 匹配任何一个列在方括号中的字符 (这个例子要么匹配一个 a,要么匹配一个 b,要么匹配一个 c); 问号(?)只匹配一个任意字符;如果在方括号中使用短划线分隔两个字符, 表示所有在这两个字符范围内的都可以匹配(比如 [0-9] 表示匹配所有 0 到 9 的数字)。 使用两个星号(**)表示匹配任意中间目录,比如 a/**/z 可以匹配 a/za/b/za/b/c/z 等。

    Tips:要养成一开始就为你的新仓库设置好 .gitignore 文件的习惯,以免将来误提交这类无用的文件。

  • 查看已暂存和未暂存的修改

    想知道具体修改了什么地方,可以用 git diff 命令。 git diff 能通过文件补丁的格式更加具体地显示哪些行发生了改变。( --staged--cached 是同义词)

    • 要查看修改之后还没有暂存起来的变化内容,不加参数直接输入 git diff
    • 要查看已暂存的将要添加到下次提交里的内容,可以用 git diff --staged 命令。 这条命令将比对已暂存文件与最后一次提交的文件差异

    Tips:git diff 本身只显示尚未暂存的改动,而不是自上次提交以来所做的所有改动

  • 提交更新

    提交命令 git commit,这样会启动你选择的文本编辑器来输入提交说明。

    可以在 commit 命令后添加 -m 选项,将提交信息与命令放在同一行,如下所示:

    1
    $ git commit -m "Story 182: Fix benchmarks for speed"

    Note:更详细的内容修改提示可以用 -v 选项查看,这会将你所作的更改的 diff 输出呈现在编辑器中,以便让你知道本次提交具体作出哪些修改。

    提交后它会告诉你,当前是在哪个分支(master)提交的,本次提交的完整SHA-1 校验和是什么(463dc4f),以及在本次提交中,有多少文件修订过,多少行添加和删改过

  • 跳过使用暂存区域

    只要在提交的时候,给 git commit 加上 -a 选项,Git 就会自动把所有已经跟踪过的文件暂存起来一并提交,从而跳过 git add 步骤

    1
    $ git commit -a -m 'added new benchmarks'
  • 移除文件

    要从 Git 中移除某个文件,就必须要从已跟踪文件清单中移除(确切地说,是从暂存区域移除),然后提交。 可以用 git rm 命令完成此项工作,并连带从工作目录中删除指定的文件,这样以后就不会出现在未跟踪文件清单中了。

    下一次提交时,该文件就不再纳入版本管理了。 如果要删除之前修改过或已经放到暂存区的文件,则必须使用强制删除选项 -f(译注:即 force 的首字母)。 这是一种安全特性,用于防止误删尚未添加到快照的数据,这样的数据不能被 Git 恢复

    另外一种情况是,我们想把文件从 Git 仓库中删除(亦即从暂存区域移除),但仍然希望保留在当前工作目录中。 换句话说,你想让文件保留在磁盘,但是并不想让 Git 继续跟踪。 当你忘记添加 .gitignore 文件,不小心把一个很大的日志文件或一堆 .a 这样的编译生成文件添加到暂存区时,这一做法尤其有用。 为达到这一目的,使用 --cached 选项:

    1
    $ git rm --cached README

    如果只是简单地从工作目录中手工删除文件,运行 git status 时就会在 “Changes not staged for commit” 部分(也就是 未暂存清单)看到。

  • 移动文件

    要在 Git 中对文件改名,可以这么做:(Git足够聪明)

    1
    $ git mv file_from file_to

    运行 git mv 就相当于运行了下面三条命令:

    1
    2
    3
    $ mv README.md README
    $ git rm README.md
    $ git add README

    直接使用 git mv 方便得多。 不过在使用其他工具重命名文件时,记得在提交前 git rm 删除旧文件名,再 git add 添加新文件名。

查看提交历史

完成这个任务最简单而又有效的工具是 git log 命令。

默认情况下,git log 会按时间先后顺序列出所有的提交,最近的更新排在最上面。这个命令会列出每个提交的 SHA-1 校验和、作者的名字和电子邮件地址、提交时间以及提交说明。

常用的选项

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(用来定义自己的格式)。
--oneline--pretty=oneline --abbrev-commit 合用的简写。
  • 其中一个比较有用的选项是 -p--patch ,它会显示每次提交所引入的差异(按 补丁 的格式输出)。 你也可以限制显示的日志条目数量,例如使用 -2 选项来只显示最近的两次提交

  • 想看到每次提交的简略统计信息,可以使用 --stat 选项。在每次提交的下面列出所有被修改过的文件、有多少文件被修改了以及被修改过的文件的哪些行被移除或是添加了。 在每次提交的最后还有一个总结

  • --pretty。 这个选项可以使用不同于默认格式的方式展示提交历史。oneline 会将每个提交放在一行显示,在浏览大量的提交时非常有用。 另外还有 shortfullfuller 选项,它们展示信息的格式基本一致,但是详尽程度不一 。

    git log --pretty=format format 接受的常用格式占位符的写法及其代表的意义(可以定制记录的显示格式):

选项说明
%H提交的完整哈希值
%h提交的简写哈希值
%T树的完整哈希值
%t树的简写哈希值
%P父提交的完整哈希值
%p父提交的简写哈希值
%an作者名字
%ae作者的电子邮件地址
%ad作者修订日期(可以用 --date=选项 来定制格式)
%ar作者修订日期,按多久以前的方式显示
%cn提交者的名字
%ce提交者的电子邮件地址
%cd提交日期
%cr提交日期(距今多长时间)
%s提交说明

eg:

1
2
3
4
$ 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
  • onelineformat 与另一个 log 选项 --graph 结合使用时尤其有用。--graph可视化显示分支、合并历史

限制输出长度

  • 你可以使用类似 -<n> 的选项,其中的 n 可以是任何整数,表示仅显示最近的 n 条提交。 不过实践中这个选项不是很常用,因为 Git 默认会将所有的输出传送到分页程序中,所以你一次只会看到一页的内容。

  • --since==--after(仅显示指定时间之后的提交)和 --until ==--before(仅显示指定时间之前的提交)这种按照时间作限制的选项很有用。 下面的命令会列出最近两周的所有提交:

    1
    $ git log --since=2.weeks

    该命令可用的格式十分丰富——可以是类似 "2008-01-15" 的具体的某一天,也可以是类似 "2 years 1 day 3 minutes ago" 的相对日期。

  • 过滤出匹配指定条件的提交。 用 --author 选项显示指定作者的提交,用 --grep 选项搜索提交说明中的关键字。

    Tips:你可以指定多个 --author--grep 搜索条件,这样会只输出匹配 任意 --author 模式和 任意 --grep 模式的提交。然而,如果你添加了 --all-match 选项, 则只会输出匹配 所有 --grep 模式的提交。

  • 另一个非常有用的过滤器是 -S,它接受一个字符串参数,并且只会显示那些添加或删除了该字符串的提交。 假设你想找出添加或删除了对某一个特定函数的引用的提交,可以调用:

    1
    $ git log -S function_name
  • 隐藏合并提交

    按照你代码仓库的工作流程,记录中可能有为数不少的合并提交,它们所包含的信息通常并不多。 为了避免显示的合并提交弄乱历史记录,可以为 log 加上 --no-merges 选项。

撤销操作

撤销操作是非常有用的,但有些撤消操作是不可逆的

git reset 通过把分支记录回退几个提交记录来实现撤销改动。

Git 把 main 分支移回到 C1;现在我们的本地代码库根本就不知道有 C2 这个提交了。

(译者注:在reset后, C2 所做的变更还在,但是处于未加入暂存区状态。)

虽然在你的本地分支中使用 git reset 很方便,但是这种“改写历史”的方法对大家一起使用的远程分支是无效的!

为了撤销更改并分享给别人,我们需要使用 git revert

我们要撤销的提交记录后面多了一个新提交!这是因为新提交记录 C2' 引入了更改 —— 这些更改刚好是用来撤销 C2 这个提交的。也就是说 C2' 的状态与 C1 是相同的。

revert 之后就可以把你的更改推送到远程仓库与别人分享

本地分支撤销用:git reset + <想要回溯的版本(之前的)>

远程分支撤销用:git revert +<当前想要改变的分支(当前的)>

提交错误

有时候我们提交完了才发现漏掉了几个文件没有添加,或者提交信息写错了。 此时,可以运行带有 --amend 选项的提交命令来重新提交:

1
$ git commit --amend

Tips:即用一个 新的提交 替换旧的提交

取消暂存的文件

git reset HEAD <file>… 来取消暂存

1
$ git reset HEAD CONTRIBUTING.md

Tips:git reset 是个危险的命令,如果加上了 --hard 选项则更是如此。

撤消对文件的修改

并不想保留对 CONTRIBUTING.md 文件的修改

1
$ git checkout -- CONTRIBUTING.md

Tips:请务必记得 git checkout — <file> 是一个危险的命令。 你对那个文件在本地的任何修改都会消失——Git 会用最近提交的版本覆盖掉它。 除非你确实清楚不想要对那个文件的本地修改了,否则请不要使用这个命令。

如果你仍然想保留对那个文件做出的修改,但是现在仍然需要撤消,Git 分支](https://git-scm.com/book/zh/v2/ch00/ch03-git-branching) 介绍保存进度与分支,这通常是更好的做法。

记住,在 Git 中任何 已提交 的东西几乎总是可以恢复的。 甚至那些被删除的分支中的提交或使用 --amend 选项覆盖的提交也可以恢复。 然而,任何你未提交的东西丢失后很可能再也找不到了。

远程仓库的使用

查看远程仓库

查看你已经配置的远程仓库服务器,可以运行 git remote 命令。 它会列出你指定的每一个远程服务器的简写。 如果你已经克隆了自己的仓库,那么至少应该能看到 origin ——这是 Git 给你克隆的仓库服务器的默认名字。

可以指定选项 -v,会显示需要读写远程仓库使用的 Git 保存的简写与其对应的 URL;远程仓库会全部列出来(可能不止一个,eg:和几个协作者合作)

添加远程仓库

git clone 命令会自行添加远程仓库。

运行 git remote add <shortname> <url> 添加一个新的远程 Git 仓库,同时指定一个方便使用的简写

1
2
3
4
$ git remote add pb https://github.com/paulboone/ticgit
$ git remote -v
pb https://github.com/paulboone/ticgit (fetch)
pb https://github.com/paulboone/ticgit (push)

可以在命令行中使用字符串 pb 来代替整个 URL

1
$ gir fetch pb

从远程仓库中抓取与拉取

从远程仓库中获得数据,可以执行:

1
$ git fetch <remote>

这个命令会访问远程仓库,从中拉取所有你还没有的数据。 执行完成后,你将会拥有那个远程仓库中所有分支的引用,可以随时合并或查看。

git fetch 命令只会将数据下载到你的本地仓库——它并不会自动合并或修改你当前的工作。 当准备好时你必须手动将其合并入你的工作。

如果你的当前分支设置了跟踪远程分支,可以用 git pull 命令来自动抓取后合并该远程分支到当前分支。

推送到远程仓库

git push <remote> <branch>

只有当你有所克隆服务器的写入权限,并且之前没有人推送过时,这条命令才能生效。 当你和其他人在同一时间克隆,他们先推送到上游然后你再推送到上游,你的推送就会毫无疑问地被拒绝。 你必须先抓取他们的工作并将其合并进你的工作后才能推送。

查看某个远程仓库

想要查看某一个远程仓库的更多信息,可以使用 git remote show <remote> 命令

它同样会列出远程仓库的 URL 与跟踪分支的信息(important)

远程仓库的重命名与移除

可以运行 git remote rename 来修改一个远程仓库的简写名。 例如,想要将 pb 重命名为 paul,可以用 git remote rename 这样做:

1
2
3
$ git remote rename pb paul
$ git remote
paul

这同样也会修改你所有远程跟踪的分支名字。 那些过去引用 pb/master 的现在会引用 paul/master。(nice)

如果因为一些原因想要移除一个远程仓库(你已经从服务器上搬走了或不再想使用某一个特定的镜像了, 又或者某一个贡献者不再贡献了)以使用 git remote removegit remote rm

1
2
3
$ git remote remove paul
$ git remote

一旦你使用这种方式删除了一个远程仓库,那么所有和这个远程仓库相关的远程跟踪分支以及配置信息也会一起被删除。

打标签

Git 可以给仓库历史中的某一个提交打上标签,以示重要。 比较有代表性的是人们会使用这个功能来标记发布结点( v1.0v2.0 等等)

列出标签

列出标签:git tag (可带上可选的 -l 选项 --list)(这个命令以字母顺序列出标签):

1
2
3
$ git tag
v1.0
v2.0

你也可以按照特定的模式查找标签。 例如,Git 自身的源代码仓库包含标签的数量超过 500 个。 如果只对 1.8.5 系列感兴趣,可以运行:

1
2
3
$ git tag -l "v1.8.5*"
v1.8.5
v1.8.5-rc0

Tips: 按照通配符列出标签需要 -l--list 选项如果你只想要完整的标签列表,那么运行 git tag 就会默认假定你想要一个列表,它会直接给你列出来, 此时的 -l--list 是可选的。然而,如果你提供了一个匹配标签名的通配模式,那么 -l--list 就是强制使用的。

创建标签

Git 支持两种标签:轻量标签(lightweight)与附注标签(annotated)。

  • 轻量标签很像一个不会改变的分支——它只是某个特定提交的引用。

    1
    git tag v1.0 c1
  • 附注标签是存储在 Git 数据库中的一个完整对象, 它们是可以被校验的,其中包含打标签者的名字、电子邮件地址、日期时间, 此外还有一个标签信息,并且可以使用 GNU Privacy Guard (GPG)签名并验证。 通常会建议创建附注标签,这样你可以拥有以上所有信息。但是如果你只是想用一个临时的标签, 或者因为某些原因不想要保存这些信息,那么也可以用轻量标签。

轻量标签

一种给提交打标签的方式是使用轻量标签。 轻量标签本质上是将提交校验和存储到一个文件中——没有保存任何其他信息。 创建轻量标签,不需要使用 -a-s-m 选项,只需要提供标签名字:

1
2
3
4
5
$ git tag v1.2-lw
$ git tag
v0.1
v1.2
v1.2-1w

这时,如果在标签上运行 git show,你不会看到额外的标签信息。 命令只会显示出提交信息。

附注标签

创建附注标签: 最简单的方式是当你在运行 tag 命令时指定 -a 选项:

1
2
3
4
5
$ git tag -a v1.4 -m "my version 1.4"
$ git tag
v0.1
v1.3
v1.4

-m 选项指定了一条将会存储在标签中的信息。 如果没有为附注标签指定一条信息,Git 会启动编辑器要求你输入信息。

通过使用 git show 命令可以看到标签信息和与之对应的提交信息.

后期打标签

你也可以对过去的提交打标签。 假设提交历史是这样的:

1
2
3
4
$ git log --pretty=oneline
9fceb02d0ae598e95dc970b74767f19372d61af8 updated rakefile
964f16d36dfccde844893cac5b347e7b3d44abbc commit the todo
8a5cbc430f1a9c3d00faaeffd07798508422908a updated readme

现在,假设在 v1.2 时你忘记给项目打标签,也就是在 “updated rakefile” 提交。 你可以在之后补上标签。 要在那个提交上打标签,你需要在命令的末尾指定提交的校验和(或部分校验和):

1
$ git tag -a v1.2 9fceb02

共享标签

默认情况下,git push 命令并不会传送标签到远程仓库服务器上。 在创建完标签后你必须显式地推送标签到共享服务器上。 这个过程就像共享远程分支一样——你可以运行 git push origin <tagname>

1
$ git push origin v1.5

如果想要一次性推送很多标签,也可以使用带有 --tags 选项的 git push 命令。 这将会把所有不在远程仓库服务器上的标签全部传送到那里。

1
$ git push origin --tags

现在,当其他人从仓库中克隆或拉取,他们也能得到你的那些标签。

Tips: git push 推送两种标签使用 git push <remote> --tags 推送标签并不会区分轻量标签和附注标签, 没有简单的选项能够让你只选择推送一种标签。

删除标签

要删除掉你本地仓库上的标签,可以使用命令 git tag -d <tagname>。 例如,可以使用以下命令删除一个轻量标签:

1
2
$ git tag -d v1.4-lw
Deleted tag 'v1.4-lw' (was e7d5add)

注意上述命令并不会从任何远程仓库中移除这个标签,你必须用 git push <remote> :refs/tags/<tagname> 来更新你的远程仓库:

第一种变体是 git push <remote> :refs/tags/<tagname>

1
2
3
$ git push origin :refs/tags/v1.4-lw
To /git@github.com:schacon/simplegit.git
- [deleted] v1.4-lw

上面这种操作的含义是,将冒号前面的空值推送到远程标签名,从而高效地删除它。

第二种更直观的删除远程标签的方式是:

1
$ git push origin --delete <tagname>

检出标签

如果你想查看某个标签所指向的文件版本,可以使用 git checkout 命令, 虽然这会使你的仓库处于“分离头指针(detached HEAD)”的状态——这个状态有些不好的副作用:

1
$ git checkout 2.0.0

在“分离头指针”状态下,如果你做了某些更改然后提交它们,标签不会发生变化, 但你的新提交将不属于任何分支,并且将无法访问,除非通过确切的提交哈希才能访问。 因此,如果你需要进行更改,比如你要修复旧版本中的错误,那么通常需要创建一个新分支:

1
2
$ git checkout -b version2 v2.0.0
Switched to a new branch 'version2'

如果在这之后又进行了一次提交,version2 分支就会因为这个改动向前移动, 此时它就会和 v2.0.0 标签稍微有些不同,这时就要当心了。

Git Describe

由于标签在代码库中起着“锚点”的作用,Git 还为此专门设计了一个命令用来描述离你最近的锚点(也就是标签),它就是 git describe

Git Describe 能帮你在提交历史中移动了多次以后找到方向;当你用 git bisect(一个查找产生 Bug 的提交记录的指令)找到某个提交记录时,或者是当你坐在你那刚刚度假回来的同事的电脑前时, 可能会用到这个命令。

1
git describe <ref>

<ref> 可以是任何能被 Git 识别成提交记录的引用,如果你没有指定的话,Git 会使用你目前所在的位置(HEAD)。

它输出的结果是这样的:

1
<tag>_<numCommits>_g<hash>

tag 表示的是离 ref 最近的标签, numCommits 是表示这个 reftag 相差有多少个提交记录, hash 表示的是你所给定的 ref 所表示的提交记录哈希值的前几位。

ref 提交记录上有某个标签时,则只输出标签名称

Git别名

配置Git command,看你需要咯

1
2
$ git config --global alias.co checkout
$ git config --global alias.br branch

References