Git的使用

这篇就算在这一周的学习笔记里吧😆

本文在我的Github上体验不佳,等我换了主题应该会好很多

推荐去简书查看原文

简书地址:https://www.jianshu.com/p/c5fb9f2dbb75

从进入红岩交的第二份作业开始就是使用的Github来上交的,但是一直一直以来,我一直只把Github当做一个云存储来使用,写完代码之后,就add,commit,push,然后结束自己的工作。如果Github只是这么使用的话,有愧于它的名字——分布式版本控制系统。最近终于有时间真正的了解Git的使用,下面是学习完Git教程-廖雪峰的官方网站之后整理的学习笔记。

1. Git的由来

这个并不是本文的重点,但是还是需要了解一下

Git的由来不得不提Linux,Linux是一个完全开源的系统,而它的用途我就不再赘述。既然是一个开源的项目,那就需要大家一起来参与开发,当是使用的是BitKeeper(同样是一个代码托管平台,不过是付费的),而且出于人道主义它对Linux社区是免费的。但是后来由于一些Linux牛人尝试去破解BitKeeper的协议被BitKeeper发现,决定取消linux社区免费的制度。然而Linux的创始人Linus仅仅花了两周用C语言就写出了Git来代替了BitKeeper!之后越来越多的开源项目使用Git这个版本控制系统。到了2008年Github网站上线,简单易用速度快的Git更是被大家广泛使用。

2. Git的结构

2.1 分布式

上文提到Git是一款分布式版本控制系统,与之相对的是集中式版本控制系统。
集中式版本控制系统示意图:QQ20190312-131318@2x.png
集中式意思就是每次工作的时候从服务器拉取最新的版本,然后自己更改完代码后再推送给服务器。工作的时候需要联网。

从某种意义上来说我之前那样Git使用和集中式没有多大区别233333

分布式版本控制系统示意图:
QQ20190312-132533@2x.png
在分布式中,代码(仓库)不存放在服务器中,而是存放在某个人的电脑中,你可以获取到自己的电脑中,然后进行更改,最后提交更改。给我的感觉有点像区块链的去中心化。整个工作过程一旦获取了仓库的内容就不需要联网。而远程仓库的存在实际上提供一个桥梁的功能,因为图中的成员A和B处于同一个局域网中,而成员C并不是,所以只能通过远程仓库来进行操作。

到这里可能还是没看的出来这个两者的区别,因为Git还有很重要的分支功能没有介绍(同时也是我之前一直没使用的功能)。

2.2 仓库结构

和集中式版本控制系统一样,Git也拥有工作区和版本库。但是版本库中加了一个暂存区

2.2.1 工作区

工作区就是我们电脑本地能看到的文件夹QQ20190312-133633@2x.png

.git是一个隐藏文件夹,里面记录这重要的信息,请不要动他

2.2.2 代码库

下面引用廖雪峰的图:0 (1).jpeg
我们常用的add,commit,这里已经写的很清楚了。现将更改的文件通过add添加到暂存区,然后再使用commit将其提交到(当前分支)版本库。push是推送到远程版本库(也就是Github)。

图中的HEAD是一个指向master分支(它也是一个指针,这个指针的指向是当前版本)的当前版本的一个指针,稍后介绍分支的时候会解释。

3. 面向修改的Git

Git设计的优点在于它跟踪并记录的是修改而不是文件。

3.1 创建一个Git仓库

为了接下来的演示,我们创建一个空的Git仓库,cd到目标目录,然后使用命令创建Git仓库

1
2
$ cd /Users/huanglong/Desktop/GitRepositories/GitTest
$ git init

随后会有反馈

1
Initialized empty Git repository in /Users/huanglong/Desktop/GitRepositories/GitTest/.git/

如果你还没有Git环境请自行搭建

此时该文件夹中会出现一个.git的隐藏文件夹,这里记录了Git仓库的关键信息,请不要改动它。

