Git
1、git简介
1.1、什么是Git
- Git是一个开源的分布式版本控制系统,用于敏捷高效地处理任何或大或小的项目。
- Git是Linus Torvalds为了帮助管理Linux内核开发而开发的一个开放源代码的版本控制软件。、
- Git与常用的版本控制工具CVS、Subversion等不同,它采用了分布式版本库的方式,不用服务器端软件支持。
1.2、Git特点
- Git是目前世界上最先进的分布式版本控制系统,在处理各种项目时,都十分高效,而且非常的高大上
1.3、集中式与分布式的区别
集中式:
集中式的版本控制系统每次在写代码时都需要从服务器中拉取一份下来,并且如果服务器丢失了,那么所有的就都丢失了,所以首先要从中央服务器那里得到最新的版本,然后开始干活,干完活后,需要把自己做完的活推送到中央服务器。而且集中式版本控制系统是必须联网才能工作的,一旦断网,所有人都干不成活了,可想而知,集中式版本控制系统的局限性有多大。换句话说,集中式就是把代码放在一个服务器上集中管理,你的所有回滚等操作都需要服务器的支持。
最常见的集中式版本控制系统是SVN
分布式:
分布式在于,每个人的电脑都是服务器,当你从主仓库拉取一份代码下来后,你的电脑就是服务器,无需担心主仓库被删或者找不到的情况,这样,工作的时候就不需要联网了,因为版本都是在自己的电脑上,随时都可以将自己在工作区间做的修改提交到本地仓库,最后将自己的本地版本仓库推动到远程版本仓库进行合并,同时你可以把自己的代码新建一份仓库分享给其它人。
Git是目前世界上最流行的分布式版本控制系统,
Git与SVN的区别:
Git | SVN | |
---|---|---|
核心区别 | 分布式 | 集中式 |
存储方式 | Git按元数据方式存储 | SVN是按文件方式存储 |
分支 | 分支是Git的必杀技能,将Git从版本控制系统的家族中区分出来 | 分支在SVN中一点也不特别,其实它就是版本控制系统中的另外一个目录 |
全局版本号 | Git没有,是目前Git跟SVN缺少的最大特征 | SVN有全局版本号 |
内容完整性 | Git的内容存储使用的是SHA-1哈希算法,确保代码内容的完整性,确保在遇到磁盘故障和网络问题时降低对版本库的破坏 | 在这方面SVN的性能是低于Git的 |
安全性 | 和SVN相比,Git的每个分支都有一个完整的版本库,某个分支的电脑坏掉了,不要紧可以随便从别人那里赋值一份就可了 | 而SVN版本控制系统的中央服务器一旦挂掉,所有人都么的活干了 |
1.4、Git下载安装
在使用Git前我们需要先安装 Git。Git 目前支持 Linux/Unix、Solaris、Mac和 Windows 平台上运行。
Git 各平台安装包下载地址为:http://git-scm.com/downloads
下载好,按默认安装即可(自定义安装路径)。安装完成后,在开始菜单里找到“Git”->“Git Bash”,双击蹦出一个类似命令行窗口的东西,
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-x07NQLx7-1679293975462)(null)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-mb1UIM8E-1679293956573)(null)]
1.5、Git配置
初次使用git需要设置你的用户名以及邮箱,这将作为当前机器git的标识,如果你用它来下载远程仓库一些需要登录权限的仓库会要求登录,git默认使用配置邮箱以及用户名登入,但会要求你手动输入密码
参数讲解:
- config:参数是用来配置git环境的
- –global:长命令表示配置整个git环境
用户名配置
user代表用户,.name代表配置用户的名称
$ git config --global user.name "你的用户名"
邮箱配置
user代表用户,.email代表配置用户的邮箱
$ git config --global user.email "你的邮箱"
因为Git是分布式版本控制系统,所以每个分支都要有自己的名字和邮箱,
注意git config
命令的--global
参数,用了这个参数,表示你这个分支上所有的Git仓库都会使用这个配置,当然也可以对某个仓库指定不同的用户名和Email地址。
理论上来说以上可以自行定义,甚至邮箱可以为一个空的,当然不配置也行,当遇到要求登录权限的远程仓库会让你在手动输入用户名、邮箱、以及密码
# 查看配置信息:
# 查看所有的配置信息
$ git config --list
# 单独查看某项配置:
$ git config user.name
$ git config user.email
1.6、Git 工作流程
一般工作流程如下:
- 克隆Git资源作为工作目录;
- 在克隆的资源上添加或修改文件;
- 如果其他人更改,你可以更新资源;
- 在提交前查看修改状态;
- 提交修改;
- 在修改完成后,如果发现错误,可以撤回提交并再次修改并提交。
1.7、Git 工作区、暂存区和版本库
概念:
工作区: 就是你在电脑上能看到的目录,即下载/克隆下来的文件夹;
暂存区: stage或index,一般放在.git(可隐藏文件)目录下的index文件(.git/index)中,所以我们把暂存区有时候也叫做索引(index);
版本库: 工作区有一个隐藏目录,.git,这个实际上是Git的本地版本仓库。
工作区、版本库中的暂存区和版本库之间的关系:
- 左侧为工作区,右侧为版本库。在版本库中标记为“index”的区域是暂存区(stage/index),标记为“master”的是master主分支代表的目录数。
- HEAD实际上是指向master主分支的一个“游标”(指当前的操作分支)。
- 图中的objects标识的区域为Git的对象库,实际位于“.git/objects”目录下,里面包含了创建的各种对象及内容。
- 当工作区进行修改(或新增)的文件执行
git add
命令时,暂存区的目录树被更新,同时工作区修改(或新增)的文件内容被写入到对象库(此时的对象库可以认为是暂存区中的对象库
)中的一个新的对象中,而该对象的ID被记录在暂存区中的文件索引中。 - 当执行提交操作
git commit
时,暂存区的目录树就被提交到版本库中的对象库(objects)
中,master
主分支会做相应的更新。即master
指向的在暂存区提交过来的目录树。 - 因为我们创建Git版本库时,Git自动为我们创建了唯一一个master分支,所以,现在,
git commit
就是往master
分支上提交更改。 - 可以简单理解为,需要提交的文件修改通通放到暂存区,然后,一次性提交暂存区的所有修改。
2、Git基本命令操作
创建版本库
什么是版本库?版本库又名仓库,英文名Repository,你可以简单成一个目录,这个目录里面的所有文件都被Git管理起来, 每个文件的修改、删除,Git都可以跟踪到,以便任何时刻都可以追踪历史,或者在将来某个时刻可以“还原”。
首先我们选择一个合适的位置,创建一个gitspace空目录(可选),用作以后存储和创建本地版本仓库,在gitspace中创建一个learngit空目录,并切入:
$ mkdir Repository #创建
$ cd Repository #切换
$ pwd #显示当前盘符路径
# /Desktop/Git/Repository
这一步其实可有可无,可以自己创建一个空的文件夹\
2.1、创建文件、文件夹:mkdir、touch
$ mkdir aaa #文件夹名字
$ touch aaa.txt #文件名(需要加后缀)
2.2、创建本地空仓库:git init
# init:初始化当前目录为仓库,初始化后会自动将当前仓库设置为master
# 创建本地仓库的条件是需要一个空目录,然后在空目录中初始化你的项目
$ git init
Initialized empty Git repository in /Desktop/Git/Repository/.git/
注意:生成的文件夹为一个隐藏文件夹,
ls / ll
是无法看到 需要加-a
或者-ah
即ll -a / ll -ah
2.3、新建文件添加到本地仓库:git add、git commit -m
add:将文件添加到缓存区
commit:提交到本地仓库
使用git add命令将文件添加到本地仓库的提交缓存
$ git add test.txt
这个时候还不算添加到了本地仓库,我们还需要使用git commit命令为其添加修改的描述信息
注意在使用git commit时我们只需要简单描述一下我们做了什么,不要像写注释那样写一大堆,不然将来在回滚代码或者查看历史版本时,很难审阅。
我们需要使用-m命令来简写描述我们的信息,如果不使用-m,会调用终端的注释编辑器让你输入描述信息,但是不建议使用,因为注释编辑器比较难用,不舒服。
$ git commit -m "add new file \"test.c\""
2.4、改写提交:git commit --amend
–amend:重写上一次的提交信息
就像刚刚的列子里一样,我们提交了仓库,但是发现注释写错了,我们可以使用 --amend长命令选项来改写提交
git commit --amend
输入上面的命令后会进入如下编辑器界面:
在界面中按下“i”即可进入编辑界面
修改完成后按:ctrl+o
->:wq
保存退出
2.5、查看历史提交日志:git log
log:查看日志
正如刚刚改写提交的,想要确定是否改写成功,我们可以使用git log查看一下
git log
可以看到没有生成新的版本号,而是直接改写了刚刚提交的注释
第一行的commit是哈希算法算出的id,正如一开始所说,分布式是没有一个主版本号的,它们都是用id来做标志的,同时用master作为主仓库,其它的分支怎么迭代都不会影响到master
commit 5c360a53a453189ba76ffae31966fdf682327c7e (HEAD -> master)
后面的head是指向的意思,表示这次提交到哪儿,head->master代表这次提交到master主仓库,如果是head->分支仓库则代表提交到分支仓库
Author是提交者是谁的意思,显示格式是:用户名 <邮箱>
Author: weike.shisan <weike.shisan@gmail.com>
Date的意思是提交时间,后面的+0800这个是格林尼治时间,代表当前是以哪儿的时间地作为基准,这是世界时间,用它来作为基数与当前所在地时差进行计算,包括地球自转等公式。
Date: Sun Mar 19 18:30:21 2023 +0800
最下面的就是注释了
hh add new file "test.c"
2.6、回滚代码仓库:git reset --hard
reset参数是重置命令
–hard是重置代码仓库版本
有三种模式
–soft 、–mixed以及–hard是三个恢复等级。
- 使用–soft就仅仅将头指针恢复,已经add的暂存区以及工作空间的所有东西都不变。
- 如果使用–mixed,就将头恢复掉,已经add的暂存区也会丢失掉,工作空间的代码什么的是不变的。
- 如果使用–hard,那么一切就全都恢复了,头变,aad的暂存区消失,代码什么的也恢复到以前状态。
-
回滚到指定历史版本
先使用git log查看历史版本
git log
在使用git reset --hard命令回滚
git reset --hard 要回滚id
示列:
使用git log回滚
第一行的commit后面的字符串就是我们的哈希id
回滚的时候我们只需要字符,其它的都不需要!
2.回滚当前仓库指向的版本
上面说过,HEAD是指向当前仓库的,历史版本中可能有别的分支,我们只想迭代我们仓库的上一个版本,这个很简单,我们只需要用HEAD来指向就可以了
git reset --hard HEAD^
^代表上一个版本的意思,HEAD代表当前仓库的指向,当前HEAD指向master,就代表回滚到master上一次提交的版本
当然我们也可以使用另外一种方式来回滚到当前仓库的指定版本
git reset --hard HEAD~3
后面的~3,代表以当前版本为基数,回滚多少次。HEAD~3代表回滚master前三个版本
如果觉得log打印内容过多,可以加上–pretty=oneline选项简洁输出
2.7、查看提交之后文件是否做了改动:git status
status:查看当前仓库状态
我们在提交完成之后,有时候可能自己不小心改动了某个文件,或者别人,我们可以使用git status查看文件是否被改动
我们修改一下刚刚提交的test.txt文件,在里面随便输点字符,并且添加一个新的文件
保存退出,然后使用git status查看
可以看到报出了修改
2.8、将文件撤销回到最近一次修改的状态:git checkout – file
checkout:切换参数,通常用来切换分支仓库
当我们在工作中修改了一个文件,猛然间发现内容好像改的不对,想重新修改,这个时又不知道自己改了什么代码,想撤销修改,有一个最简单的方法,就是git checkout – file,注意中间要有“–”,checkout这个命令是切换分支的功能,关于它我们后面在细说,你现在只需要知道这个命令加上“–”可以用来将文件切换到最近一次的状态
注意
- 这个恢复只能恢复到上一次提交的状态,如你刚提交了这个文件到仓库,随后你修改了它,那么使用这个命令只会回到刚刚提交后的那个状态里,不能回到你还没有提交,但修改的状态中。
- 这个功能不能一直迭代恢复,如你恢复到了修改前的版本,你想再次回滚回滚到修改前在之前的版本是不行的。
2.9、查看单个文件可回滚版本:git log filename
当我们想回滚指定文件到指定版本时,需要查看该文件有多少个版本可以回滚时,可以使用git log filename命令
2.10、删除文件:git rm
如果我们使用普通的命令,rm删除文件,git状态会提示你删除了文件,你只需要使用add重新提交一次就可以了。
当然你也可以使用git rm删除文件,但是也需要使用git commit提交一次
2.11、查看提交历史:git reflog
git reflog可以查看当前版本库的提交历史,凡是对仓库版本进行迭代的都会出现在这个里面,包括你回滚版本都会出现在这个历史中
2.12、git rm后恢复文件:git rm、git reset、git checkout
此方法仅限git rm,因为git rm会先将文件放入缓存区,且没有使用commit提交的情况下
首先使用git rm删除一个文件
git rm d.c
在使用git reset重置所有缓存区操作
git reset
重置完成之后在使用git checkout命令将文件取消操作
git checkout d.c
如果已经提交了想恢复怎么办?
这里给一个方法,就是把当前目录全部提交一次,这样做是为了防止我们等下回滚的时候导致一些修改的文件被替换掉了,然后我们回滚到有那个文件的版本,将那个文件copy到别的文件目录,这个文件目录要是你记得的,然后在回滚到最新版本代码,在将那个文件copy回来,在提交进去。
2.13、git创建分支:git branch、git checkout
使用git checkout -b参数来创建一个分支,创建完成分支后会自动切换过去
git checkout -b dev
然后我们在使用branch来查看当前属于哪个分支,也就是查看HEAD的指向
git branch
git checkout -b等价于
git branch dev
git checkout dev
git branch 如果后面跟着名字则会创建分支,但不会切换
git checkout 后面如果是分支名称则切换过去
2.14、git切换分支:git checkout
当我们想切换分支可以使用git checkout来切换,如刚刚我们创建了一个分支dev并切换了过去,现在切换回masterk
git checkout master
2.15、git合并分支:git merge
当我们新建分支并做完工作之后,想要把分支提交至master,只需要切换到master仓库,并执行git merge 分支名就可以了
如我们在分支中新建了一个f.c和test.c的文件
然后在使用git checkout master切换到master
在使用git merge dev将其合并
这里需要说一点,如果你在任何分支下创建文件,没有提交到仓库,那么它在所有仓库都是可见的,比如你在分支dev中创建了一个文件,没有使用git add和git commit提交,此时你切换到master,这个文件依旧存在的,因为你创建的文件在工作目录中,你切换仓库时git只会更新跟仓库有关的文件,无关的文件依然存放在工作区。
2.16、git查看分支:git branch -a
git branch -a
2.17、git删除本地分支:git branch -D
git branch -D 分支名
# 如果遇到无法删除的分支可以使用git branch -D 大写的D即可。
2.18、git删除远程分支:git push origin --delete
注意这里的远程分支名不需要加origin,输入分支名就可以了
git push origin --delete 远程分支名
3、对接远程库
3.1、创建远程库
3.2、给远程地址设定别名
# 添加别名
git remote add origin "远程仓库地址"
# 查看别名
git remote -v
3.3、推送
git push origin master
3.4、克隆
如果远程库是私有库,那么需要登录账号密码。
git clone "仓库地址"
克隆命令有三个效果:
- 自动初始化本地库,也就是自动创建.git目录,不需要执行git init命令了
- 下载远程库所有文件、目录
- 自动创建远程库地址别名
3.5、拉取
如果远程库是私有库,那么需要登录账号密码。
git pull origin master
3.6、跨团队协作
Tips
- 隐藏文件夹,
ll / ls
是无法看到 需要加 -a或者-ah 即ll -a / ll -ah
- git 命令中如果携带的是单词的命令一般是以–开头
- 在进行add添加时一帮会采取–all进行文件的一个全部提交,即:
git add --all
git基本组成框架:Workspace、Index / Stage、Repository、Remote
Workspace:开发者工作区
Index / Stage:暂存区/缓存区
Repository:仓库区(或本地仓库)
Remote:远程仓库
Workspace:开发者工作区,也就是你当前写代码的目录,它一般保持的是最新仓库代码。
Index / Stage:缓存区,最早叫Stage,现在新版本已经改成index,位于.git目录中,它用来存放临时动作,比如我们做了git add或者git rm,都是把文件提交到缓存区,这是可以撤销的,然后在通过git commit将缓存区的内容提交到本地仓库
Repository:仓库区,是仓库代码,你所有的提交都在这里,git会保存好每一个历史版本,存放在仓库区,它可以是服务端的也可以是本地的,因为在分布式中,任何人都可以是主仓库。
Remote:远程仓库,只能是别的电脑上的仓库,即服务器仓库。
在开发中git分支的重要性
当我们在开发中,无论做什么操作都建议使用分支,因为在团队开发中,master只有一个,合作开发里任何人都可以从master里拉取代码,拉取时master后创建分支,分支名改为你要做的操作,比如修改某某文件,修改什么什么bug,单词以下划线做分割,然后在提交一个版本
分支名必须简洁,和标题一样,提交的commit在简单描述一下就可以了。
如我们的master中有个bug,是内存泄漏
我们可以常见一个分支名为Memory_Leak,然后在commit里简单描述一下修复了哪个模块的内存泄漏,不要写修复了什么什么代码,什么什么问题导致的,只需要简单描述一下就可以了。
一般情况下,我们都是拉取master后,想要修改功能或者添加功能,都是创建分支,在分支里修改不影响master,如果修改错了代码或者误删之类的,在从master上拉取一份就可以了。