Git 基础

Git 基础

深入了解 Git,推荐阅读官方的《Pro Git》

常用命令记录

# 本地检出远程分支
$ git checkout -b <local_branch_name> origin/<origin_branch_name>

# 删除所有未跟踪的文件(主要是修改后未跟踪文件无法被git checkout .时)
$ git clean -nf  # 首先查看要删除的文件
$ git clean -f   # 执行删除操作

一、Git 纵览

1. 什么是 Git

git(/ɡɪt/)是一个分布式版本控制软件,最初由林纳斯·托瓦兹创作,于2005年以GPL发布。最初目的是为更好地管理Linux内核开发而设计。
目前 git 已经被广泛用于管理项目开发,是当今最流行、最先进的分布式版本控制系统。

GitHubGitLab 都是通过 Git 进行版本控制的软件源代码托管服务平台,GitLab 可以部署私有化 Git Server。
国内知名的 Git 源码托管平台有码云Coding 等。

2. 为什么使用 Git

  • 速度 - 快
    Git 基于 C 语言开发,而且版本库本地化;有能力高效管理类似 Linux 内核一样的超大规模项目。
  • 完全分布式 - 离线工作
    对于像 svn 的集中式版本控制系统来说,没有互联网、没有连接到中央仓库,甚至说中央服务器宕机,所有人就没有办法很好的协同工作。
    而 git 作为分布式系统,几乎所有的东西都可以在本地完成;当恢复互联网连接后即可与服务器同步。
  • 分支 - 灵活
    Git 可以创建许多分支,每个 branch 都是独立的;当我们需要修改代码的时候,commit 也只是对本地分支的修改。分支可以非常方便的合并。

二、安装和基本流程

1. 下载安装

可以从官方网站 https://git-scm.com/downloads下载对应系统的 git 程序。
基本一路 next 即可,也可以参见内网的安装图解

在命令行输入git --version,看到版本号即表示 git 已经配置完毕。

$ git --version
git version 2.24.0.windows.2

图形化
安装完 git 客户端后,可以通过命令行进行 git 操作。
当然 git 也有一些图形化工具,可以试试 Sourcetree
除了第三方 GUI 工具, 现代 IDE 也基本都内置了 Git,比如 JetBrains 系列软件的 VCS,VSCode 的 SOURCE CONTROL 模块等。
以下文档将会以 Windows10 环境,Git Bash + WebStorm 的方式介绍。

2. 基本工作流程

sequenceDiagram participant Working Directory participant Staging Area participant .git directory(Repository) .git directory(Repository)->>Working Directory: Checkout the project Working Directory->>Staging Area: Stage Fixes Staging Area->>.git directory(Repository): Commit

基本的 Git 工作流程如下:

  1. 在工作目录中修改文件。
  2. 暂存文件,将文件的快照放入暂存区域(Index)。
  3. 提交更新,找到暂存区域的文件,将快照永久性存储到 Git 仓库目录(Repository)。

三、Git clone(克隆)

1. 克隆现有仓库

通常加入一个项目,这个项目或空,或已经有了源码,都已经在仓库新建完成。
这时候我们就需要克隆这个仓库到本地以开始进行开发。

值得注意的是,如果你使用 clone 命令克隆了一个仓库,命令会自动将其添加为远程仓库并默认以 origin 为简写。

比如在内网 git 仓库有一个的空项目(仅包含 README.md),项目管理员(Owner/Maintainer)已经添加你到项目中(Guest/Reporter/Developer/Maintainer),登录自己的源码托管平台账户(GitLab),就可以看到这个项目:

1.1 通过 HTTP

点击 Clone with HTTP 复制仓库地址,然后在命令行执行:

# git clone [仓库HTTP地址] [本地文件夹名称]
$ git clone http://192.168.0.252:8000/jehorn/my-git-demo.git my-demo

# 如果是首次从该仓库克隆项目
# 系统会提示你输入凭证
# 输入正确后项目将会被克隆到指定目录

这样就克隆了一个项目到本地,并且和远程仓库关联。
注意:如果是开源项目,克隆是不需要凭证的。

凭证存储
如果你是 Windows 用户,用户凭证存储在 控制面板 - 凭据管理器 - Windows 凭据 中:

当你的 GitLab 账号修改了密码后,可以到这里重置密码。

1.2 通过 SSH 密钥

有时候我们不想输入密码,或者部署 DevOps 工作流时,输入密码不方便,可以考虑使用 ssh 密钥克隆项目:

# 1. 首先进入 .ssh 目录看看是否已经生成
$ cd ~/.ssh && ls

# 如果已经存在 id_rsa 和 id_rsa.pub 表示密钥已经存在
# 跳过第2步

# 2. 生成密钥
# -t 参数可以指定其他加密类型 默认RSA
# -C 参数指定注释
$ ssh-keygen -C "youremail@example.com"

# 3. 拷贝密钥到仓库
# 查看 id_rsa.pub 文件
# 并将其文本粘贴至仓库个人设置中
$ cat ~/.ssh/id_rsa.pub

![](https://img2018.cnblogs.com/blog/1012606/201911/1012606-20191119134704276-118213713.gif

此时你的电脑的公钥已经添加到了仓库中,可以无需密码克隆、提交代码了。
在仓库首页,复制 Clone with SSH 的路径:

$ git clone git@192.168.0.252:jehorn/my-git-demo.git my-demo

2. 在现有目录中初始化仓库(不推荐)

这个主要是用于新建仓库场景,对现有的项目打算使用 Git 来进行管理。
以下命令不推荐的原因是操作比较复杂,推荐直接在远程仓库新建项目,克隆到本地空文件夹,然后将现有项目文件粘贴至空文件夹中再提交来初始化项目。

# 1. 在项目根目录下初始化
$ git init

# 2. 如果项目根目录已经存在文件
# 应该开始对这些文件进行跟踪
$ git add .
$ git commit -m "initial project version"

# 3. 关联远程仓库
$ git remote add origin git@192.168.0.252:jehorn/my-git-demo.git

# 4. 拉取远程仓库的文件
# --allow-unrelated-histories 表示允许不相关历史合并
$ git pull origin master --allow-unrelated-histories

# 5. 提交本地文件到远程仓库
$ git push origin master

四、简单的分支操作

现在我们手上有了一个真实项目的 Git 仓库,并从这个仓库中取出了所有文件的工作拷贝。
通常克隆的项目的默认分支是 master,如果在多人协作开发,要做比较合理的分支管理的情况下,是不应该直接在 master 分支修改的。

具体的分支管理将在后面的分支策略中,这里只是介绍一下一些简单的分支操作命令。

1. 查看分支

# 查看本地分支
$ git branch

# 查看全部分支(包括 origin 分支)
$ git branch -a

在 WebStorm 中点击右下角的分支名称即可看到所有分支。

2. 新建分支

# 新建并检出分支
$ git checkout -b iss53

# 以上命令相当于
$ git branch iss53
$ git checkout iss53

在 WebStorm 中可以这样新建分支:

3. 切换分支

# 切换分支
# 注意切换分支前 stage 或 commit 自己的更改
$ git checkout master

在 WebStorm 中可以这样切换分支:

4. 删除分支

# 删除本地分支
$ git branch -d iss53

# 删除远程分支
# 如果已经检出远程分支到本地
# 这里并不会删除本地分支
$ git push origin --delete test1
To 192.168.0.252:jehorn/my-git-demo.git
- [deleted]         test1

在 WS 删除分支:

5. 分支合并

# 合并本地分支 iss53 到当前所在分支
# 假如你当前在 master 分支
# 执行下述命令将会把 iss53 分支合并到 master
$ git merge iss53

# 合并远程分支 origin/test1 到当前分支
# 首先获取更新
$ git fetch
# 合并远程 test1 分支至当前分支
$ git merge origin/test1

# 推荐还是先检出远程分支
# 拉取更新后切换回当前分支
# 然后执行本地分支合并

WS 上合并某分支至当前分支:

6. 解决冲突

不推荐直接编辑文本,可以通过WS的可视化工具合并:

VCS -> Git -> Resolve Conflicts

五、Git 拉取

1. fetch

git fetch 是将远程主机的最新内容拉到本地,用户在检查了以后决定是否合并到工作本机分支中,这一步骤可以叫做获取

# 将远程仓库全部更新取回本地
$ git fetch <远程主机(可选/默认 origin)>

# 取回指定分支的更新
$ git fetch <远程主机> <分支名>

# 查看取回的更新内容
$ git log -p FETCH_HEAD

2. pull

git pull 是将远程主机的最新内容拉下来后直接合并,可以称为拉取
git pull 过程可以理解为:

# 获取远程 master 分支的最新内容
$ git fetch origin master
# 将获取到的内容合并至当前分支
$ git merge FETCH_HEAD
git pull <远程主机> <远程分支>:<本地分支(如果远程分支与当前分支合并, 该参数可省略)>

# 比如拉取远程 master 并合并到当前分支
# 为保证按照预期 确保你此时在本地 master 分支
$ git pull origin master

WS 拉取代码:

六、Git 提交/保存

基于文件状态,基本工作流程如下图所示:

sequenceDiagram participant Untracked participant Unmodified participant Modified participant Staged Untracked->>Staged: Add the file Unmodified->>Modified: Edit the file Modified->>Staged: Stage the file Staged->>Unmodified: Commit Unmodified->>Untracked: Remove the file

1. add

git add命令用于将文件添加为staged(已暂存)状态

# 暂存单个文件
$ git add <文件名>

# 暂存所有变化
# 包括 modified(已修改)和 new(新添加)
# 不包括 deleted(已删除)的文件
$ git add .

# 暂存已跟踪的变化
# 暂存 modified(已修改)和 deleted(已删除)文件
# 不包括 new(新文件)
$ git add -u

# 暂存所有变化
$ git add -A

在图形化界面中,通常把 add 包括在 commit 中。

2. commit

# 提交已暂存的更改到本地仓库
$ git commit -m <注释>

3. push

# 先拉取远程更新
$ git pull origin master

# 推送本地更新
$ git push origin master

3. stash(储藏)

经常有这样的事情发生,当你正在进行项目中某一部分的工作,里面的东西处于一个比较杂乱的状态,而你想转到其他分支上进行一些工作。问题是,你不想提交进行了一半的工作,否则以后你无法回到这个工作点。解决这个问题的办法就是 git stash 命令。

假设有一个项目,再工作区中工作了一半,突然测试要求你紧急修复一个 bug:

# 查看当前工作区状态
$ git status
On branch master
Your branch is up to date with 'origin/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:   index.html

这时我们执行git stash命令储藏当前工作状态:

$ git stash

# 再查看工作区状态
$ git status
On branch master
Your branch is up to date with 'origin/master'.

nothing to commit, working tree clean
# 储藏变更 包括新增的 untracked 文件
# message 是备注
$ git stash save "message" --include-untracked

可以看到此时工作区是干净的了。
此时你可以随意切换到其他分支,进行 bug 修复等紧急工作。

# 查看已经保存的 stash
$ git stash list
stash@{0}: WIP on master: dd164f5 add .gitignore

# 重新应用保存的状态
$ git stash apply stash@{0} # stash@{0} 是可选参数 如果不指定会默认应用最新的一个
On branch master
Your branch is up to date with 'origin/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:   index.html

可以看到我们之前的修改又回到了工作目录中。
以上示例是在同一个分支储藏和应用的,当然它也可以在一个分支创建,在另一个分支应用,但是可能会有冲突
stash 也可以被删除。

# 删除 stash
$ git stash drop stash@{0}
Dropped stash@{0} (42dc836537c70cf5a1bf3169db98a24b030e9745)

$ git stash list
# 显示为空 已经被删除

拓展
stash 可以直接检出一个新的分支,便于之后的其它操作:

$ git stash branch test01
Switched to a new branch 'test01'
On branch test01
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:   index.html

no changes added to commit (use "git add" and/or "git commit -a")
Dropped refs/stash@{0} (c976f3681b21e091b7380708977f948dea8963c1)

可以看到检出了一个新分支test01并自动删除了 stash。

了解更多 stash。

5. .gitignore

gitignore - Specifies intentionally untracked files to ignore.
忽略提交到远程仓库的文件的配置。

这是存在于工作区目录根路径下的一个文件,如果在 Windows 系统下看不到,可以设置资源管理器的隐藏文件可见

常见的比如:

# 忽略 IDE 配置文件
/.idea
/.vscode

# 忽略 依赖包
/node_modules

七、Git 分支策略

1. Git Flow

  • 长期分支
    • Master
    • Develop
  • 功能分支
    • Feature Branch
    • Release Branch
    • Hotfix Branch

2. GitHub Flow

  • 只有一个长期分支 master ,而且 master 分支上的代码,永远是可发布状态,一般 master 会设置 protected 分支保护,只有有权限的人才能推送代码到 master 分支。
  • 如果有新功能开发,可以从 master 分支上检出新分支。
  • 在本地分支提交代码,并且保证按时向远程仓库推送。
  • 当你需要反馈或者帮助,或者你想合并分支时,可以发起一个 pull request。
  • 当 review 或者讨论通过后,代码会合并到目标分支。
  • 一旦合并到 master 分支,应该立即发布。

3. GitLab Flow

这个分支策略比较适用服务端,包含了测试环境,预发环境,正式环境,一个环境建一个分支。
要按环境依次推送,确保代码被充分测试过,才会从上游分支合并到下游分支。除非是很紧急的情况,才允许跳过上游分支,直接合并到下游分支。

八、Git 回滚/撤销

1. add 前

撤销修改(revert changes)

使用git checkout -- <file>...命令可以撤销对指定文件的修改。
使用git checkout .命令可以撤销所有更改。

假设一个仓库有以下状态:

$ 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)
        modified:   index.html # 未暂存的修改
        deleted:    text.txt # 未暂存的删除
        