3.2 提交文件到暂存区

首先我们在GitTest文件夹中创建一个新的文件 README.md

1
$ touch README.md

然后往里面放写入东西

1
2
$ vi README.md
//......写入fsddw

然后我们使用如下命令将这个文件加入到我们的暂存区

1
$ git add README.md

然后我们使用这个命令来查看当前Git仓库的状态

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.md

On branch master 表示我们现在在master分支上 ,分支的概念我们稍后介绍
我们可以看到README.md文件已经放入暂存区,但是还没有commit到分支(No commits yet)

3.3 提交文件到分支

使用如下命令就可以将缓存区的所有文件提交到分支

1
2
3
4
$ git commit -m "test"
[master (root-commit) 0fbdc51] test
1 file changed, 1 insertion(+)
create mode 100644 README.md

“ “里打上你对这一次commit的备注,虽然不是必须的,但是推荐每次都打上,方便我们之后回看

然后我们在查看当前Git仓库的状态

1
2
3
$ git status
On branch master
nothing to commit, working tree clean

可以看到工作区是空的(nothing to commit, working tree clean),文件已经全部提交了。

3.4 commit的是修改而不是文件

为了验证,我们在将README.md放入缓存区后,再对README.md进行修改,然后再commit到分支,你会发现分支并没有应用你的第二次更改。

3.5 撤销修改

我们此时将README.md中再加入fsqsll。
我们发现的这句话是错误的,需要撤销修改,此时应该使用命令

1
$ git checkout -- README.md

这时候,README就会返回到我们当前版本库中的状态,即只有fsddw。
如果你是已经add了修改,然后又对文件进行了修改,那么使用该命令将使你的文件回到add后的状态。如果你已经add了修改,又想让文件回到版本库的状态,那么需要先使用如下命令:

1
$ git reset HEAD README.md

然后再撤销修改。

3.6 文件删除

如果我们需要将工作区的某个文件删除,可以使用如下命令:

1
2
3
4
5
6
$ git rm README.md
rm 'README.md'
$ git commit -m "Delete README.md"
[master 8849efd] Delete README.md
1 file changed, 1 deletion(-)
delete mode 100644 README.md

那么当前版本库的这个版本即没有了这个文件。
如果你不小心使用了git rm命令删掉了某个文件,但是版本库的当前版本还存在,那么你可以使用如下命令来找回:

1
$ git checkout -- README.md

可以看到,checkout同时用于撤销修改和文件找回,因为这个命令实际上就是将版本库的文件复制进入工作区然后覆盖。

4. Git分支

Git中最最最强大的功能就是分支了√
利用分支结构,不仅可以让开发小组的成员有序地工作,也让我们个人开发项目变得很有条理。

  • 你可以让分出多个分支给自己的小组成员,然后各自在一个分支上工作,然后工作完成后再合并到一个分支上
  • 自己一个人的工作同样可以使用分支结构来让自己的项目变得井然有序(master、dev、Feature、Bug分支)

    4.1 单分支结构

    这就是我没有学习如何使用Git之前的样子2333333

以上图中的master分支举例子:
master分支结构

master分支是当你创建库时的初始分支,你的每一次更改都会新创建一个圆点,形成一个时间线,HEAD指针自然而然地就指向你现在最新的更改。

4.2 版本退回

在某些时候,我们可能需要对我们的文件进行版本退回,由于分支的结构特点,利用指针,我们瞬间就可以完成版本的退回,使用如下命令:

1
$ git reset --hard HEAD^

命令应该很容易理解,HEAD^意思就是HEAD的上一个,其实Git的工作只是将HEAD指向了上一个圆点罢了,所以可以很快的完成。

上个版本是HEAD^ 上上个是HEAD^^ 以此类推,数量太多的时候就是用HEAD~数量,比如 HEAD~100

4.3 多分支结构

不多bb,上图:多分支结构

