入职必会!Git版本管理软件

git简介

git的诞生

1991年 Linus开创了开源的Linux

2002年以前 Linus手动合并代码

2002年 BitKeeper免费授权

2005年 BitKeeper被尝试破解,收回授权

2005年 Linus花了两周时间用C写出了git,并且一个月之内将Linux搬迁到git上

2008年 GitHub上线

集中式与分布式

集中式

​ CVS、SVN

分布式

​ Git

Git安装

git最新版本,没有安装包的话,去官方地址下载https://github.com/git-for-windows/git/releases/download/v2.23.0.windows.1/Git-2.23.0-64-bit.exe

一路next直到安装完毕,保持默认的选项

安装完毕后,打开windows的cmd 命令界面,输入如下命令,来设置自己的用户名和邮箱。

1
2
git config --global user.name "Aaron"
git config --global user.email "Aaron@eagleslab.com"

创建版本库

版本库又名仓库,英文名repository ,你可以简单的解成一个目录,这个目录里面的所有文件都可以被Git管理起来,每个文件的修改、删除,Git都能跟踪,以便任何时刻都可以追踪历史,或者在将来某个时刻可以“还原”。

第一步 找个空的地方创建一个文件夹

第二步 在文件夹中打开cmd界面,然后输入git init 命令把这个目录变成Git可以管理的仓库

image-20191026205132429

我们也可以发现,在这个文件夹中会创建一个.git的目录, 这个目录是Git来跟踪管理版本库的

添加文件到版本库

这边要注意,git只能追踪文本文件的改动,而二进制文件只能记录大小的变化。

第一步

  • 在我们的git文件夹中创建一个记事本文件,不过注意,千万别用windows自带的记事本编辑内容!
  • 在记事本文件中写一些内容,比如学前沿IT,到英格科技
  • 使用命令git add告诉git,把文件添加到暂存区中
1
git add readme.txt

执行上面的命令,没有任何显示

第二步

用命令git commit告诉Git,把文件提交到仓库

1
2
3
4
C:\Users\Aaron\Desktop\gitlearn>git commit -m "write a readme file"
[master (root-commit) 4121352] write a readme file
1 file changed, 1 insertions(+)
create mode 100644 readme.txt

git commit后面的-m是输入本次提交的说明的,可以输入任何内容,最好是自己能看懂的,这样就可以从理事会记录里面方便的找到改动记录。

执行成功后1 file changed 一个文件被改动了,也就是我们添加的readme.txt

1 insertions(+)表示插入了一行内容,我们写的那个学前沿IT,到英格科技

注意

因为在commit前需要add一下,所以可以一次提交多个文件

1
2
3
4
5
6
7
C:\Users\Aaron\Desktop\gitlearn>git add file1.txt
C:\Users\Aaron\Desktop\gitlearn>git add file2.txt
C:\Users\Aaron\Desktop\gitlearn>git commit -m "two files"
[master dc43809] two files
2 files changed, 2 insertions(+)
create mode 100644 file1.txt
create mode 100644 file2.txt

回滚操作

我们修改上面的文件readme.txt

然后使用git status查看

1
2
3
4
5
6
7
8
9
C:\Users\Aaron\Desktop\gitlearn>git status
On branch master
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git checkout -- <file>..." to discard changes in working directory)

modified: readme.txt

no changes added to commit (use "git add" and/or "git commit -a")

git status命令可以让我们时刻掌握仓库当前的状态,上面的命令输出告诉我们,readme.txt被修改过了,但还没有准备提交的修改。

如果想看看具体修改了什么内容,我们可以使用git diff来查看

image-20191026211316876

可以看到在第一行后面加了一个换行符,然后加了一行在下面

下面我们将其添加,然后查看status

image-20191026211507764

git status告诉我们,将要被提交的修改包括readme.txt,下一步,就可以放心地提交了

image-20191026211724339

提交后,我们再用git status命令看看仓库的当前状态:

image-20191026211757079

Git告诉我们当前没有需要提交的修改,而且,工作目录是干净(working tree clean)的

版本回退

我们创建一个文件叫game ,在这个文件中写入以下内容

1
屠龙勇士村来了一个新勇士叫"林克"

然后提交,提交的说明就是”新的开始”

image-20191026212115336

在文件中追加内容

1
勇士赤手空拳来到了野外

然后提交,提交的说明就是”走出新手村”

image-20191026212310506

在文件中追加内容

1
勇士林克被Lv1怪物史莱姆一屁股坐死

然后提交,提交的说明就是”阵亡”

image-20191026212439959

在文件中追加内容

1
勇士林克被公主"塞尔达"所救,丢失全部金币!

然后提交,提交的说明就是”复活”

image-20191026212614476

下面我们来看下这个悲催的勇士的经历,可以使用git log查看历史提交

image-20191026212755780

git log命令显示从最近到最远的提交日志,我们可以看到3次提交