Untracked files:
  (use "git add <file>..." to include in what will be 
committed)
        index.css # 未暂存的新增

执行git checkout .命令来取消所有更改:

$ git checkout .
Updated 2 paths from the index

# 再次查看状态
$ git status
On branch master

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

可以看到未暂存的修改未暂存的删除已经被抹去了,而未追踪(Untracked)的文件依然存在。

你需要知道 git checkout -- [file] 是一个危险的命令。除非你确实清楚不想要那些变更了,否则不要使用这个命令。

在WS中,可以通过VCS -> Git -> Revert...选项打开撤销更改的对话框:

点击Revert按钮即可。

2. add 后且 commit 前回滚

取消暂存的文件

当不小心暂存了额外的文件,想要取消暂存,可以使用git restore --staged <file>...命令。

比如:
我们在项目目录下新增了一个index.css文件,同时修改了index.html文件;这时要暂存修改,顺手执行了:

# 暂存所有修改和新增
$ git add .

# 查看 本地仓库 状态
$ git status

On branch master
Changes to be committed:
    (use "git restore --staged <file>..." to unstage)
        new file:   index.css
        modified:   index.html

然后我们取消暂存index.css文件:

$ git restore --staged index.css

$ git status
On branch master

Changes to be committed:
  (use "git restore --staged <file>..." to unstage)
        modified:   index.html

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