这里的多分支结构是从4这里看开始分出一个dev的分支,两个分支互不影响,每个分支都可以单独进行操作(其实也就是操作指针)。

  • HEAD:它的指向代表着的是现在正在操作的分支
  • master/dev:它的指向代表着现在版本库中的版本

    4.3.1 创建新的分支

    使用这个命令在当前分支的当前版本创建一个dev分支,并且换到dev分支
    1
    2
    3
    $ git branch dev
    $ git checkout dev
    switched to branch dev

以上代码也可以通过这一行代替

1
2
$ git checkout -b dev
switched to a new branch dev

4.3.2 合并分支(使用Fast-forward)

将两个分支进行合并的操作也很简单,比如我们现在在dev分支上进行完了所有工作,是时候合并到master分支上了,这时我们应首先回到master分支:

1
$ git checkout master

然后将dev分支合并到master中

1
$ git merge dev

Tips: 如果你不知道现在在哪个分支,你可以输入如下命令:

1
2
3
$ git branch
* dev
master

该命令可以列出现在所有的分支,带*号的就是目前所在的分支
实战练习:
现在我创建一个新的分支,然后在分支上更改了README.md,加入了“守夜冠军不请自来”的字样

1
2
$ git checkout -b dev
Switched to a new branch 'dev'

在dev分支上更改README
然后add并commit它(略)

随后我们回到master分支

1
2
$ git checkout master
Switched to branch 'master'

此时我们看到README中只有fsddw
master分支上的README
然后我们开始合并分支

1
2
3
4
5
$ git merge dev
Updating 0fbdc51..daecc97
Fast-forward
README.md | 1 +
1 file changed, 1 insertion(+)

我们再查看一下README,就会发现“守夜冠军不请自来”已经添加到README上了!
master分支合并后已经更改了!
另外通过如下命令可以查看当先的分支图:

1
2
3
$ git log --graph --pretty=oneline --abbrev-commit
* 75edfc5 (HEAD -> master, dev) 守夜冠军不请自来
* 5ff1c9f fsddw

如果你不再需要dev分支,那么你可以将它删掉

1
2
$ git branch -d dev
Deleted branch dev (was daecc97).

  • 注意,如果你的分支上有未合并的工作,那么Git会提示你再输入一次已确认删除(如果删除这个分支你可能就会丢失你的工作记录)
    1
    2
    3
    4
    5
    $ git branch -d dev
    error: The branch 'dev' is not fully merged.
    If you are sure you want to delete it, run 'git branch -D dev'.
    $ git branch -D dev
    Deleted branch dev (was a883195).

然后我们再查看当前的分支图:

1
2
3
$ git log --graph --pretty=oneline --abbrev-commit
* 75edfc5 (HEAD -> master) 守夜冠军不请自来
* 5ff1c9f fsddw

dev字样被删除了

4.4 分支冲突解决

上面的实战中,我们从返回的日志可以看到Fast-forward的字样
表明这个是使用的快速合并模式,即直接将master的指针指向dev指针所指向的版本。快速合并
但是,如果我们的master分支同时也对README做出了修改,那么就会出现冲突。
实例:
现在,我们在master分支上的README加上“守夜冠军不请自来”并add,commit
然后我们在这里分出一个新的分支,然后将“守夜冠军不请自来”改成“守夜冠军就是我”,然后add,commit
然后回到master分支,再将“守夜冠军不请自来”改成“守夜冠军奖杯是我的”,然后add,commit
现在的分支情况如下图:
现在的分支结构
此时如果我们尝试将他们dev分支合并到master分支上,就会出现错误

1
2
3
4
$ git merge dev
Auto-merging README.md
CONFLICT (content): Merge conflict in README.md
Automatic merge failed; fix conflicts and then commit the result.

