乐趣区

关于前端:Git基础指令和进阶

  • 工作区 (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 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.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 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 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 分支做了一次提交,留神这次提交的 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-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 分支 上开发,就必须创立近程 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 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
退出移动版