通过git status命令我们看到了,index.css已经是未暂存状态了。

3. commit 后且 push 前回滚

3.1 commit 后追加改动/备注更正
$ git commit --amend

这个命令会将暂存区中的文件重新提交。
如果自上次提交以来你还未做任何修改(例如,在上次提交后马上执行了此命令),那么快照会保持不变,而你所修改的只是提交信息。

下面做个示例

# 假如某仓库 我们新增了一个文件
# 我们执行了一次提交
$ git add index.html

$ git commit -m "add index.html"
[master a54024b] add index.html
1 file changed, 12 insertions(+)
create mode 100644 index.html

# 查看刚才的提交
$ git log
commit a54024b987f9637c10cbe2a1e35e7cca71eb03e7 (HEAD -> master)
Author: Jehorn <gujh@bbdtek.com>
Date:   Thu Nov 14 11:38:41 2019 +0800
    add index.html

此时提交完我们又发现有个文件没有添加到暂存区(add)而没有提交:

# 查看当前项目还有那些改动
$ git diff
# 可以看到修改了 text.txt 文件
diff --git a/text.txt b/text.txt
index 2435860..33204a3 100644
--- a/text.txt
+++ b/text.txt
@@ -1 +1,2 @@
 Hi~
+How r u?

# 这时候我们执行 commit amend
# 来追加提交这些更改 并且修改 commit 备注
# 到上一次提交中
$ git add text.txt
$ git commit --amend