这是就会提示合并失败,因为同一个文件两个版本不一致,不知道应该采取谁的版本,Git让我们自己解决冲突,然后我们此时打开README:
此时的README
这时合并失败的文件里已经被更改了,而且Git将两个不一样的地方都给我们标了出来,然后我们要做的就是删掉我们不需要的部分。这里我们删掉HEAD的内容。
删掉冲突的部分
然后重新add,commit即可。

注意,这里只会提示你合并失败的文件,其他文件是合并成功的,也就是说你自己处理自动合并失败的地方,然后自己重新add,commit

查看当前的分支图:

1
2
3
4
5
6
7
8
9
10
$ git log --graph --pretty=oneline --abbrev-commit
* 809c050 (HEAD -> master) merge
|\
| * f533bc3 (dev) test
* | bf15858 test
|/
* f6f80d2 test
* 24484f1 test
* daecc97 test
* 0fbdc51 test

可以看到现在dev分支确实合并到master上了,但是会出现和刚才不一样的分支图
这时我们如果删除dev分支的话分支图就会变成这样:

1
2
3
4
5
6
7
8
9
10
11
12
$ git branch -d dev
Deleted branch dev (was f533bc3).
$ git log --graph --pretty=oneline --abbrev-commit
* 809c050 (HEAD -> master) merge
|\
| * f533bc3 test
* | bf15858 test
|/
* f6f80d2 test
* 24484f1 test
* daecc97 test
* 0fbdc51 test

也只是去掉了一个(dev)2333333,因为解决冲突的时候是要创建一个commit来解决

4.5 合并分支(不使用Fast-forward)

上面介绍如果使用Fast-forward,会直接将指针指向分支上的版本,这虽然很快,但会有弊端:如果你把被合并的分支删掉后会把历史记录都一并删除。不过,我们可以加入参数来禁止Fast-forward。

1
$ git merge --no-ff -m "内容" dev

实例:
我们重复上面的分支操作进行更改后使用不使用Fast-forwar的合并。

1
2
3
4
git merge --no-ff -m"使用非Fast-forward合并" dev
Merge made by the 'recursive' strategy.
README.md | 1 +
1 file changed, 1 insertion(+)

然后我们查看分支图:

1
2
3
4
5
6
$ git log --graph --pretty=oneline --abbrev-commit
* aa24518 (HEAD -> master) 使用非Fast-forward合并
|\
| * 11f4d28 (dev) 守夜冠军不请自来
|/
* 5ff1c9f fsddw

我们可以看到这里多了一个commit,即使我们删除了dev
分支,我们仍可以清楚地看到,这里是曾经合并过的。而不是没有任何的提示。

1
2
3
4
5
6
7
8
$ git branch -d dev
Deleted branch dev (was 11f4d28).
$ git log --graph --pretty=oneline --abbrev-commit
* aa24518 (HEAD -> master) 使用非Fast-forward合并
|\
| * 11f4d28 守夜冠军不请自来
|/
* 5ff1c9f fsddw

4.6 分支策略

在实际的使用中,分支应该这么设计:

  • master分支应该是最稳定的,工作不应该在master上进行,应该充当一个类似版本更新的分支
  • dev分支是真正的工作的分支,在这里进行工作
  • 从dev中分出给小组成员的分支,小组成员完成工作后合并到dev分支,dev分支完成一个个小任务后在提交到master分支
    引用廖雪峰的图:
    分支策略

4.7 分支的妙用

4.7.1 Bug分支

使用Git的分支,我们可以通过创建一个Bug分支,更改bug结束后再合并。但是如果在此时你工作区中还有没有commit的文件,然后但是你又不想马上commit来创建节点,然而这个bug被要求马上完成那可怎么办呢。Git提供了一种储存的方法,将前的工作区保存起来。

1
2
$ git stash
Saved working directory and index state WIP on master: aa24518 使用非Fast-forward合并

这是我们查看工作区:

1
2
3
$ git status
On branch master
nothing to commit, working tree clean

