工作区(working directory)
,简言之就是你工作的区域。对于git而言,就是的本地工作目录。工作区的内容会包含提交到暂存区和版本库(当前提交点)的内容,同时也包含自己的修改内容。暂存区(stage area, 又称为索引区index)
,是git中一个非常重要的概念。是我们把修改提交版本库前的一个过渡阶段。查看GIT自带帮助手册的时候,通常以index来表示暂存区。在工作目录下有一个.git的目录,里面有个index文件,存储着关于暂存区的内容。git add命令将工作区内容添加到暂存区。本地仓库(local repository)
,版本控制系统的仓库,存在于本地。当执行git commit命令后,会将暂存区内容提交到仓库之中。在工作区下面有.git的目录,这个目录下的内容不属于工作区,里面便是仓库的数据信息,暂存区相关内容也在其中。这里也可以使用merge或rebase将远程仓库副本合并到本地仓库。图中的只有merge,注意这里也可以使用rebase。远程版本库(remote repository)
,与本地仓库概念基本一致,不同之处在于一个存在远程,可用于远程协作,一个却是存在于本地。通过push/pull可实现本地与远程的交互;远程仓库副本
,可以理解为存在于本地的远程仓库缓存。如需更新,可通过git fetch/pull命令获取远程仓库内容。使用fech获取时,并未合并到本地仓库,此时可使用git merge实现远程仓库副本与本地仓库的合并。git pull 根据配置的不同,可为git fetch + git merge 或 git fetch + git rebase。rebase和merge的区别可以自己去网上找些资料了解下。
一、解决冲突
场景如下:人生不如意之事十之八九,合并分支往往也不是一帆风顺的
git switch -c feature1 //创建新的feature1分支,并切换到feature1分支
git add readme.txt
git commit -m "AND simple" //分支中完成代码修改并提交
git switch master
git add readme.txt
git commit -m "& simple" //切回到master分支,但在master分支上对readme.txt文件也做了同行位置的代码提交
现在master
分支和feature1
分支各自都分别有新的提交,变成了这样:
这种情况下,Git无法执行快速合并
,只能试图把各自的修改合并起来,但这种合并就可能会有冲突,我们试试看:
$ git merge feature1
Auto-merging readme.txt
CONFLICT (content): Merge conflict in readme.txt
Automatic merge failed; fix conflicts and then commit the result.
果然冲突了!Git告诉我们,readme.txt
文件存在冲突,必须手动解决冲突后再提交。git status
也可以告诉我们冲突的文件:
$ git status
On branch master
Your branch is ahead of 'origin/master' by 2 commits.
(use "git push" to publish your local commits)
You have unmerged paths.
(fix conflicts and run "git commit")
(use "git merge --abort" to abort the merge)
Unmerged paths:
(use "git add <file>..." to mark resolution)
both modified: readme.txt
no changes added to commit (use "git add" and/or "git commit -a")
我们可以直接cat readme.txt
查看readme.txt
的内容, Git用<<<<<<<,=======,>>>>>>>
标记出不同分支的内容,我们修改如下后保存:
$ cat readme.txt
Git is a distributed version control system.
Git is free software distributed under the GPL.
Git has a mutable index called stage.
Git tracks changes of files.
<<<<<<< HEAD
Creating a new branch is quick & simple.
=======
Creating a new branch is quick AND simple.
>>>>>>> feature1
我们直接可以vim readme.txt
修改内容后:wq
直接并完成保存。或者直接在vscode编辑器里(借用插件快速修改)
完成修改后保存。
再提交:
$ git add readme.txt
$ git commit -m "conflict fixed"
[master cf810e4] conflict fixed
现在,master
分支和feature1
分支变成了下图所示:
最后,删除feature1
分支:
$ git branch -d feature1
Deleted branch feature1 (was 14096d0).
用git log --graph
命令可以看到分支合并图。
注意:
在切换分支前,要留意你的工作目录和暂存区里那些还没有被提交的修改, 它可能会和你即将检出的分支产生冲突从而阻止 Git 切换到该分支。 最好的方法是,在你切换分支之前,保持好一个干净的状态。 有一些方法可以绕过这个问题(即,暂存(stashing)
和 修补提交(commit amending)
), 会在bug分支处理模块
中看到关于stash命令
的介绍。
二、分支管理策略
通常,合并分支时,如果可能,Git会用Fast forward
模式,但这种模式下,删除分支后,会丢掉分支信息。
如果要强制禁用Fast forward
模式,Git就会在merge
时生成一个新的commit
,这样,从分支历史上就可以看出分支信息。
查看所有包含未合并工作的分支,可以运行 git branch --no-merged
:
场景如下:
请注意--no-ff
参数,表示禁用Fast forward
。因为本次合并要创建一个新的commit
,所以加上-m参数
,把commit
描述写进去:
$ git merge --no-ff -m "merge with no-ff" dev //master主支上合并dev分支
Merge made by the 'recursive' strategy.
readme.txt | 1 +
1 file changed, 1 insertion(+)
合并后,我们用git log --graph
看看分支历史:
$ git log --graph
* e1e9c68 (HEAD -> master) merge with no-ff
|\
| * f52c633 (dev) add merge
|/
* cf810e4 conflict fixed
...
可以看到,不使用Fast forward
模式,merge
后就像这样:
分支策略
在实际开发中,我们应该按照几个基本原则进行分支管理:
首先,master
分支应该是非常稳定的,也就是仅用来发布新版本,平时不能在上面干活;
那在哪干活呢?干活都在dev
分支上,也就是说,dev
分支是不稳定的,到某个时候,比如1.0版本发布时,再把dev
分支合并到master
上,在master
分支发布1.0版本;
你和你的小伙伴们每个人都在dev分支上干活,每个人都有自己的分支,时不时地往dev
分支上合并就可以了。
所以,团队合作的分支看起来就像这样:
Git分支十分强大,在团队开发中应该充分应用。
合并分支时:
- 加上
--no-ff
参数就可以用普通模式合并,合并后的历史有分支,能看出来曾经做过合并,而fast forward
合并就看不出来曾经做过合并。- 加上
--squash
,使用squash
方式合并,把多次分支commit
历史压缩为一次。例如:git merge --squash -m 'merge with squash' dev
三、版本回退
首先,Git必须知道当前版本是哪个版本,在Git中,用HEAD表示当前版本,上一个版本就是HEAD~
,上上一个版本就是HEAD~~
,当然往上100个版本写100个~
比较容易数不过来,所以写成HEAD~100
。
场景如下:
- 现在,我们要把当前版本回退到上一个版本,就可以使用git reset命令:
git reset --hard HEAD~
- 现在,你回退到了某个版本,关掉了电脑,第二天早上就后悔了,想恢复到新版本怎么办?找不到新版本的
commit id
怎么办?
在Git中,总是有后悔药可以吃的。当你用git reset --hard HEAD~
回退到上一版本时,再想恢复到最新版本,就必须找到最新版本的commit id
。Git提供了一个命令git reflog
用来记录你的每一次命令:
$ git reflog
e475afc HEAD@{1}: reset: moving to HEAD^
1094adb (HEAD -> master) HEAD@{2}: commit: append GPL
e475afc HEAD@{3}: commit: add distributed
eaadf4e HEAD@{4}: commit (initial): wrote a readme file
- 找到最新版本的
commit id
是1094adb...
,于是就可以指定回到未来的某个版本:git reset --hard 1094a
模块小结:
- HEAD指向的版本就是当前版本,因此,Git允许我们在版本的历史之间穿梭,使用命令:
git reset --hard commit_id
。- 穿梭前,用
git log --graph
可以查看提交历史,以便确定要回退到哪个版本。- 要重返未来,用
git reflog
查看命令历史,以便确定要回到未来的哪个版本。
四、管理修改
场景如下:
操作过程:第一次修改 -> git add
-> 第二次修改 -> git commit
- Git管理的是修改,当你用
git add
命令后,在工作区的第一次修改被放入暂存区,准备提交,但是,在工作区的第二次修改并没有放入暂存区,所以,git commit
只负责把暂存区的修改提交了,也就是第一次的修改被提交了,第二次的修改不会被提交。git diff
是工作区(work dict)和暂存区(stage)的比较。(注意:跟最新的暂存区对比,也就是上一个提交commit
前的暂存区 ;并不是跟比如有空暂存区这种情况对比,新人潜意识就会拿工作区和commit
后最新的那个提交版本去对比,以为那个就是最新的暂存区。)git diff HEAD -- readme.txt
是查看工作区和版本库里面最新版本的区别。
$ git diff HEAD -- readme.txt
diff --git a/readme.txt b/readme.txt
index 76d770f..a9c5755 100644
--- a/readme.txt
+++ b/readme.txt
@@ -1,4 +1,4 @@
Git is a distributed version control system.
Git is free software distributed under the GPL.
Git has a mutable index called stage.
-Git tracks changes.
+Git tracks changes of files.
- 那怎么提交第二次修改呢?你可以继续
git add
再git commit
,也可以别着急提交第一次修改,先git add
第二次修改,再git commit
,就相当于把两次修改合并后一块提交了:- 第一次修改 ->
git add
-> 第二次修改 ->git add
->git commit
五、撤销修改
- 场景一:当你改乱了工作区域某个文件的内容,想直接丢弃工作区的修改时,直接用命令:
git checkout -- 文件名
。(注:git checkout -- file
命令中的--
很重要,没有--
,就变成了“切换到另一个分支”的命令)- 场景二:当你不但改乱了工作区某个文件的内容,还添加到了暂存区,想丢弃修改需要分两步走。
① 命令一:git reset HEAD 文件名
/ 直接git reset
② 命令二: 接上场景一操作- 场景三: 但你提交了不合适的修改到了版本库,想要撤销本次提交,参考版本回退模块的内容,命令:
git reset -- hard commit_id
。
五、bug分支处理
场景一如下:
当前正在dev
分支上进行的工作还没有提交,并不是你不想提交,而是工作只进行到一半,还没法提交,预计完成还需1天时间。但是,必须在两个小时内修复该bug
,怎么办?
幸好,Git还提供了一个stash
功能,可以把当前工作现场“储藏”起来,等以后恢复现场后继续工作:
$ git stash
Saved working directory and index state WIP on dev: f52c633 add merge
现在,用gst
查看工作区,就是干净的(除非有没有被Git管理的文件),因此可以放心地创建分支来修复bug再合并到开发或者发布版本。
首先确定要在哪个分支上修复bug
,假定需要在master
分支上修复,就从master
创建临时分支:
$ git checkout master //第一步切回master分支
Switched to branch 'master'
Your branch is ahead of 'origin/master' by 6 commits.
(use "git push" to publish your local commits)
$ git switch -c issue-101 //创建issue-101修改版本分支
Switched to a new branch 'issue-101'
现在修复bug,然后提交。修复完成后,切换到master
分支,并完成合并,最后删除issue-101
分支:
$ git switch master //切回主分支master
Switched to branch 'master'
Your branch is ahead of 'origin/master' by 6 commits.
(use "git push" to publish your local commits)
$ git merge --no-ff -m "merged bug fix 101" issue-101 //在主分支master上合并
Merge made by the 'recursive' strategy.
readme.txt | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
太棒了,bug修复只花了5分钟!现在,是时候接着回到dev
分支干活了!但dev
工作区是干净的,刚才的工作现场存到哪去了?工作现场还在,Git把stash内容存在某个地方了,但是需要恢复一下,有两个办法:
①用git stash apply
恢复,但是恢复后,stash
内容并不删除,你需要用git stash drop
来删除。
②用git stash pop
,恢复的同时把stash
内容也删了。
再用git stash list
查看,就看不到任何stash
内容了。
场景二如下:
在master
分支上修复了bug
后,我们要想一想,dev
分支是早期从master
分支分出来的,所以,这个bug
其实在当前dev
分支上也存在。那怎么在dev
分支上修复同样的bug
?有木有更简单的方法?
同样的bug
,要在dev
上修复,我们只需要把4c805e2 fix bug 101
这个提交所做的修改“复制”到dev
分支,并不是把整个master分支merge过来。Git专门提供了一个cherry-pick
命令,让我们能复制一个特定的提交到当前分支:
$ git branch
* dev
master
$ git cherry-pick 4c805e2
[master 1d4b803] fix bug 101
1 file changed, 1 insertion(+), 1 deletion(-)
Git自动给dev
分支做了一次提交,注意这次提交的commit
是1d4b803
,它并不同于master
的4c805e2
,因为这两个commit
只是改动相同,但确实是两个不同的commit
。用git cherry-pick
,我们就不需要在dev
分支上手动再把修bug的过程重复一遍。
模块小结:
- 修复bug时,我们会通过创建新的bug分支进行修复,然后合并,最后删除;
- 当手头工作没有完成时,先把工作现场
git stash
一下,然后去修复bug,修复后,再git stash pop
,回到工作现场;- 在
master
分支上修复的bug,想要合并到当前dev
分支,可以用git cherry-pick <commit>
命令,把bug提交的修改“复制”到当前分支,避免重复劳动。
六、Feature功能开发分支
feature分支
和bug分支
是类似的,先合并再删除。
场景如下:
因经费不足,新功能必须取消!虽然白干了,但是这个包含机密资料的分支还是必须就地销毁:
$ git branch -d feature-vulcan
error: The branch 'feature-vulcan' is not fully merged.
If you are sure you want to delete it, run 'git branch -D feature-vulcan'.
Git友情提醒,feature-vulcan分支
还没有被合并,如果删除,将丢失掉修改,如果要强行删除,需要使用大写的-D
参数。
$ git branch -D feature-vulcan
Deleted branch feature-vulcan (was 287773e).
如果要丢弃一个没有被合并过的分支,可以通过git branch -D <分支名>
强行删除。
七、多人协作
当你从远程仓库克隆时,实际上Git自动把本地的master分支
和远程的master分支
对应起来了,并且,远程仓库的默认名称是origin
。
$ git remote //要查看远程库的信息
origin
$ git remote -v //显示了可以抓取和推送的origin的地址。如果没有推送权限,就看不到push的地址。
origin git@github.com:michaelliao/learngit.git (fetch)
origin git@github.com:michaelliao/learngit.git (push)
$ 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 push origin master
//Git就会把该分支推送到远程库对应的远程分支上git push origin dev
//如果要推送其他分支,比如dev- 哪些分支需要推送,哪些不需要:
①master分支
是主分支,因此要时刻与远程同步;
②dev分支
是开发分支,团队所有成员都需要在上面工作,所以也需要与远程同步;
③bug分支
只用于在本地修复bug,就没必要推到远程了,除非老板要看看你每周到底修复了几个bug;
④feature分支
是否推到远程,取决于你是否和你的小伙伴合作在上面开发。
如果你是 Git 的重度使用者,那么还可以通过 git remote show
看到更多的信息:这个命令列出了当你在特定的分支上执行 git push
会自动地推送到哪一个远程分支。 它也同样地列出了哪些远程分支不在你的本地,哪些远程分支已经从服务器上移除了, 还有当你执行 git pull
时哪些本地分支可以与它跟踪的远程分支自动合并。
$ 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是分布式管理的,克隆是整个仓库都被克隆下来了,当然就包括所有分支了。git clone git@github.xxx.com:xxxxx.git
来克隆别人github的版本库时是克隆了全部分支,但是别人一开始只能看到你的master分支,需要创建远程origin
的对应分支到本地,才能看到对应的分支。
- 你的小伙伴只能看到本地的
master分支
。不信可以用git branch
命令看看:
$ git branch
* master
- 现在,你的小伙伴要在
dev分支
上开发,就必须创建远程origin
的dev分支
到本地,于是他用这个命令创建本地dev分支
:git switch -c dev origin/dev
- 现在,他就可以在dev上继续修改,然后,时不时地把
dev分支
push到远程:
$ git add env.txt
$ git commit -m "add env"
[dev 7a5e5dd] add env
1 file changed, 1 insertion(+)
create mode 100644 env.txt
$ git push origin dev
Counting objects: 3, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (2/2), done.
Writing objects: 100% (3/3), 308 bytes | 308.00 KiB/s, done.
Total 3 (delta 0), reused 0 (delta 0)
To github.com:michaelliao/learngit.git
f52c633..7a5e5dd dev -> dev
- 你的小伙伴已经向
origin/dev分支
推送了他的提交,而碰巧你也对同样的文件作了修改,并试图推送:
$ git push origin dev //你尝试向dev远程分支提交代码,但你不知道你的小伙伴已经向dev分支提交过一遍了
To github.com:michaelliao/learngit.git
! [rejected] dev -> dev (non-fast-forward)
error: failed to push some refs to 'git@github.com:michaelliao/learngit.git'
hint: Updates were rejected because the tip of your current branch is behind
hint: its remote counterpart. Integrate the remote changes (e.g.
hint: 'git pull ...') before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for details.
- 不幸的是推送失败,因为你的小伙伴的最新提交和你试图推送的提交有冲突,解决办法也很简单,Git已经提示我们,先用
git pull
把最新的提交从origin/dev
抓下来,然后,在本地合并,解决冲突,再推送:
$ git pull
There is no tracking information for the current branch.
Please specify which branch you want to merge with.
See git-pull(1) for details.
git pull <remote> <branch>
If you wish to set tracking information for this branch you can do so with:
git branch --set-upstream-to=origin/<branch> dev
- 更不幸的是
git pull
也失败了,提示no tracking information
,原因是没有指定本地dev分支
与远程origin/dev分支
的链接,根据提示,设置dev和origin/dev
的链接,然后再pull:
$ git branch --set-upstream-to=origin/dev dev //先建立链接
Branch 'dev' set up to track remote branch 'dev' from 'origin'.
$ git pull //再pull
Auto-merging env.txt
CONFLICT (add/add): Merge conflict in env.txt
Automatic merge failed; fix conflicts and then commit the result.
- 这回
git pull
成功,但是合并有冲突,需要手动解决,解决的方法和解决冲突模块完全一样。解决后,提交,再push:
$ git commit -m "fix env conflict"
[dev 57c53ab] fix env conflict
$ git push origin dev
Counting objects: 6, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (4/4), done.
Writing objects: 100% (6/6), 621 bytes | 621.00 KiB/s, done.
Total 6 (delta 0), reused 0 (delta 0)
To github.com:michaelliao/learngit.git
7a5e5dd..57c53ab dev -> dev
- 当然上面提示了,如果你本地
dev分支
与远程origin/dev分支
的有链接,可以直接git pull <remote远程库名> <branch分支名>
来完成git pull
操作。- 如果想要查看设置的所有跟踪分支,可以使用
git branch -vv
命令。 这会将所有的本地分支列出来并且包含更多的信息,如每一个分支正在跟踪哪个远程分支与本地分支是否是领先、落后或是都有。
$ git branch -vv
iss53 7e424c3 [origin/iss53: ahead 2] forgot the brackets
master 1ae2a45 [origin/master] deploying index fix
* serverfix f8674d9 [teamone/server-fix-good: ahead 3, behind 1] this should do it
testing 5ea463a trying something new
小结
- 查看远程库信息,使用
git remote -v
;- 本地新建的分支如果不推送到远程,对其他人就是不可见的;
- 从本地推送分支,使用
git push origin branch-name
,如果推送失败,先用git pull抓取远程的新提交;- 在本地创建和远程分支对应的分支,使用
git checkout -b branch-name origin/branch-name
,本地和远程分支的名称最好一致;- 建立本地分支和远程分支的关联,使用
git branch --set-upstream-to=<remote>/<branch-name> <branch-name>
;- 从远程抓取分支,使用
git pull
,如果有冲突,要先处理冲突。
八、Git 分支 - 变基
回顾一下经典的快进合并:
分支 master
想要合并的分支 hotfix
所指向的提交 C4 是你所在的提交 C2 的直接后继, 因此 Git 会直接将指针向前移动。换句话说,当你试图合并两个分支时, 如果顺着一个分支走下去能够到达另一个分支,那么 Git 在合并两者的时候, 只会简单的将指针向前推进(指针右移),因为这种情况下的合并操作没有需要解决的分歧——这就叫做 “快进(fast-forward)
”。
回顾一下经典的简单三方合并:
master 分支
所在提交并不是iss53 分支
所在提交的直接祖先,Git 不得不做一些额外的工作。 出现这种情况的时候,Git 会使用两个分支的末端所指的快照(C4 和 C5)以及这两个分支的公共祖先(C2),做一个简单的三方合并。
一次典型合并中所用到的三个快照和之前将分支指针向前推进所不同的是,Git 将此次三方合并的结果做了一个新的快照并且自动创建一个新的提交指向它。 这个被称作一次合并提交,它的特别之处在于他有不止一个父提交。
注意:
当merge合并时使用--no-ff参数禁用fast forward时,和merge合并时出现三方合并这种情况时,我们都会发现 Merge made by the 'recursive' strategy
(通过“递归”策略进行合并):
git merge --no-ff -m'merge iss' iss //使用--no-ff参数禁用fast forward
Merge made by the 'recursive' strategy.
readme.txt | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
$ git checkout master
Switched to branch 'master'
$ git merge iss53 //三方合并情况时
Merge made by the 'recursive' strategy.
index.html | 1 +
1 file changed, 1 insertion(+)
下面进入变基正题:
其实,还有一种方法:你可以提取在 C4 中引入的补丁和修改,然后在 C3 的基础上应用一次。 在 Git 中,这种操作就叫做
变基(rebase)
。你可以使用 rebase 命令
将提交到某一分支上的所有修改都移至另一分支上,就好像“重新播放”一样。
操作第一步:
$ git checkout experiment
$ git rebase master
First, rewinding head to replay your work on top of it...
Applying: added staged command
它的原理是首先找到这两个分支(即当前分支 experiment
、变基操作的目标基底分支 master
) 的最近共同祖先 C2,然后对比当前分支相对于该祖先的历次提交,提取相应的修改并存为临时文件, 然后将当前分支指向目标基底 C3, 最后以此将之前另存为临时文件的修改依序应用。此时逻辑图如下:
操作第二步:
$ git checkout master
$ git merge experiment
现在回到 master 分支
,进行一次快进合并。此时,C4'
指向的快照就和图一中 C5 指向的快照一模一样了。 这两种整合方法的最终结果没有任何区别,但是变基使得提交历史更加整洁。 此时逻辑图如下:
变基的风险:
如果提交存在于你的仓库之外,而别人可能基于这些提交进行开发,那么不要执行变基。
- 如果你只对不会离开你电脑的提交执行变基,那就不会有事。 如果你对已经推送过的提交执行变基,但别人没有基于它的提交,那么也不会有事。 如果你对已经推送至共用仓库的提交上执行变基命令,并因此丢失了一些别人的开发所基于的提交, 那你就有大麻烦了,你的同事也会因此鄙视你。
- 如果你或你的同事在某些情形下决意要这么做,请一定要通知每个人执行 git pull --rebase 命令,这样尽管不能避免伤痛,但能有所缓解。
总的原则是,只对尚未推送或分享给别人的本地修改执行变基操作清理历史, 从不对已推送至别处的提交执行变基操作,这样,你才能享受到两种方式带来的便利。
九、Git打标签
①git tag <tagname>
用于新建一个标签,默认为HEAD
,也可以指定一个commit id
:
$ git tag v1.0
$ git tag v0.9 f52c633
②git tag
可以查看所有标签:
$ git tag
v0.9
v1.0
③git tag -a <tagname> -m "blablabla..."
可以指定标签信息:
$ git tag -a v0.1 -m "version 0.1 released" 1094adb
④git show <tagname>
查看标签信息:
$ git show v0.1
tag v0.1
Tagger: Michael Liao <askxuefeng@gmail.com>
Date: Fri May 18 22:48:43 2018 +0800
version 0.1 released
commit 1094adb7b9b3807259d8cb349e7df1d4d6477073 (tag: v0.1)
Author: Michael Liao <askxuefeng@gmail.com>
Date: Fri May 18 21:06:15 2018 +0800
append GPL
diff --git a/readme.txt b/readme.txt
...
⑤git tag -d <tagname>
可以删除一个本地标签:
$ git tag -d v0.1
Deleted tag 'v0.1' (was f15b0dd)
⑥git push origin <tagname>
可以推送一个本地标签:
$ git push origin v1.0
Total 0 (delta 0), reused 0 (delta 0)
To github.com:michaelliao/learngit.git
* [new tag] v1.0 -> v1.0
⑦git push origin --tags
可以推送全部未推送过的本地标签:
$ git push origin --tags
Total 0 (delta 0), reused 0 (delta 0)
To github.com:michaelliao/learngit.git
* [new tag] v0.9 -> v0.9
⑧git push origin :refs/tags/<tagname>
可以删除一个远程标签:
$ git tag -d v0.9 //如果标签已经推送到远程,要删除远程标签就麻烦一点,先从本地删除
Deleted tag 'v0.9' (was f52c633)
$ git push origin :refs/tags/v0.9 //然后,从远程删除
To github.com:michaelliao/learngit.git
- [deleted] v0.9