# 执行完 commit amend 后
# 命令行会自动从 vim 打开一个修改备注
# 如下图所示

通过 vim 修改这个文件,添加了新的备注后,保存并退出(wq)。就成功提交了。
可以通过 git log来查看:

$ git log
# 可以看到我们追加的更改已经在上一次提交里了
commit f5c34cb3fb00d88e7ab0393837c8fe6f7b8f6d0b (HEAD -> master)
Author: Jehorn <jehorn@gmail.com>
Date:   Thu Nov 14 11:38:41 2019 +0800
    add index.html; update text.txt
3.2 撤销 commit

Git中 HEAD 指向的版本就是当前版本,所以可以使用 git reset来重置 HEAD 以及它所指向的 branch 的位置。
使用 git log 可以查看提交历史,可以确定要回退到哪次提交。
使用 git reflog 查看历史命令,可以在回退后再回到回退前的提交。

这里先使用 --hard 模式演示版本回退。需要注意hard模式可能会导致工作区修改丢失。
还是强调一下,这里的回滚是在 push 前;要回滚已经 push 的 commit,请参见《4. push》后回滚 这一节。

假设有一个仓库,已经有了几次提交,可以使用 git log 命令查看:

$ git log

# commit 后面的就是本次提交的 id
# 可以用于 撤销提交操作
# 通常只需要输入前几位 git 就可以自动识别
commit e7e3c0694265835fca12b66bc2605c01474e5767 (HEAD -> master) # 最近一次提交 和当前工作区内容一致
Author: Jehorn <jehorn@gmail.com>
Date:   Mon Nov 18 16:08:04 2019 +0800
    add index.css

commit f5c34cb3fb00d88e7ab0393837c8fe6f7b8f6d0b
Author: Jehorn <jehorn@gmail.com>
Date:   Thu Nov 14 11:38:41 2019 +0800
    add index.html; update text.txt
    
commit b271fcd5023b4dd1379143891835b4a6be005b08
Author: Jehorn <jehorn@gmail.com>
Date:   Thu Nov 14 10:57:49 2019 +0800
    add gitignore

commit 6925a90efa3ec6d300cd966837154b3733d3c3cc 
(origin/master, origin/HEAD)
Author: Jehorn <jehorn@gmail.com>
Date:   Wed Nov 13 17:56:02 2019 +0800
    add text.txt
回退版本

现在我们想要撤销最近一次提交(意思是回到倒数第二次提交,也可以说丢弃最后一次提交的修改):

$ git reset --hard f5c34cb
# 或者
# $ git reset --hard HEAD^
HEAD is now at f5c34cb add index.html; update text.txt

查看工作区日志(git log),可以看到提交e7e3c06已经不见了。

撤销回退版本

此时可能又有新的想法,不想抛弃那一次更改了,想要再回到回退之前版本:

# 首先使用 reflog 查看历史记录
$ git reflog
f5c34cb (HEAD -> master) HEAD@{0}: reset: moving to HEAD^
e7e3c06 HEAD@{5}: commit: add index.css # 这一条记录就是当初 commit 的记录

# 然后再 reset HEAD 到那一次提交
$ git reset --hard e7e3c06

查看工作区目录,可以发现index.css又回来了。

3.3 关于 git reset

上面我们都是用git reset --hard <id> 来示例的,这个 --hard是一种模式,还有其它两种模式:--soft--mixed(默认)

hard

将 HEAD 和 Index 和 workingcopy 重置到某一 commit,中间的 commit 修改记录和 Staging area 的修改文件和 Working copy 的修改文件将全部丢失,并更新到这一 commit 的状态。具有破坏性。

soft

改变 HEAD。将 HEAD 重置到某一 commit,并把中间的 commit 记录放到 Index 中。

mixed

改变 HEAD 和 Index,它将重置 HEAD 到某一 commit,并且将中间的 commit 记录和 Staging area 文件都返回到 Working copy 中。

4. push 后回滚

如果是你自己的分支,完全还可以使用 git reset --hard 来回滚,即便已经 push 到远程仓库。
只不过回滚后再提交 git 会提示你本地仓库版本落后于 remote 仓库,不能提交。这时通过:

# 强制推送
git push -f