可以看到工作区是空的了,然后你就可以转换到你要改Bug的分支改Bug
改完之后回到原来的分支,并输入如下命令:

1
2
$ git stash list
stash@{0}: WIP on master: aa24518 使用非Fast-forward合并

看到list,显然我们可以多次保存工作区,这其实很像快照
然后输入下面这个命令来恢复工作区“0”:

1
$ git stash apply stash@{0}

和快照一样,恢复快照后并不会删除,你需要手动删除:

1
$ git stash drop stash@{0}

或者使用这个命令来恢复并删除:

1
$ git stash pop stash@{0}

当list里只有一个stash时,apply/drop/pop可以不接参数,直接应用/删除/应用并删除这个stash

5. 使用GitHub进行多人协作

5.1 链接到远程仓库(Github)

远程仓库并不只有Githu,这里只是以Github进行举例

前提: 你的Github已经配置好了公钥

  • 首先我们在自己的Github上建立一个仓库(略)
  • 然后我们有两个方法可以让本地的仓库和远程的仓库进行连接
  1. 使用git clone 你的Git仓库地址
    这里以自己的仓库举例
    1
    $ git clone https://github.com/Override0330/AndroidDevelopmentTools.git

然后等待clone完成,你会发现你终端所在的目录生成了一个AndroidDevelopmentTools文件夹,这个文件夹就是和远程Git仓库链接好的本地仓库√

  1. 使用git remote add origin 你的Git仓库地址
    在你的本地仓库目录中输入如下命令
    1
    $ git remote add origin https://github.com/Override0330/AndroidDevelopmentTools.git

origin是远程仓库名(可以自定义,但一般默认)
同样可以链接

5.2 将分支推送到Github

如果你是使用git clone的方式建立的链接,在你想要推送的时候使用如下命令就好,但这样默认推送的是master分支

1
$ git push

在需要推送到别的远程仓库以及别的分支时,使用如下命令:

1
$ git push origin dev

origin指的是远程仓库名,dev就是你要推送的分支名称

Tips1:如果你的远程仓库是空的,而且建立链接时使用的是git remote add origin
那么第一次push的时候应该加上参数-u,完整命令如下:

1
2
>$ git push -u origin dev
>

下一次的时候就不需要加上这个-u参数

Tips2:第一次进行提交的时候会提示

1
2
3
4
>The authenticity of host 'github.com (xx.xx.xx.xx)' can't be established.
>RSA key fingerprint is xx.xx.xx.xx.xx.
>Are you sure you want to continue connecting (yes/no)?
>

这个意思是让你确认公钥是否正确,输入yes按下回车就可以了

5.3 远程仓库的分支技巧

  • master是主分支,应该要推送到远程仓库
  • dev是工作分支,记录着每一次工作,也是应该推送到远程仓库
  • 小组成员工作分支,可以不用推送到远程仓库,只需要从dev分支上分出一个自己的分支,然后在分支上工作,完成工作再合并到dev分支就好了
  • Bug分支,更没必要除非你想让别人看到你改了什么bug
  • 其他分支,自己开着玩,没必要√

    5.4 从远程仓库中clone

    5.1 链接到远程仓库中我们使用了git clone的命令,但是我们clone得到的是这个仓库以及这个仓库的master分支。根据上文5.3 远程仓库的分支技巧我们不仅要push到master分支,还要push到dev分支,所以我们需要新建一个和远程仓库分支链接的本地分支:
    1
    2
    3
    $ git checkout -b dev origin/dev
    //origin代表你的远程仓库名
    //“/”后面接远程仓库的分支名

Tips:如果你的远程仓库中并没有dev分支,那么你需要看看5.5在远程仓库中创建新的分支不然你会出现报错

1
2
3
4
5
6
> The current branch dev has no upstream branch.
> To push the current branch and set the remote as upstream, use
> git push --set-upstream origin dev
> 其实就是多了一个参数罢了
> 然后就可以在dev分支中开始工作啦
>

