Git原理+使用(超详细)

Git初识

当我们写项目代码时,需要不断的更新版本,那么就需要一个东西去管理这些不同版本的文件---版本控制器。

目前最主流的版本控制器就是Git。它是一个可以记录工程的每一次改动和版本迭代的管理系统,同时方便多人协同作业。

!注意:Git只能跟踪文本文件的改动,比如第几行改了什么,但是图片,视频,二进制文件,并不能直观的观察到改了什么,比如只知道图片从100kb变为120kb。

安装Git

前言(目前显示的ubuntu平台)

你可以通过输入git来看看有没有安装Git,如果安装了就会弹出以下界面。

安装Git

sudo apt-get install git -y

查看Git安装版本

Git基本操作

创建Git本地仓库

因为仓库是进行版本控制的文件目录,要想对文件进行版本控制,就必须先创建一个仓库。

我们先创建一个gitcode目录,后续操作都在这个目录里面进行。

通过 git init命令创建一个本地仓库

之后我们会发现有个.git的隐藏文件 ,注意不要修改这个目录的文件,它是用来跟踪管理仓库的,我们可以输入tree .git命令进去看看

配置Git

安装完Git后最好先设置你的用户名称和e-mail地址。

git config --global user.name "Your Name"
git config --global user.email "email@example.com"

your name改为你的名字
email "email@example.com改为你的邮箱

--global是个可以选项,如果带上该选项表明这台机器上的所有Git仓库都会用这个配置,如果希望不同仓库有不同的名称和邮箱地址就不要带 。

可以通过一个命令来查看配置

复制代码
root@hecs-95072:~/gitcode# git config -l
user.name=pikes
user.email=2994322314@qq.com
core.repositoryformatversion=0
core.filemode=true
core.bare=false
core.logallrefupdates=true

删除对应命令配置

git config --global --unset user.name
git config --global --unset user.email

工作区,暂存区,版本库

  • 工作区:也就是电脑上要写的代码或文件的目录
  • 暂存区:一般存放在.git目录下的index文件中
  • 版本库:也叫仓库,这个版本库中的所有文件都可以被Git管理起来,对于每个文件的修改,删除,Git都能跟踪。

在工作区写的代码和文件 必须通过git add命令,让暂存区的文件索引更新,再通过git commiit命令才能将文件添加到仓库中进行管理~

添加文件

我们可以在包含.git的目录下创建一个文件,写入一些内容,使用git add命令将文件添加到暂存区

• 添加⼀个或多个⽂件到暂存区: git add file1 file2 ...
• 添加指定⽬录到暂存区,包括⼦⽬录: git add dir
• 添加当前⽬录下的所有⽂件改动到暂存区: git add .

使用 git commit命令将暂存区的内容添加到仓库中

• 提交暂存区全部内容到本地仓库中: git commit - m "message"
• 提交暂存区的指定⽂件到仓库区: git commit file1 file2 ... - m "message"

注意 -m选项是要描述本次提交的message信息,以确保下次查看时知道本地提交的具体信息

通过 git log命令查看历史提交记录,因为我提交过几次,所以会出现一下信息

如果想看简便的信息,可以加上一个参数

前面一大串黄色的字符串是每次提交的commit id。

查看.git目录

1:index就是我们的暂存区,add后的内容就添加在这里

**2:**HEAD就是我们默认指向master分支的指针

可以通过命令来查看

root@hecs-95072:~/gitcode# cat .git/HEAD
ref: refs/heads/master
root@hecs-95072:~/gitcode# cat .git/refs//heads/master
946c80e794901d4169040596e7d827647dc1e829

打引出来的字符串就是最新的commit id

3:objects是Git的对象库,里面包含了创建的各种版本库对象和内容,当执行git add命令时,暂存区目录更新,同时工作区被修改的文件内容被写入到对象库中一个新的对象中

我们可以看看object里面有什么

commit id分为两部分,前两位是文件夹名称,后38位是文件名称。因为文件是经过安全哈希算法加密过的文件,我们要使用git cat-file命令来查看版本库对象的内容