强制推送可以将落后与 remote 仓库的本地仓库同步到服务器。

但是如果 git 仓库禁止强推,或者在公共分支上,想要做回滚就需要使用 git revert 来操作了。

git revert 命令意思是撤销某次提交。它会产生一个新的提交,虽然代码回退了,但是版本依然是向前的,所以,当你用 revert 回退之后,所有人 pull 之后,他们的代码也自动的回退了。

git revert 如果不是撤销的最近一次提交,那么一定会有冲突。一个人解决冲突,总比团队所有人来处理回滚,要好得多……

假设有一个项目,当前有以下提交历史:

$ git log
commit e7e3c0694265835fca12b66bc2605c01474e5767 (HEAD ->  master, origin/master, origin/HEAD)) # 最后一次提交已经提交到 remote 仓库
Author: Jehorn <jehorn@gmail.com>
Date:   Mon Nov 18 16:08:04 2019 +0800
    add index.css

commit f5c34cb3fb00d88e7ab0393837c8fe6f7b8f6d0b
Author: Jehorn <jehorn@gmail.com>
Date:   Thu Nov 14 11:38:41 2019 +0800
    add index.html; update text.txt
    
commit b271fcd5023b4dd1379143891835b4a6be005b08
Author: Jehorn <jehorn@gmail.com>
Date:   Thu Nov 14 10:57:49 2019 +0800
    add gitignore

commit 6925a90efa3ec6d300cd966837154b3733d3c3cc 
(origin/master, origin/HEAD)
Author: Jehorn <jehorn@gmail.com>
Date:   Wed Nov 13 17:56:02 2019 +0800
    add text.txt

然后我们要回滚到 f5c34cb 版本:

# 回滚到 f5c34cb
$ git revert f5c34cb
CONFLICT (modify/delete): index.html deleted in parent of f5c34cb... add index.html; update text.txt and modified in HEAD. Version HEAD of index.html left in tree.
error: could not revert f5c34cb... add index.html; update text.txt
hint: after resolving the conflicts, mark the corrected paths
hint: with 'git add <paths>' or 'git rm <paths>'
hint: and commit the result with 'git commit'

可以看到出现了冲突,这时候就需要解决冲突,在WS中可以通过可视化工具很方便的解决冲突:VCS -> Git -> Resolve Conflicts

选择Merge...进行合并操作。中间是合并结果,左(新的)右(本地)两边是不同版本。
注意 git 会自动尝试一些合并,比如某些新增的文件,会默认保留,这时候建议手动删除,并追加到 revert 生成的提交中。

解决冲突后:

# 查看状态
$ git status
On branch master
Your branch is up to date with 'origin/master'.

You are currently reverting commit f5c34cb.
  (all conflicts fixed: run "git revert --continue")
  (use "git revert --skip" to skip this patch)
  (use "git revert --abort" to cancel the revert operation)

Changes to be committed:
  (use "git restore --staged <file>..." to unstage)
        modified:   text.txt
        
# 继续操作
$ git revert --continue
Revert "add index.html; update text.txt"

This reverts commit f5c34cb3fb00d88e7ab0393837c8fe6f7b8f6d0b.

# Conflicts:
#       index.html

# Please enter the commit message for your changes. Lines starting
# with '#' will be ignored, and an empty message aborts the commit.
#
# On branch master
# Your branch is up to date with 'origin/master'.
#
# You are currently reverting commit f5c34cb.
#
# Changes to be committed:
#       modified:   text.txt
#    

# 修改完后 wq 退出
# 然后就可以推送到远程仓库了
$ git push origin master

可以看出,提交后再回滚会很麻烦。
所以尽量做到多 commit 少 push,可以有效减少失误的操作。
本地操作是非常自由方便的。

九、Git tag

标签可以用于生产分支的版本号管理等。

# 切换到要打标签的分支
$ git checkout release
# 添加标签
$ git tag -a "v1.0.0" -m "release version 1.0.0"
# 查看标签
$ git tag -l
v1.0.0

# 推送标签
$ git push origin release --tags
...
 * [new tag]         v1.0.0 -> v1.0.0

The end.
Last updated by Gu. 11/18, 2019.

原文地址:https://www.cnblogs.com/jimmyguu/p/11888904.html