Post

progit 笔记 02 - Git 基础

本部分涵盖 Git 使用中的各种基本命令,包括初始化仓库(repository)、开始或停止跟踪(track)文件、暂存(stage)或提交(commit)更改;配置 Git 来忽略指定的文件和文件模式、撤销错误操作、浏览项目的历史版本以及不同提交(commits)间的差异、推送(push)到远程仓库以及从远程仓库拉取(pull)文件等。

获取 Git 仓库

在现有的项目目录中初始化仓库

1
$ git init

该命令将创建一个 .git 子目录,这个子目录包含初始化的 Git 仓库中所有的必须文件,这些文件是 Git 仓库的骨干。 这时仅做了初始化,项目文件还没有被跟踪。通过以下命令跟踪并提交

1
2
3
$ git add *.c
$ git add LICENSE
$ git commit -m 'initial project version'

这样就得到了一个跟踪着若干文件的 Git 仓库。

克隆现有仓库

使用 git clone 命令克隆一个现有仓库,比如克隆 libgit2:

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

这会在当前目录下创建一个 libgit2 目录,并在该目录下初始化一个 .git 文件夹,从远程仓库拉取所有数据存放在 .git 文件夹内,然后从中读取最新版本的拷贝,并且存放在应该在的位置。

如果想要自定义本地仓库的名字,可以使用下面的命令:

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

这样在本地创建的仓库名字就会变为 mylibgit

检查当前文件状态

使用 git status 命令查看仓库中哪些文件处于什么状态。如果检查刚克隆后的 libgit2 仓库,会看到类似输出:

1
2
3
4
5
$ git status

On branch master

nothing to commit, working directory clean

此时新建一个 README 文件,再次使用 git status 命令时,将看到一个新的未追踪文件:

1
2
3
4
5
6
7
8
9
10
11
$ echo 'My Project' > README
$ git status
On branch master

No commits yet

Untracked files:
  (use "git add <file>..." to include in what will be committed)
    README

nothing added to commit but untracked files present (use "git add" to track)

在状态报告中可以看到 README 文件出现在 untracked files 下面。未跟踪的文件意味着 Git 在之前的快照(提交)中没有这些文件;Git 不会自动将之纳入跟踪范围,除非你明明白白地告诉它“我需要跟踪该文件”。

跟踪新文件

使用 git add 命令开始跟踪一个文件。git add 命令使用文件或目录的路径作为参数;如果参数是目录的路径,该命令将递归地跟踪该目录下的所有文件。比如要跟踪 README 文件:

1
$ git add README

此时再运行 git status 检查状态,会看到 README 文件已被跟踪,并且处于暂存状态:

1
2
3
4
5
6
7
8
$ git status
On branch master

No commits yet

Changes to be committed:
  (use "git rm --cached <file>..." to unstage)
    new file: README

这里可以看到文件在 Changes to be committed 下面,说明是已暂存状态。

暂存已修改的文件

如果修改了 README 文件,再次运行 git status 时将会看到:

1
2
3
4
5
6
7
8
9
10
11
12
13
$ git status
On branch master

No commits yet

Changes to be committed:
  (use "git rm --cached <file>..." to unstage)
    new file: README

Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git restore <file>..." to discard changes in working directory)
    modified: README

这时 README 文件同时出现在等待提交区(暂存区)和未暂存区,是因为 Git 只暂存了上次运行 git add 命令时的那个版本,而不是当前修改过的版本。

Changes not staged for commit: 看到 README 说明已修改了但是没有放到暂存区。要暂存这次更新,需要运行 git add 命令。 这是个多功能命令:可以用它开始跟踪新文件,或者把已跟踪的文件放到暂存区,还能用于合并时把有冲突的文件标记为已解决状态等。这个命令理解为“添加内容到下一次提交中”而不是“将一个文件添加到项目中”要更加合适。

将修改后的 README 文件添加到下一次提交,并再次查看状态:

1
2
3
$ git add README $ git status On branch master
No commits yet
Changes to be committed: (use "git rm --cached ..." to unstage) new file: README

状态简览

git status 命令输出当前仓库状态信息。使用 git status -sgit status --short 获得更为紧凑的状态信息: bash $ git status -s A  NEWADD M  README MM UNSTAGED ?? LICENSE.txt

上面的报告表示,NEWADD 文件前的 A 表示该文件是新添加的并且放入了暂存区,README 前的 M 表示文件被修改了并且放入了暂存区,UNSTAGED 文件前左边的 M 表示被修改并且放入了暂存区,右边的 M 表示文件被修改但还未放入暂存区,LICENSE.txt 前的 ?? 表示文件未被追踪。

忽略文件

创建 .gitignore 文件来忽略日志文件,或者编译过程中创建的临时文件等。

1
2
3
4
5
$ cat .gitignore

*.[oa]

*~

第一行表示忽略后缀名是 o 或者以 a 的文件,第二行告诉 Git 忽略所有以 ~ 符号结尾的文件。

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

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

glob 模式是指 shell 所使用的简化了的正则表达式。

GitHub 有一个十分详细的,针对数十种项目及语言的 .gitignore 文件列表,你可以在 https://github.com/github/gitignore 找到它.

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

git diff 命令查看未暂存的文件更新了哪些部分:

1
2
3
4
5
6
7
8
9
$ git diff
diff --git a/UNSTAGED b/UNSTAGED
index f3229c5..eb1ae45 100644
--- a/UNSTAGED
+++ b/UNSTAGED
@@ -1 +1 @@
-..
+...
(END)

若要查看已暂存的将要提交到下次更新里的内容,可以使用 git diff --cached 或者 git diff --staged(Git >= 1.6.1)命令查看:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
$ git diff --staged
diff --git a/NEWADD b/NEWADD
new file mode 100644
index 0000000..e69de29
diff --git a/README b/README
index 0e6bdc2..e00a688 100644
--- a/README
+++ b/README
@@ -1 +1 @@
-my project.
+my project..
diff --git a/UNSTAGED b/UNSTAGED
index 9c558e3..f3229c5 100644
--- a/UNSTAGED
+++ b/UNSTAGED
@@ -1 +1 @@
-.
+..
(END)

还可以通过 git difftool 命令使用图形化界面分析文件差异

提交更新

当确保修改过的文件都已暂存(通过 git add 添加修改过但还未暂存的文件),就可以准备提交了。运行提交命令 git commit

1
$ git commit

该命令会启动文本编辑器,以便输入本次提交更新的说明。编辑器会显示下面的文本信息:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 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: NEWADD
# modified: README
# modified: UNSTAGED
#
# Changes not staged for commit:
# modified: UNSTAGED
#
# Untracked files:
# LICENSE.txt
#

默认的提交信息会包括最后一次运行 git status 的输出,放在注释行里,并且开头有一空行,用来输入提交说明。另外可以使用 git commit -m 来将提交信息和命令放在同一行进行提交:

1
2
3
4
$ git commit -m "Story 182: Fix benchmarks for speed"
[master c800db7] Story 182: Fix benchmarks for speed
 3 files changed, 2 insertions(+), 2 deletions(-)
 create mode 100644 NEWADD

此时便完成了提交。

跳过使用暂存区域

使用 git commit -a -m 来跳过暂存步骤,Git 会自动把所有已经跟踪过的文件暂存起来一并提交:

1
2
3
4
5
6
7
8
9
10
11
12
$ git status
On branch master
Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git restore <file>..." to discard changes in working directory)
    modified: CONTRIBUTING.md

no changes added to commit (use "git add" and/or "git commit -a")

$ git commit -a -m "added new benchmarks"
[master 4520c36] added new benchmarks
 1 file changed, 1 insertion(+)

移除文件