可以看到有一行tree c8d28685fa88d74a960702c1674b1559623b2c09。用同样的命令查看

再继续看ReadMe中对应的

这样就看到了我们刚刚做的修改。

修改文件

当我们对ReadMe文件进行修改后,仓库中的ReadMe和工作区中的ReadMe是不同的,可以通过git status来查看距上次提交之后是否对文件进行修改。

它提示了,我们修改过了ReadMe但并没有添加和修改。

当我们好几个月前修改的代码,我们通过这个命令是看不到具体什么地方被修改的,所以我们就需要通过另一个命令来显示暂存区和工作区文件的差异git diff file, 也可以通过**git diff HEAD -- file**命令查看版本库和工作区的文件区别

版本回退

因为我们提到过,Git能够管理文件的历史版本,这也是它的主要作用之一。如果你因为工作出现问题,要在某个特定的历史版本重新开始,就需要版本回退功能了。

执行git reset命令用于回退版本,回退的本质是将版本库中的内容回退,工作区和暂存区是否回退由命令参数决定:

git reset -- soft \| -- mixed \| -- hard HEAD

|---------------------------|----------------------------|----------------|-----------|
| --soft | --mixed | --hard | HEAD |
| 将版本库回退到某个指定版本工作区,工作区暂存区不变 | 默认选项,将暂存区的内容回退指定版本内容,工作区不变 | 暂存区和工作区回退到指定版本 | 代表指定回退的版本 |

• HEAD 说明:
◦ 可直接写成 commit id,表⽰指定退回的版本
◦ HEAD 表⽰当前版本
◦ HEAD^ 上⼀个版本
◦ HEAD^^ 上上⼀个版本
◦ 以此类推...
• 可以使⽤ 〜数字表⽰:
◦ HEAD~0 表⽰当前版本
◦ HEAD~1 上⼀个版本
◦ HEAD^2 上上⼀个版本
◦ 以此类推..

版本回退原理

Git的版本回退速度非常快,因为Git内部有个指向当前分支的HEAD指针,就是refs/heads/master文件里保存的当前的master分支最新的commit id,当我们回退时候,master指针就会指向对应版本。

撤销修改

当我们在工作区写了很长时间代码后,但是老板不满意需要恢复到上一个版本怎么办,这时候分为三种情况:

1.工作区的代码,还没有add

复制代码
root@hecs-95072:~/gitcode# vim ReadMe 
root@hecs-95072:~/gitcode# cat ReadMe 
大鹏一日同风起,扶摇直上九万里.
剑气纵横三万里,一剑光寒十九州.
皮克斯来了
测试撤销修改 //新增代码

可以使用git checkout -- file命令会到最近一次add或者commit时状态

2.已经add,但没有commit

我们可以使用git reset命令,带上--mixed参数,然后用git checkout -- file命令撤销在工作区的修改

3.已经add和commit

可以用git reset --hard HEAD^命令回退到上一个版本,但有个前提,就是还没有把自己本地版本库推送到远程。

删除文件

可以通过git rm file命令删除暂存区和工作区文件

复制代码
root@hecs-95072:~/gitcode# touch test1 //创建文件
root@hecs-95072:~/gitcode# ls
ReadMe  test1
root@hecs-95072:~/gitcode# git add test1  //add到暂存区
root@hecs-95072:~/gitcode# git commit -m "add test1"  //提交到版本库
[master 7b8ebfd] add test1
 1 file changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 test1
root@hecs-95072:~/gitcode# git status
On branch master
nothing to commit, working tree clean
root@hecs-95072:~/gitcode# git rm test1  。。删除暂存区和工作区的test1文件
rm 'test1'
root@hecs-95072:~/gitcode# git status  //查看状态
On branch master
Changes to be committed:
  (use "git restore --staged <file>..." to unstage)
	deleted:    test1