5.6 在远程仓库中创建新的分支

5.3的操作中,如果你的仓库没有对应的分支,那么将会报错
根据Git的提示,使用如下代码在远程仓库建立新的分支并和本地的dev分支链接在一起:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
//记得要先定位到dev分支在进行该操作
$ git push --set-upstream origin dev
Enumerating objects: 5, done.
Counting objects: 100% (5/5), done.
Delta compression using up to 8 threads
Compressing objects: 100% (3/3), done.
Writing objects: 100% (3/3), 401 bytes | 401.00 KiB/s, done.
Total 3 (delta 0), reused 0 (delta 0)
remote:
remote: Create a pull request for 'dev' on GitHub by visiting:
remote: https://github.com/Override0330/AndroidDevelopmentTools/pull/new/dev
remote:
To https://github.com/Override0330/AndroidDevelopmentTools.git
* [new branch] dev -> dev
Branch 'dev' set up to track remote branch 'dev' from 'origin'.

这样就完成了创建分支和链接

5.5 远程仓库的分支合并冲突

和本地分之合并一样,远程仓库一样会产生分支合并冲突:
你push的文件别人同样对他进行了不同的更改而且比你先一步
解决方法其实大同小异,根据Git自带的提示,让我们先pull远程的分支到本地,然后在本地进行分支合并,然后在push到远程。
实例:
假设我有成员A和成员B
他们同时通过在master分支新建立一个dev分支
成员A将仓库的README修改并且已经提交到远程master分支
成员A的修改

此时成员B在dev分支也修改完了,也尝试合并到远程master分支
成员B的修改
此时就出现了报错

1
2
3
4
5
6
7
8
9
$ git push
To https://github.com/Override0330/AndroidDevelopmentTools.git
! [rejected] master -> master (fetch first)
error: failed to push some refs to 'https://github.com/Override0330/AndroidDevelopmentTools.git'
hint: Updates were rejected because the remote contains work that you do
hint: not have locally. This is usually caused by another repository pushing
hint: to the same ref. You may want to first integrate the remote changes
hint: (e.g., 'git pull ...') before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for details.

根据提示,我们使用pull进行将当前远程仓库中最新的版本拉取到本地进行手动合并

1
2
3
4
5
6
7
8
9
10
11
$ git pull
remote: Enumerating objects: 5, done.
remote: Counting objects: 100% (5/5), done.
remote: Compressing objects: 100% (3/3), done.
remote: Total 3 (delta 0), reused 0 (delta 0), pack-reused 0
Unpacking objects: 100% (3/3), done.
From https://github.com/Override0330/AndroidDevelopmentTools
4da968a..eb617ad master -> origin/master
Auto-merging README.md
CONFLICT (content): Merge conflict in README.md
Automatic merge failed; fix conflicts and then commit the result.

pull成功了,我们打开README

1
$ vim README.md

pull之后的README
是否似曾相识?和上文中提到的本地冲突一样,手动解决冲突之后,然后重新add,commit就能够完成合并了。
这时我们看看分支图如何?

1
2
3
4
5
6
7
8
9
10
$ git log --graph --pretty=oneline --abbrev-commit
* fd17927 (HEAD -> master, origin/master, origin/HEAD) fix conflict
|\
| * eb617ad branch conflict test
* | 95194b6 different person branch conflict test
|/
* 4da968a bug
* 8ba355d update
* 59b308b upload
* f31c620 Initial commit

由于我们pull了一次,就会和本地冲突解决一样留下一个commit,现在还挺好,但是当人一多起来,冲突是难免的,冲突解决也都是pull合并冲突重新提交,然后就会变成这个样子:

由于我一个人模拟多人协作并疯狂pull有点麻烦
所以接下来都是引用廖雪峰大佬的示例:
原链接:https://www.liaoxuefeng.com/wiki/0013739516305929606dd18361248578c67b8067c8c017b000/0015266568413773c73cdc8b4ab4f9aa9be10ef3078be3f000

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
$ git log --graph --pretty=oneline --abbrev-commit
* d1be385 (HEAD -> master, origin/master) init hello
* e5e69f1 Merge branch 'dev'
|\
| * 57c53ab (origin/dev, dev) fix env conflict
| |\
| | * 7a5e5dd add env
| * | 7bd91f1 add new env
| |/
* | 12a631b merged bug fix 101
|\ \
| * | 4c805e2 fix bug 101
|/ /
* | e1e9c68 merge with no-ff
|\ \
| |/
| * f52c633 add merge
|/
* cf810e4 conflict fixed

好乱奥为什么不是一个直线???
怎么解决这个问题呢?⬇️

5.6 使用Rebase来解决分支太乱的问题

使用前:

1
2
3
4
5
6
7
8
9
$ git log --graph --pretty=oneline --abbrev-commit
* e0ea545 (HEAD -> master) Merge branch 'master' of github.com:michaelliao/learngit
|\
| * f005ed4 (origin/master) set exit=1
* | 582d922 add author
* | 8875536 add comment
|/
* d1be385 init hello
...

Tips:这里的时间线貌似出现了一些问题,本地分支超前了远程分支三个commit。

使用中:

1
2
3
4
5
6
7
8
9
10
11
12
$ git rebase
First, rewinding head to replay your work on top of it...
Applying: add comment
Using index info to reconstruct a base tree...
M hello.py
Falling back to patching base and 3-way merge...
Auto-merging hello.py
Applying: add author
Using index info to reconstruct a base tree...
M hello.py
Falling back to patching base and 3-way merge...
Auto-merging hello.py

使用后:

1
2
3
4
5
6
$ git log --graph --pretty=oneline --abbrev-commit
* 7e61ed4 (HEAD -> master) add author
* 3611cfe add comment
* f005ed4 (origin/master) set exit=1
* d1be385 init hello
...

有啥用???变得好看(实际上我觉得原来也挺好看的)
其他的我看不太出来🙃
等一手fsddw

5.7 给commit打上标签(tag)

标签有啥用?增加可读性√

5.7.1 在本地打标签

使用如下命令给当前所在分支的最新commit打标签

1
$ git tag v1.0

想给其他commit打标签有点麻烦,在标签名后面加上这个commit的id
使用如下命令获得所有commit的id

1
2
3
4
5
6
7
8
9
10
11
$ git log --pretty=oneline --abbrev-commit
fd17927 (HEAD -> master, tag: v1.0, origin/master, origin/HEAD) fix conflict
95194b6 different person branch conflict test
eb617ad branch conflict test
4da968a bug
293fc4c (origin/dev, dev) dev branch conflict test
383c456 branch conflict test
c20fb65 dev branch test
8ba355d update
59b308b upload
f31c620 Initial commit

比如给95194b6 different person branch conflict test打标签

1
$ git tag v0.9 95194b6

然后使用这个命令来获得当前分支的所有标签:

1
2
3
$ git tag
v0.9
v1.0

有创建标签就有删除标签:

1
2
$ git tag -d v0.9
Deleted tag 'v0.9' (was 95194b6)

想要获取某个标签所对应的commit信息?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
$ git show v1.0
commit fd1792783aabdbb0230d66386def191f9e50beeb (HEAD -> master, tag: v1.0, origin/master, origin/HEAD)
Merge: 95194b6 eb617ad
Author: Override0330 <854098072@qq.com>
Date: Wed Mar 13 01:41:39 2019 +0800

fix conflict

diff --cc README.md
index 8e5d4a4,6635c26..13c394c
--- a/README.md
+++ b/README.md
@@@ -1,3 -1,3 +1,2 @@@
# AndroidDevelopmentTools
这里存放一些自己假装封装的工具类
- 这句话用来测试不同小组成员之间的发生的合并冲突!
-这里是测试小组成员的合并到master分支上的冲突