要从 Git 中移除某个文件,要从已跟踪的文件清单中移除(从暂存区移除),然后提交。使用 git rm 命令,连带从工作目录中删除指定文件,这样以后就不会出现在未跟踪文件清单中了。

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

1
2
3
4
5
6
7
8
9
$ rm PROJECTS.md
$ git status
On branch master
Changes not staged for commit:
  (use "git add/rm <file>..." to update what will be committed)
  (use "git restore <file>..." to discard changes in working directory)
    deleted: PROJECTS.md

no changes added to commit (use "git add" and/or "git commit -a")

然后需要再运行 git rm 操作来移除此文件,这样下次提交时,该文件就不再纳入版本管理了。

1
2
3
4
5
6
$ git rm PROJECTS.md
$ git status
On branch master
Changes to be committed:
  (use "git restore --staged <file>..." to unstage)
    deleted: PROJECTS.md

如果删除之前,已修改过并且放入了暂存区,必须使用强制删除选项 -f

如果我们想把文件从暂存区删除,但是不想删除本地文件的话,使用 --cached 选项:

1
$ git rm --cached README

移动文件

要在 Git 中修改文件名,可以使用下面的命令:

1
$ git mv file_from file_to

此时查看状态信息:

1
2
3
4
5
6
$ git mv README README.md
$ git status
On branch master
Changes to be committed:
  (use "git restore --staged <file>..." to unstage)
    renamed: README -> README.md

该命令相当于:

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

查看提交历史

使用 git log 命令查看并回顾提交历史:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
$ git log
commit ca82a6dff817ec66f44342007202690a93763949 (HEAD -> master, origin/master, origin/HEAD)
Author: Scott Chacon <schacon@gmail.com>
Date: Mon Mar 17 21:52:11 2008 -0700

    changed the verison number

commit 085bb3bcb608e1e8451d4b2432f8ecbe6306e7e7
Author: Scott Chacon <schacon@gmail.com>
Date: Sat Mar 15 16:40:33 2008 -0700

    removed unnecessary test code

commit a11bef06a3f659402fe7563abf99ad00de2209e6
Author: Scott Chacon <schacon@gmail.com>
Date: Sat Mar 15 10:31:28 2008 -0700

    first commit
(END)

使用 -p 参数,来显示每次提交的内容差异。也可以加上 -2 来显示仅最近2次提交:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
$ git log -p -2
commit ca82a6dff817ec66f44342007202690a93763949 (HEAD -> master, origin/master, origin/HEAD)
Author: Scott Chacon <schacon@gmail.com>
Date: Mon Mar 17 21:52:11 2008 -0700

    changed the verison 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@gmail.com"
     s.summary = "A simple gem for using Git in Ruby code."

commit 085bb3bcb608e1e8451d4b2432f8ecbe6306e7e7
Author: Scott Chacon <schacon@gmail.com>
Date: Sat Mar 15 16:40:33 2008 -0700

    removed unnecessary test code

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

使用 --stat 选项,显示每次提交的简略信息:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
$ git log --stat
commit ca82a6dff817ec66f44342007202690a93763949 (HEAD -> master, origin/master, origin/HEAD)
Author: Scott Chacon <schacon@gmail.com>
Date: Mon Mar 17 21:52:11 2008 -0700

    changed the verison number

 Rakefile | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

commit 085bb3bcb608e1e8451d4b2432f8ecbe6306e7e7
Author: Scott Chacon <schacon@gmail.com>
Date: Sat Mar 15 16:40:33 2008 -0700

    removed unnecessary test code

 lib/simplegit.rb | 5 -----
 1 file changed, 5 deletions(-)

commit a11bef06a3f659402fe7563abf99ad00de2209e6
Author: Scott Chacon <schacon@gmail.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(+)
(END)

使用 --pretty=<> 选项来用不同的方式展示提交历史,如:

1
2
3
4
5
$ git log --pretty=online
ca82a6dff817ec66f44342007202690a93763949 (HEAD -> master, origin/master, origin/HEAD) changed the verison number
085bb3bcb608e1e8451d4b2432f8ecbe6306e7e7 removed unnecessary test code
a11bef06a3f659402fe7563abf99ad00de2209e6 first commit
(END)

使用 format 参数来定制显示的记录格式:

1
2
3
4
5
$ git log --pretty=format:"%h - %an, %ar : %s"
ca82a6d - Scott Chacon, 12 years ago : changed the verison number
085bb3b - Scott Chacon, 12 years ago : removed unnecessary test code
a11bef0 - Scott Chacon, 12 years ago : first commit
(END)

更多选项查看 pretty-formats

如果使用 onlineformat 选项时配合 --graph 使用,会添加一些 ASCII 字符串来形象的展示分支、合并历史:

1
$ git log --pretty=online --graph

git log 详细参数参考 git-log

撤消操作

有些撤消操作是不可逆的。 这是在使用 Git 的过程中,会因为操作失误而导致之前的工作丢失的少有的几个地方之一。

当我们提交完成后发现漏掉了文件,或者提交信息填写错误,可以运行带有 --amend 选项的提交命令,重新提交。

1
2
3
4
5
$ git commit -m 'initial commit'

$ git add forgotten_file

$ git commit --amend

这个命令会将暂存区的文件提交;如果暂存区没有文件(自上次提交后没有修改,如上次提交后马上执行此命令),那么快照会保持不变,只是提示修改提交信息。最终只会有一个提交,第二次提交将替代第一次提交。

取消暂存的文件