root@hecs-95072:~/gitcode# git commit -m "delete test1"  //提交修改结果
[master 729581a] delete test1
 1 file changed, 0 insertions(+), 0 deletions(-)
 delete mode 100644 test1
root@hecs-95072:~/gitcode# git status
On branch master
nothing to commit, working tree clean

分支管理

分支管理是Git的最重要的功能之一,就像两个平行宇宙,你正在学习Git,另一个平行宇宙的你在学习Redis,两者互不干扰,但在一个时间点重合,这时的你既学会了Git又学会了Redis。

刚刚版本回退的图里面已经知道,每次提交,Git都会把它们串成一条时间线,一个时间线就是一个分支,master分支就是主分支。

HEAD是指向master的master指向提交,所以HEAD指向的就是当前分支。

创建分支

可以通过git branch dev创建一个dev分支,用git branch命令查看当前本地所有分支

*表示当前HEAD指向的分支是master分支,这时我们查看目录结构就可以看到新的分支

切换分支

我们可以切换到dev分支下进行开发,使用git checkout命令

这时HEAD就指向了dev分支上,下图便于理解:

我们可以在dev分支上进行操作并提交,再回到master分支上看看结果是不是一样

可以看到master分支上的内容并没有变化,可以看看dev和master分支指向,发现两者指向是不同的:

是因为我们在dev分支上提交的,切换到master分支后,master分支此刻的提交点并没有改变,HEAD此时指向的是master分支,如图所示:

合并分支

我们要在master分支上看到新的提交,就需要将dev分支合并到master分支上:

git merge命令用于合并指定分支到当前分支,合并后,master就能看到dev分支提交的内容了

删除分支

合并冲突

当我们想合并分支时,并不是每次都会成功,比如下面这个例子:

复制代码
root@hecs-95072:~/gitcode# cat ReadMe 
大鹏一日同风起,扶摇直上九万里.
剑气纵横三万里,一剑光寒十九州.
皮克斯来了
测试dev分支
测试合并冲突aaa  //修改代码
root@hecs-95072:~/gitcode# git add ReadMe 
root@hecs-95072:~/gitcode# git commit -m "测试合并冲突"
[dev d1b0845] 测试合并冲突
 1 file changed, 1 insertion(+), 1 deletion(-)
root@hecs-95072:~/gitcode# git checkout master
Switched to branch 'master'
root@hecs-95072:~/gitcode# cat ReadMe 
大鹏一日同风起,扶摇直上九万里.
剑气纵横三万里,一剑光寒十九州.
皮克斯来了
测试dev分支
测试合并冲突111
root@hecs-95072:~/gitcode# vim ReadMe 
root@hecs-95072:~/gitcode# cat ReadMe 
大鹏一日同风起,扶摇直上九万里.
剑气纵横三万里,一剑光寒十九州.
皮克斯来了
测试dev分支
测试合并冲突bbb  //此时master也进行修改
root@hecs-95072:~/gitcode# git merge dev
Updating d35e425..d1b0845
error: Your local changes to the following files would be overwritten by merge:
	ReadMe
Please commit your changes or stash them before you merge.
Aborting

这时合并就会有冲突,如下图所示:

这时就要手动调整冲突代码,并再次提交修正后的结果

这时冲突就解决完成,此时状态变为:

分支管理策略

我们在合并分支时,如果顺利,Git会采用Fast forward模式,删除分支后,查看分支历史,看不到分支信息,不知道最新提交的是合并进来的还是正常提交的。

但在合并冲突部分,我们会进行一次新的提交,这种不是Fast forward模式,这样的好处是,可以从分支历史看出分支信息,下图可以看到master是由其他分支合并得到的:

其实Git支持我们不使用这个模式,那么就会在merge时生成一个新的commit,这样从分支历史上就可以看出分支信息。

首先创建分支test,切换到此分支,修改ReadMe文件,并提交一个新的commit

切回master分支,合并两个分支

这里加上了 --no-ff参数,表示禁用Fast forward模式,因为禁用后会创建一个新的commit,所以要带上-m参数,写上本次描述。