如果嫌输出信息太多,看得眼花缭乱的,可以试试加上--pretty=oneline参数

image-20191026212850868

其实勇士的悲剧完全可以逆转,我们可以读档新的开始,让勇士在出门前带把武器

image-20191026213156010

Git的版本回退速度非常快,因为Git在内部有个指向当前版本的HEAD指针,当你回退版本的时候,Git仅仅是把HEAD从指向新的开始

1
2
3
4
5
6
7
8
9
10
11
┌────┐
│HEAD│
└────┘

└──> ○ 复活

○ 阵亡

○ 走出新手村

○ 新的开始

改为指向add distributed

1
2
3
4
5
6
7
8
9
10
11
┌────┐
│HEAD│
└────┘

│ ○ 复活
│ │
│ ○ 阵亡
│ │
│ ○ 走出新手村
│ │
└──>○ 新的开始

在Git中,用HEAD表示当前版本,上一个版本就是HEAD^,上上一个版本就是HEAD^^,当然往上100个版本写100个^比较容易数不过来,所以写成HEAD~100

Git提供了一个命令git reflog用来记录你的每一次命令:

工作区和暂存区

工作区

就是你在电脑里能看到的目录,比如上面的gitlearn文件夹

image-20191026213858444

版本库

工作区有一个隐藏目录.git,这个不算工作区,而是Git的版本库。

Git的版本库里存了很多东西,其中最重要的就是称为stage(或者叫index)的暂存区,还有Git为我们自动创建的第一个分支master,以及指向master的一个指针叫HEAD

image-20191026214144680

前面讲了我们把文件往Git版本库里添加的时候,是分两步执行的:

第一步是用git add把文件添加进去,实际上就是把文件修改添加到暂存区;

第二步是用git commit提交更改,实际上就是把暂存区的所有内容提交到当前分支。

因为我们创建Git版本库时,Git自动为我们创建了唯一一个master分支,所以,现在,git commit就是往master分支上提交更改。

你可以简单理解为,需要提交的文件修改通通放到暂存区,然后,一次性提交暂存区的所有修改。

管理修改

git不是管理文件,而是管理修改的操作。

我们修改readme.txt,然后add提交到暂存区

image-20191026214759593

然后再次修改readme.txt,这次我们直接commit

image-20191026214923112

然后查看状态

image-20191026214953282

我们会发现第二次修改的并没有被提交

查看一下工作区的文件和仓库的文件的区别

image-20191026215100477

撤销修改

  • 当你改乱了工作区某个文件的内容,想直接丢弃工作区的修改时,用命令git checkout -- file

  • 当你不但改乱了工作区某个文件的内容,还添加到了暂存区时,想丢弃修改,分两步,第一步用命令git reset HEAD,就回到了上一种情况,第二步按上一种情况操作操作。

删除文件

我们将文件从工作区删除

image-20191026220634410

git会直接察觉到我们的删除操作,如果这个时候提交,那么就会从版本库中删除该文件

image-20191026220737779

但是如果误删除了,可以还原到版本库中的最新版本

image-20191026220846139

如果要删除暂存区中的文件,可以使用git rm

远程仓库

注册github

打开命令行,创建key

image-20191026222146813

打开github的个人用户设置

image-20191026222232810

在里面找到SSH and GPG keys

image-20191026222304248

新建一个ssh keys

image-20191026222341875

然后按照下图提示填写

image-20191026222527219

然后你就成功添加了ssh的key,下次登录github的时候,就会直接被识别出你的身份啦

image-20191026222731981

添加远程仓库

首先回到登录之后的页面

image-20191026222810944

创建你的仓库

image-20191026222939132

根据这边的提示可以将我们本地的仓库和远程的仓库关联起来哦

image-20191026223058803

推送成功的画面

image-20191026223328983

观察到远程仓库和我们本地仓库已经关联一致

image-20191026223401158

要关联一个远程库,使用命令git remote add origin git@server-name:path/repo-name.git

关联后,使用命令git push -u origin master第一次推送master分支的所有内容;

此后,每次本地提交后,只要有必要,就可以使用命令git push origin master推送最新修改;

从远程仓库克隆

1
git clone <地址>

分支管理

创建与合并分支

一开始的时候,master分支是一条线,Git用master指向最新的提交,再用HEAD指向master,就能确定当前分支,以及当前分支的提交点:

image-20191027123341011

每次提交,master分支都会向前移动一步,这样,随着你不断提交,master分支的线也越来越长。

当我们创建新的分支,例如dev时,Git新建了一个指针叫dev,指向master相同的提交,再把HEAD指向dev,就表示当前分支在dev上:

image-20191027123400412

你看,Git创建一个分支很快,因为除了增加一个dev指针,改改HEAD的指向,工作区的文件都没有任何变化!

不过,从现在开始,对工作区的修改和提交就是针对dev分支了,比如新提交一次后,dev指针往前移动一步,而master指针不变:

image-20191027123426946