可以看到记录得非常的清楚√

5.7.2 在远程仓库打标签

和提交修改差不多,只需要将标签push到远程仓库就可以了

1
2
3
4
$ git push origin v1.0
Total 0 (delta 0), reused 0 (delta 0)
To https://github.com/Override0330/AndroidDevelopmentTools.git
* [new tag] v1.0 -> v1.0

或者一次性添加所有标签

1
2
3
4
$ git push origin --tags
Total 0 (delta 0), reused 0 (delta 0)
To https://github.com/Override0330/AndroidDevelopmentTools.git
* [new tag] v0.9 -> v0.9

然后我们在Github上就可以通过tags来筛选commit了
Github上的tag
删除远程标签,先在本地删除,然后再push到远程,注意push的格式

1
2
3
4
5
6
$ git tag -d v0.9
Deleted tag 'v0.9' (was 95194b6)

$ git push origin :refs/tags/v0.9
To https://github.com/Override0330/AndroidDevelopmentTools.git
- [deleted] v0.9

6. 小结

这篇学习笔记可以说是我写过最长的了2333333可能内容比较多吧问题不大,加深了很大的印象。
然后接下来时常用命令汇总:
Git仓库管理:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
//创建一个空仓库
$ git init
//添加指定文件/所有文件到暂存区
$ git add <filename>/.
//将工作区的文件提交到分支
$ git commit -m "info"
//查看当前Git仓库状态
$ git status
//撤销指定文件的修改/删除
$ git checkout -- <filename>
$ git reset HEAD <filename>
//删除工作区的文件
$ git rm <filename>
//给当前工作区的文件“拍快照”
$ git stash
//查看“快照列表”
$ git stash list
//恢复快照
$ git stash apply <stashId>
//删除快照
$ git stash drop <stashId>
//恢复并删除快照
$ git stash pop <stashId>

Git分支:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
//创建分支
$ git branch <branchName>
//切换到分支
$ git checkout <branchName>
//创建并切换到分支
$ git checkout -b <branchName>
//删除分支
$ git branch -d <branchName>
//查看分支列表
$ git branch
//版本退回
$ git reset --hard HEAD^
//将目标分支合并到当前分支默认使用Fast-forward
$ git merge <branchName>
//将目标分支合并到当前分支不使用Fast-forward
$ git merge --no-ff -m "info" <branchName>
//查看分支图
$ git log --graph --pretty=oneline --abbrev-commit

远程仓库:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
//克隆目标Git仓库
$ git clone <HttpsUrl/ssh>
//将当前的Git仓库和远程仓库链接
$ git remote add <远程仓库名称> <HttpsUrl/ssh>
//将当前分支推送到远程仓库
$ git push
$ git push <远程仓库名> <branchName>
$ git push -u <远程仓库名> <branchName>
//新建本地分支和并和远程仓库的对应分支连接
$ git checkout -b <本地分支名> <远程仓库名>/<远程分支名>
//在远程仓库中新建新的分支并和当前的本地分支相连接
$ git push --set-upstream <远程仓库名> <新建的远程分支名>
//解决合并冲突
$ git pull
//让分支图变得整洁好看
$ git rebase

标签使用:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
//给当前branch的最新commit加标签
$ git tag <tag>
//给之前的commit加标签
$ git tag <tag> <commitId>
//显示当前分支所有commit的id
$ git log --pretty=oneline --abbrev-commit
//显示该分支下的所有标签
$ git tag
//删除标签
$ git tag -d <tag>
//获取某个标签所对应的commit的详细信息
$ git show <tag>
//将标签推送到远程仓库
$ git push <远程仓库名> <tag>
$ git push <远程仓库名> --tags
//删除远程标签,请先在本地删除
$ git push <远程仓库名> :refs/tags/<tag>