• 工作区(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 feature1Auto-merging readme.txtCONFLICT (content): Merge conflict in readme.txtAutomatic merge failed; fix conflicts and then commit the result.

果然抵触了!Git通知咱们,readme.txt文件存在抵触,必须手动解决抵触后再提交。git status也能够通知咱们抵触的文件:

$ git statusOn branch masterYour 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.txtno changes added to commit (use "git add" and/or "git commit -a")

咱们能够间接cat readme.txt查看readme.txt的内容, Git用<<<<<<<,=======,>>>>>>>标记出不同分支的内容,咱们批改如下后保留:

$ cat readme.txtGit 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.<<<<<<< HEADCreating 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 feature1Deleted 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 refloge475afc HEAD@{1}: reset: moving to HEAD^1094adb (HEAD -> master) HEAD@{2}: commit: append GPLe475afc HEAD@{3}: commit: add distributedeaadf4e HEAD@{4}: commit (initial): wrote a readme file
  • 找到最新版本的commit id1094adb...,于是就能够指定回到未来的某个版本: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.txtindex 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 addgit 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 stashSaved 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  //切回主分支masterSwitched 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分支做了一次提交,留神这次提交的commit1d4b803,它并不同于master4c805e2,因为这两个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-vulcanerror: 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-vulcanDeleted 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分支上开发,就必须创立近程origindev分支到本地,于是他用这个命令创立本地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 devCounting 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 behindhint: 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 pullThere 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   //再pullAuto-merging env.txtCONFLICT (add/add): Merge conflict in env.txtAutomatic 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 devCounting 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 forwardMerge made by the 'recursive' strategy. readme.txt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
$ git checkout masterSwitched 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 masterFirst, 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 tagv0.9v1.0
git tag -a <tagname> -m "blablabla..."能够指定标签信息:
$ git tag -a v0.1 -m "version 0.1 released" 1094adb
git show <tagname>查看标签信息:
$ git show v0.1tag v0.1Tagger: Michael Liao <askxuefeng@gmail.com>Date:   Fri May 18 22:48:43 2018 +0800version 0.1 releasedcommit 1094adb7b9b3807259d8cb349e7df1d4d6477073 (tag: v0.1)Author: Michael Liao <askxuefeng@gmail.com>Date:   Fri May 18 21:06:15 2018 +0800    append GPLdiff --git a/readme.txt b/readme.txt...
git tag -d <tagname>能够删除一个本地标签:
$ git tag -d v0.1Deleted tag 'v0.1' (was f15b0dd)
git push origin <tagname>能够推送一个本地标签:
$ git push origin v1.0Total 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 --tagsTotal 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