本次普通合并的状态为:

分支策略

在平时开发中,我们应该按照几个基本原则进行分支管理;

首先,master分支是非常稳定的,最好仅用来发布新版本,不能在上面干活,干活都在其他分支上,到时候将其他分支合并到master上,在master上发布新版本。

bug分支

加入我们在test分支上进行开发,开发到一半,发现master分支上有bug需要解决。在Git中,每个bug都可以通过一个新的临时分支来修复,修复后,合并分支,然后将临时分支删除。

当我们test分支工作区的代码写了一半,还无法提交怎么办?Git提供了git stash命令,可以将当前工作区信息进行储藏,被储藏的内容可以在某个时刻恢复出来。

此时就可以看到,执行完git stash命令后,用git status查看工作区就是干净的,接下来就可以安心处理bug。

root@hecs-95072:~/gitcode# git checkout -b bug //创建bug分支

Switched to a new branch 'bug'

root@hecs-95072:~/gitcode# vim ReadMe

root@hecs-95072:~/gitcode# cat ReadMe

大鹏一日同风起,扶摇直上九万里.

剑气纵横三万里,一剑光寒十九州.

皮克斯来了

测试dev分支

测试合并冲突aaa

测试分支策略 假设修复完毕 //假设修复完毕

root@hecs-95072:~/gitcode# git add ReadMe //重新add和commit

root@hecs-95072:~/gitcode# git commit -m "修复bug"

bug 7bef88b 修复bug

1 file changed, 1 insertion(+), 1 deletion(-)

root@hecs-95072:~/gitcode# git checkout master

Switched to branch 'master'

root@hecs-95072:~/gitcode# git merge --no-ff -m "merge bug branch" bug

Merge made by the 'ort' strategy.

ReadMe | 2 +-

1 file changed, 1 insertion(+), 1 deletion(-)

root@hecs-95072:~/gitcode# cat ReadMe

大鹏一日同风起,扶摇直上九万里.

剑气纵横三万里,一剑光寒十九州.

皮克斯来了

测试dev分支

测试合并冲突aaa

测试分支策略 假设修复完毕

root@hecs-95072:~/gitcode# git branch -d bug //删除bug分支

Deleted branch bug (was 7bef88b).

此时,bug修复完毕,再回到test分支继续敲代码,可以看看刚刚的代码跑哪去了

我们可以通过git stash pop或者git stash apply命令来恢复,主要区别是前者恢复同时会把stash删了,后者不会。

但此时test分支并不能看见修复bug的代码,因为合并操作会冲突,我们最好在自己分支上合并master,再让master去合并自己分支,这样即便在解决冲突时出现错误,也不会影响master分支。(此处就不展示了)

删除临时分支

当我们需要添加实验性质代码时,为了不影响主代码,可以新建一个分支,称为feature分支,在上面开发,合并,最后删除。

但如果写到一半,这个分支不要了,用传统的git branch -d 命令删除是不行的,需要用到 git branch -D命令

相关推荐
炸炸鱼.25 分钟前
Git+Jenkins实战(一):从零搭建自动化发布与回滚系统(附完整代码)
git·jenkins
言6663 小时前
要忽略前端依赖包node_modules的文件在目录下 git暂存区消失
git
胡小禾4 小时前
Git Worktree
git
程序员小羊!4 小时前
18 GIt
git
怣疯knight4 小时前
Git 本地分支关联远程分支 常用命令汇总
git
ANNENBERG5 小时前
git分支开发管理
git
坤坤藤椒牛肉面5 小时前
GIT的使用
git
w3296362715 小时前
使用 OpenCode 在 Windows 上加速安装 Playwright 的完整指南
windows·git
我家媳妇儿萌哒哒1 天前
git:无法推送refs到远端。您可以试着运行“拉取”功能,整合您的更改。
git
驯龙高手_追风1 天前
Gitlab本地服务器搭建及配置-详细教程
git·github