假如我们在dev上的工作完成了,就可以把dev合并到master上。Git怎么合并呢?最简单的方法,就是直接把master指向dev的当前提交,就完成了合并:

image-20191027123523590

合并完分支后,甚至可以删除dev分支。删除dev分支就是把dev指针给删掉,删掉后,我们就剩下了一条master分支:

image-20191027123606591

首先,我们创建dev分支,然后切换到dev分支:

1
2
ubuntu@DESKTOP-HQ0R9B5:/mnt/c/Users/Aaron/Desktop/learngit$ git checkout -b dev
Switched to a new branch 'dev'

git checkout命令加上-b参数表示创建并切换,相当于以下两条命令:

1
2
3
$ git branch dev
$ git checkout dev
Switched to branch 'dev'

然后,用git branch命令查看当前分支:

1
2
3
ubuntu@DESKTOP-HQ0R9B5:/mnt/c/Users/Aaron/Desktop/learngit$ git branch
* dev
master

git branch命令会列出所有分支,当前分支前面会标一个*号。

然后,我们就可以在dev分支上正常提交,比如对readme.txt做个修改,加上一行。

然后提交

image-20191027124746947

切换回master分支后,再查看一个readme.txt文件,刚才添加的内容不见了!因为那个提交是在dev分支上,而master分支此刻的提交点并没有变

image-20191027124809015

现在,我们把dev分支的工作成果合并到master分支上:

image-20191027124912044

git merge命令用于合并指定分支到当前分支。合并后,再查看readme.txt的内容,就可以看到,和dev分支的最新提交是完全一样的。

注意到上面的Fast-forward信息,Git告诉我们,这次合并是“快进模式”,也就是直接把master指向dev的当前提交,所以合并速度非常快。

合并完成后,就可以放心地删除dev分支了:

image-20191027125002911

删除后,查看branch,就只剩下master分支了:

image-20191027125038982

switch

最新版本的Git提供了新的git switch命令来切换分支

创建并切换到新的dev分支,可以使用:

1
$ git switch -c dev

直接切换到已有的master分支,可以使用:

1
$ git switch master

使用新的git switch命令,比git checkout要更容易理解。

命令总结

Git鼓励大量使用分支:

查看分支:git branch

创建分支:git branch

切换分支:git checkout或者git switch

创建+切换分支:git checkout -b或者git switch -c

合并某分支到当前分支:git merge

删除分支:git branch -d

解决冲突

准备新的feature1分支,继续我们的新分支开发:

image-20191027130450579

修改readme.txt最后一行

feature1分支上提交

image-20191027130621731

切换到master分支,修改readme.txt最后一行为别的内容,然后提交

image-20191027130755666

现在,master分支和feature1分支各自都分别有新的提交,变成了这样:

image-20191027130814425

Git无法执行“快速合并”,只能试图把各自的修改合并起来,但这种合并就可能会有冲突

image-20191027130908476

Git告诉我们,readme.txt文件存在冲突,必须手动解决冲突后再提交。git status也可以告诉我们冲突的文件:

image-20191027130931402

我们可以直接查看readme.txt的内容:

image-20191027131016245

Git用<<<<<<<=======>>>>>>>标记出不同分支的内容,我们修改后保存,然后提交:

image-20191027131149032

现在,master分支和feature1分支变成了下图所示:

image-20191027131204136

用带参数的git log也可以看到分支的合并情况:

image-20191027131309319

分支策略

首先,master分支应该是非常稳定的,也就是仅用来发布新版本,平时不能在上面干活

所以,团队合作的分支看起来就像这样

image-20191027131459753

标签管理

创建标签

首先,切换到需要打标签的分支上:

image-20191027131658489

然后,敲命令git tag就可以打一个新标签:

image-20191027131722212

可以用命令git tag查看所有标签:

image-20191027131746160

可以给历史的commit id加上标签

image-20191027131848176

注意,标签不是按时间顺序列出,而是按字母排序的。可以用git show查看标签信息:

image-20191027131920369

还可以创建带有说明的标签,用-a指定标签名,-m指定说明文字:

image-20191027132037874

用命令git show可以看到说明文字:

image-20191027132118336

操作标签

如果标签打错了,也可以删除:

image-20191027132213310

因为创建的标签都只存储在本地,不会自动推送到远程。所以,打错的标签可以在本地安全删除。

如果要推送某个标签到远程,使用命令git push origin

image-20191027132413256

如果标签已经推送到远程,要删除远程标签就麻烦一点,先从本地删除:

image-20191027132447546

然后,从远程删除。删除命令也是push,但是格式如下:

image-20191027132513867

  • 命令git push origin可以推送一个本地标签;
  • 命令git push origin --tags可以推送全部未推送过的本地标签;
  • 命令git tag -d可以删除一个本地标签;
  • 命令git push origin :refs/tags/可以删除一个远程标签。
评论
加载中,最新评论有1分钟缓存...