使用 git reset HEAD <file>... 来取消暂存某个文件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
$ git status
On branch master
Changes to be committed:
(use "git reset HEAD ..." 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 ..." to unstage)
renamed: README.md -> README
Changes not staged for commit:
(use "git add ..." to update what will be committed)
(use "git checkout -- ..." to discard changes in working directory)
modified: CONTRIBUTING.md
modified: CONTRIBUTING.md

撤消对文件的修改

使用 git checkout -- <file>... 来把文件还原到上次提交时的样子。如还原 CONTRIBUTING.md 文件:

1
2
3
4
5
6
7
8
9
10
11
12
13
$ git checkout -- CONTRIBUTING.md

$ git status

On branch master

Changes to be committed:

  (use "git reset HEAD <file>..." to unstage)



    renamed: README.md -> README

git checkout -- [file] 是一个危险的命令,Git 只是拷贝了另一个文件来覆盖它,所以对它做的修改历史都会消失。

远程仓库的使用

查看远程仓库

使用 git remote 命令查看已经配置了的远程仓库服务器。如果你试着在自己克隆的项目目录运行 git remote 那么至少能看到 origin:这是 Git 给克隆的仓库服务器的默认名字: ```bash $ git clone https://github.com/schacon/ticgit $ cd ticgit $ git remote

使用 git remote -v 会显示远程仓库的 Git 简写以及对应的 URL。

1
2
3
4
5
$ git remote -v

origin https://github.com/schacon/ticgit (fetch)

origin https://github.com/schacon/ticgit (push)

如果远程仓库不止一个(与多个协作者合作的仓库),那么输出将会像是这样:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
$ cd grit
$ git remote -v

bakkdoor https://github.com/bakkdoor/grit (fetch)

bakkdoor https://github.com/bakkdoor/grit (push)

cho45 https://github.com/cho45/grit (fetch)

cho45 https://github.com/cho45/grit (push)

defunkt https://github.com/defunkt/grit (fetch)

defunkt https://github.com/defunkt/grit (push)

koke git://github.com/koke/grit.git (fetch)

koke git://github.com/koke/grit.git (push)

origin git@github.com:mojombo/grit.git (fetch)

origin git@github.com:mojombo/grit.git (push)

我们可以拉取任何一个用户的贡献。

添加远程仓库

运行 git remote add <shortname> <url> 添加一个远程仓库,同时指定一个简写:

1
2
3
4
$ 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。如想要拉取 paulboone 的仓库,只需要输入:

1
2
3
4
5
6
7
8
$ 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

然后就可以在本地通过 pb/master 访问到了。

从远程仓库中抓取与拉取

如上面所见,从远程仓库中获得数据,可以执行 git fetch [remote-name] 命令。这个命令会访问远程仓库,拉取本地没有的数据。执行完成后,可以随时合并或查看。

如果是使用 git clone 命令克隆了一个仓库,命令会自动将其添加为远程仓库并以 origin 为简写。所以 git fetch origin 会抓取 git clone 后(或上一次 git fetch 后新推送的所有工作。

需要注意的是 git fetch 命令只会将数据拉取到本地,但是不会自动合并或修改当前分支,需要你自己准备好的时候手动合并。

如果你需要从默认远程分支上抓取并合并,可以使用 git pull 命令。该命令自动抓取默认的远程仓库分支,并尝试合并到当前本地分支。一般情况下,git clone 命令会自动设置本地 master 分支跟踪并克隆远程仓库的 master 分支(或其他名字的默认分支)。

推送到远程仓库

当你想要分享项目时,必须将其推送到上游,使用 git push [remote-name] [branch-name] 命令来操作。比如当你想要将本地的 master 分支推送到远程 origin 服务器时(这一般是克隆时命令自动设置的远程服务器名字),那么运行如下代码:

1
$ git push origin master

只有你拥有远程仓库的写入权限,并且之前没有人推送过时,该命令才能生效。如果在你克隆后,其他人先推送了项目到上游,此时你需要先将他们的工作拉取下来并合并到你的工作后,才能推送成功。

查看远程仓库

如果想要查看远程仓库的更多信息,可以使用 git remote show [remote-name] 命令。如查看 origin

1
2
3
4
5
6
7
8
9
10
11
12
$ 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 分支(HEAD branch: master),并且如果你运行 git pull,就会抓取所有远程引用,然后将远程 master 分支合并到本地 master 分支(master merges with remote master)。

如果是 Git 的重度使用着,将会通过 git remote show 看到更多信息:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
$ git remote show origin
* remote origin
  URL: https://github.com/my-org/complex-project
    Fetch URL: https://github.com/my-org/complex-project
    Push URL: https://github.com/my-org/complex-project
    HEAD branch: master
    Remote branches:
      master tracked
        dev-branch tracked
        markdown-strip tracked
        issue-43 new (next fetch will store in remotes/origin)
        issue-45 new (next fetch will store in remotes/origin)
        refs/remotes/origin/issue-11 stale (use 'git remote prune' to remove)
      Local branches configured for 'git pull':
      dev-branch merges with remote dev-branch
        master merges with remote master
      Local refs configured for 'git push':
      dev-branch pushes to dev-branch (up to date)
        markdown-strip pushes to markdown-strip (up to date)
        master pushes to master (up to date)

这里输出显示了当你在特定分支上执行 git push 时会将本地项目推送到哪个远程分支,还列出了哪些分支不在本地,哪些远程分支已经从服务器删除,还有当你执行 git pull 时哪些分支会自动合并。

远程仓库的移除与重命名

重命名远程引用,可以通过 git remote rename 修改。例如将上面的 pb 重命名为 paul 可以通过下面命令实现: bash $ git remote rename pb paul $ git remote origin paul

需要注意的是这也同样会修改远程分支中的名字,那些之前引用 pb/master 的现在会引用 paul/master

如果需要移除一个远程仓库,可以使用 git remote rm 命令: bash $ git remote rm paul $ git remote roigin

打标签

列出标签

使用 git tag 命令列出标签: bash $ git tag v0.1 v1.3

该命令默认以字幕顺序列出标签。

你也可以使用特定的模式查找标签,如查看 Git 自身源代码仓库的 1.8.5 系列,可以运行:

1
2
3
4
5
6
7
8
9
10
11
$ 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 Privace Guard(GPG)签名与验证。通常建议创建附注标签,这样就可以拥有以上所有信息;但如果想要临时标签,或者不想保存这些信息,轻量标签也是可以的。

附注标签

在运行 git tag 时指定 -a 选项,来创建一个附注标签:

1
2
3
$ git tag -a v1.4 -m 'my version 1.4'
$ git tag
v1.4

-a 选项指定了一条需要存储在标签中的信息,如果没有指定信息,Git 会通过运行编辑器来要求你输入信息。

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

1
2
3
4
5
6
7
8
9
10
11
$ git show v1.4
Tagger: Ben Straub <ben@straub.cc>
Date: Sat May 3 20:19:12 2014 -0700

my version 1.4

commit ca82a6dff817ec66f44342007202690a93763949
Author: Scott Chacon <schacon@gee-mail.com>
Date: Mon Mar 17 21:52:11 2008 -0700

    changed the version number

轻量标签

轻量标签本质上是将提交校验和存储到一个文件中 - 没有保存任何其他信息。创建轻量标签只需要提供标签名字: bash $ git tag v1.4-lw $ git tag v1.4 v1.4-lw

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

1
2
3
4
5
6
$ git show v1.4-lw
commit ca82a6dff817ec66f44342007202690a93763949
Author: Scott Chacon <schacon@gee-mail.com>
Date: Mon Mar 17 21:52:11 2008 -0700

    changed the version number

后期打标签

通过指定提交的校验和,来对历史提交进行打标签。

比如一个这样的提交历史:

1
2
3
4
5
$ git log --pretty-oneline
15027957951b64cf874c3557a0f3547bd83b3ff6 Merge branch 'experiment'
a6b4c97498bd301d84096da251c98a07c7723e65 beginning write support
0d52aaab4479697da7686c15f77a3d64d9165190 one more thing
9fceb02d0ae598e95dc970b74767f19372d61af8 updated rakefile

假设在 v1.2 时忘记打标签,也就是在 updated rakefile 提交,可以在命令末尾添加校验和(或部分校验和): bash $ git tag -a v1.2 9fceb02

通过 git show v1.2 可以看到已经打上了标签:

1
2
3
4
5
6
7
8
9
10
11
$ git show v1.2
tag v1.2
Tagger: Scott Chacon <schacon@gee-mail.com>
Date: Mon Feb 9 15:32:16 2009 -0800

version 1.2
commit 9fceb02d0ae598e95dc970b74767f19372d61af8
Author: Magnus Chacon <mchacon@gee-mail.com>
Date: Sun Apr 27 20:43:35 2008 -0700

    updated rakefile

共享标签

默认情况下 git push 命令不会推送标签到远程服务器。可以显式的将标签推送到共享服务器:

1
2
3
4
5
6
7
8
$ git push origin v1.5
Counting objects: 14, done.
Delta compression using up to 8 threads.
Compressing objects: 100% (12/12), done.
Writing objects: 100% (14/14), 2.05 KiB | 0 bytes/s, done.
Total 14 (delta 3), reused 0 (delta 0)
To git@github.com:schacon/simplegit.git
* [new tag] v1.5 -> v1.5

如果需要一次推送多个标签,可以使用带有 --tags 选项的 git push 命令。这将会把所有不在远程仓库服务器上的标签全部推送过去。

1
2
3
4
5
6
7
$ 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] 在特定的标签上创建一个新分支:

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

当然,如果在这之后又进行了一次提交,version2 分支会因为改动向前移动,那么 version2 分支就和 v2.0.0 标签有些不同了。

Git 别名

Git 并不会在你输入部分命令时自动推断你想要的命令。如果不想每次输入完整的 Git 命令,可以通过 git config 文件来为每个命令设置一个别名。比如:

1
$ git config --global alias.br branch

这意味着,当你需要输入 git commit 命令时,只需要输入 git ci

This post is licensed under CC BY 4.0 by the author.