Git 基础知识与常用操作详解

Revision control

如上,我们经常会为了文件保存曾经的改动,将新版本另存为一个文件,最后你的变成了这样:

之后想找回被删除的文字,但是已经记不清删除前保存在哪个文件里了,只好一个一个文件去找。然后想保留最新的一个,把其他的删掉,但是有可能之前的改动以后会用到。

一个文件需要团队共同完成,每个人负责不同模块,完成后需要合并各个模块到最终的文件中,如何规模较大的话,将会非常麻烦。

如果有一个软件,不但能自动帮助记录每次文件的改动,还可以让其他团队成员协作编辑,这样就不用自己管理一堆类似的文件了,也不需要把文件传来传去。如果想查看某次改动,只需要在软件里查看就可以,岂不是很方便?

这个软件用起来就应该像这个样子,能记录每次文件的改动:

版本文件名用户说明日期
1service.doc张三删除了软件服务条款7/12 10:38
2service.doc张三增加了License人数限制7/12 18:09
3service.doc李四财务部门调整了合同金额7/13 9:51
4service.doc王五延长了免费升级周期7/14 15:17

版本控制是一种记录一个或若干文件内容变化,以便将来查阅特定版本修订情况的系统

采用版本控制系统(VCS)可以将某个文件回溯到之前的状态,甚至将整个项目都回退到过去某个时间点的状态。可以比较文件的变化细节,查出最后是谁修改了哪个地方,从而找出导致问题出现的原因。使用版本控制系统通常还意味着,就算把整个项目中的文件改的改删的删,也照样可以轻松恢复到原先的样子。但额外增加的工作量却微乎其微。

本地版本控制系统

许多人习惯用复制整个项目目录的方式来保存不同的版本,或许还会改名加上备份时间以示区别。 这么做唯一的好处就是简单,但是特别容易犯错。 有时候会混淆所在的工作目录,一不小心会写错文件或者覆盖意想外的文件。

为了解决这个问题,人们很久以前就开发了许多种本地版本控制系统,大多都是采用某种简单的数据库来记录文件的历次更新差异


集中式版本控制系统

接下来人们又遇到一个问题,如何让在不同系统上的开发者协同工作?

于是,集中化的版本控制系统( Centralized Version Control Systems,简称 CVCS )应运而生。这类系统,诸如 CVS,Subversion 以及 Perforce 等,都有一个单一的集中管理的服务器,保存所有文件的修订版本,而协同工作的人们都通过客户端连到这台服务器,取出最新的文件或者提交更新。多年以来,这已成为版本控制系统的标准做法。

这种做法带来了许多好处,特别是相较于老式的本地 VCS 来说。 现在,每个人都可以在一定程度上看到项目中的其他人正在做些什么。 而管理员也可以轻松掌控每个开发者的权限,并且管理一个 CVCS 要远比在各个客户端上维护本地数据库来得轻松容易。

这么做最显而易见的缺点是中央服务器的单点故障。 如果宕机一小时,那么在这一小时内,谁都无法提交更新,也就无法协同工作。 如果中心数据库所在的磁盘发生损坏,又没有做恰当备份,毫无疑问你将丢失所有数据——包括项目的整个变更历史,只剩下人们在各自机器上保留的单独快照。 本地版本控制系统也存在类似问题,只要整个项目的历史记录被保存在单一位置,就有丢失所有历史更新记录的风险

另一个缺点便是必须联网才能工作,如果在局域网内还好,带宽够大,速度够快,可如果在互联网上,遇到网速慢的话,可能提交一个10M的文件就需要5分钟。


分布式版本控制系统

为了解决上述问题,分布式版本控制系统(Distributed Version Control System,简称 DVCS)面世了。 在这类系统中,像 Git、Mercurial、Bazaar 以及 Darcs 等,客户端并不只提取最新版本的文件快照,而是把代码仓库完整地镜像下来。 这么一来,任何一处协同工作用的服务器发生故障,事后都可以用任何一个镜像出来的本地仓库恢复。 因为每一次的克隆操作,实际上都是一次对代码仓库的完整备份。更进一步,许多这类系统都可以指定和若干不同的远端代码仓库进行交互


因此,由于每个人的电脑上都是一个完整的版本库,那么在工作的时候,就不需要联网了,因为版本库就在本机上

About Git

Git是一个开源的分布式版本控制系统,可以有效、高速地处理从很小到非常大的项目版本管理。Git具有以下特点:

  • 直接记录快照,而非差异比较
  • 近乎所有操作都是本地执行
  • 时刻保持数据完整性
  • 多数操作仅添加数据

Git工作原理:https://git-scm.com/book/zh/v2/%E8%B5%B7%E6%AD%A5-Git-%E5%9F%BA%E7%A1%80
在这里插入图片描述


安装Git

在Linux下安装Git

使用 Debian 或 Ubuntu,安装 Git 使用一条命令即可:

sudo apt-get install git

安装结束后,我们直接输入git命令即可查看帮助
在这里插入图片描述


如果是其他Linux版本,可以直接通过源码安装。先从Git官网下载源码,然后解压、配置安装目录、编译、安装即可。
git - 2.9.4 : https://mirrors.edge.kernel.org/pub/software/scm/git/git-2.9.4.tar.xz

1、解压Git安装包

2、解压完成后进入git-version目录

3、配置git安装路径

4、编译并安装

5、查看git版本号

我们发现系统提示,没有git命令,我们打开配置文件 /etc/profile,在Path manipulation 下的if then 后添加 pathmunge 命令路径 :

pathmunge /usr/loacl/git/bin

完成后保存退出,终端下输入 sourse /etc/profile 使配置文件立即生效

我们同样可以直接使用 git 查看命令帮助

6、设置环境变量
在主目录的.bash_profile或者/etc/profile文件加入设置环境变量

export PATH=$PATH:/usr/local/git/bin

Windows下安装Git

在Windows上使用Git,可以从Git官网直接下载安装程序,然后按默认选项安装即可。
在这里插入图片描述
安装完成后,在开始菜单里找到 “Git” -> “Git Bash”,弹出一个类似命令行窗口的东西,就说明Git安装成功!
在这里插入图片描述
其中的MINGW64是GCC C编译器的Windows端口


Git初始配置

安装完成后,还需要最后一步设置,在命令行输入:

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

因为Git是分布式版本控制系统,所以,每个机器都必须自报家门:姓名和Email地址
注意:git config命令的–global参数,用了这个参数,表示这台机器上所有的Git仓库都会使用这个配置,当然也可以对某个仓库指定不同的用户名和Email地址。

若第一次使用Git没有进行初始配置,那么在commit提交到本地库时会出现提示,要求设置默认验证信息(name + email)。如下图所示:

示例如下图:


创建版本库

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

所以,创建一个版本库非常简单,首先,选择一个合适的地方,创建一个空目录,
通过pwd命令我们可以看到,这个仓库位于/home/zy/Desktop/learnGit

通过git init命令把当前目录变成Git可以管理的仓库
在这里插入图片描述
瞬间Git就把仓库建好了,而且告诉你是一个空的仓库(empty Git repository),我们可以发现当前目录下多了一个.git的目录,这个目录是Git来跟踪管理版本库的。===》 .git 文件夹详解

也不一定必须在空目录下创建Git仓库,**选择一个已经有文件的目录也是可以的。
**。


添加文件到版本库

所有的版本控制系统,其实只能跟踪文本文件的改动,比如TXT文件,网页,所有的程序代码等等,Git也不例外。

版本控制系统可以告诉你每次的改动,比如在第5行加了一个单词“Linux”,在第8行删了一个单词“Windows”。而图片、视频这些二进制文件,虽然也能由版本控制系统管理,但没法跟踪文件的变化,只能把二进制文件每次改动串起来,也就是只知道图片从100KB改成了120KB,但到底改了啥,版本控制系统不知道,也没法知道。

Microsoft的Word格式是二进制格式,因此,版本控制系统是没法跟踪Word文件的改动的

  • 文本编码建议使用UTF-8
  • Windows下文本文件编辑使用Notepad++代替记事本,默认编码设置为UTF-8 without BOM。

现在我们编写一个README.txt文件,内容如下:

一定要放到仓库的目录或子目录下,因为这是一个Git仓库,放到其他地方Git是无法找到的。

1、使用命令 git add 把文件添加到暂存区

执行上面的命令,成功的话是没有提示的。

2、使用命令 git commit 告诉Git,把文件提交到本地仓库

-m 参数后面输入的是本次提交的说明,最好是有意义的,这样就能从历史记录里方便地找到改动记录

git commit命令执行成功后会有提示:

  • 1 file changed:1个文件被改动(我们新添加的README.txt文件)
  • 1 insertions:插入了一行内容(README.txt有一行内容)。

“创建版本库”总结

1、初始化一个Git仓库,使用git init命令。

2、添加文件到Git本地仓库,分两步:

  • 使用命令 git add < filename > 添加文件从工作区到缓存区,可反复多次使用,添加多个文件;
  • 使用命令git commit -m < message >,添加文件从缓冲区到本地仓库,完成。

修改文件

我们已经成功地添加并提交了一个README.txt文件,是时候继续工作了,于是,我们继续修改README.txt文件,改成如下内容:

现在,运行git status命令看看结果:
在这里插入图片描述
git status命令可以让我们时刻掌握仓库当前的状态,上面的命令输出告诉我们,README.txt被修改过了,但还没有准备提交的修改

虽然git status命令仅仅告诉我们readme.txt被修改了,不能查看改动内容。

我们可以使用git diff这个命令方便地查看具体修改了什么内容。

git diff顾名思义就是查看difference,显示的格式正是Unix通用的diff格式,可以从上面的命令输出看到,我们在第二行添加了一个语句

接下来我们将修改提交到仓库,提交修改和提交新文件是一样的两步。

第一步是git add ,同样没有任何输出。在执行第二步git commit之前,我们再运行git status看看当前仓库的状态:

git status告诉我们,将要被提交的修改包括README.txt,下一步,就可以放心地提交了:
在这里插入图片描述
提交后,我们再用git status命令看看仓库的当前状态:

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


"修改文件"小结

  • 随时掌握工作区的状态,使用git status命令。
  • 如果使用git status发现有文件被修改过,用 git diff 可以查看修改内容
  • 提交修改和提交新文件的步骤是一样的(git add & git commit 、git commit -am)

Git版本控制操作

版本回退

现在,再次修改README.txt文件如下:

由于我们之前使用git add跟踪过README.txt文件,那么我们直接可以使用git commit -am 提交修改:
在这里插入图片描述
现在,我们想回顾一下README.txt文件一共有几个版本被提交到Git仓库里了,那么版本控制系统的特点就出来了,我们可以方便地使用git log 命令来查看历史版本记录

git log命令显示从最近到最远的提交日志,我们清晰地可以看到3次提交,最近的一次是third commit,上一次是secondcommit,最早的一次是first second。

如果嫌输出信息太多,看得眼花缭乱的,可以试试加上–pretty=oneline参数:
在这里插入图片描述
前边一大串是commit id(版本号),它是一个SHA1计算出来的一个非常大的数字,用十六进制表示。为什么commit id需要用这么一大串数字表示呢?因为Git是分布式的版本控制系统,后面我们还要研究多人在同一个版本库里工作的场景,如果大家都用1,2,3……作为版本号,那肯定就会发生冲突


接下来我们利用Git的版本控制命令将README.txt回退到上一个版本,也就是second id的那个版本,怎么做呢?

首先,Git必须知道当前版本是哪个版本,在Git中,用HEAD表示当前版本,,上一个版本就是HEAD ^ ,上上一个版本就是HEAD ^ ^ ,当然往前n个版本可以写成HEAD~n

现在,我们要把当前版本回退到上一个版本,就可以使用git reset命令,reset的实现是修改HEAD的位置,即将HEAD指向的位置改变为之前存在的某个版本。并且这条命令会把工作区中所有未提交的内容清空

接下来我们用git log再看看版本库的更新日志:

最新的那个版本third commit已经看不到了,只要我们知道最新版本的commit id,就可以指定回到未来的某个版本:

Git的版本回退速度非常快,因为Git在内部有个指向当前版本的HEAD指针当你回退版本的时候,Git仅仅是把HEAD从指向了commit id指定的位置

如果没有保存新版本的commit id怎么办?Git提供了一个git reflog用来记录你的每一次重要操作:在这里插入图片描述


"版本回退"小结

  • HEAD指向的版本就是当前版本,因此,Git允许我们回溯到曾经的任何一个版本,使用命令git reset --hard commit_id

  • git log可以查看提交历史,以便确定要回到之前的哪个版本。

  • git reflog查看命令历史,以便确定要回到未来的哪个版本。


工作区、版本库和暂存区

工作区(Working Directory)
就是在本机里能看到的目录,比如之前创建的文件夹learnGit就是一个工作区

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

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

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

第一步是用git add把文件添加进去,实际上就是把文件修改添加到暂存区
第二步是用git commit提交更改,实际上就是把暂存区的所有内容提交到当前分支

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

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


接下来我们做一个简单的实践,向README.txt文件添加一行内容:

然后,在工作区新增一个LICENSE文本文件。

先用git status查看一下状态:
在这里插入图片描述
Git非常清楚地告诉我们,README.txt被修改了,而LICENSE还从来没有被添加过,所以它的状态是Untracked。

现在,使用两次git add命令,把README.txt和LICENSE都添加后,用git status再查看当前状态:
在这里插入图片描述
现在,暂存区的状态就变成这样了:
在这里插入图片描述
所以,git add命令实际上就是把要提交的所有修改放到暂存区(Stage),然后,执行git commit就可以一次性把暂存区的所有修改提交到分支。一旦提交后,如果你又没有对工作区做任何修改,那么工作区就是“干净”的:
在这里插入图片描述
现在版本库变成了这样,暂存区就没有任何内容了:
在这里插入图片描述
暂存区是Git非常重要的概念弄明白了暂存区,就弄明白了Git的很多操作d的实质。


管理修改

接下来我们要讨论的就是,为什么Git比其他版本控制系统设计得优秀,因为Git跟踪并管理的是修改,而非文件。

接下来我们通过一个实例再来理解一下。

首先我们继续给README.txt文件添加一行内容:

接着我们使用git add命令添加其到缓存区,使用git status来查看当前状态:

我们再次修改README.txt文件,添加一行内容,然后通过git commit命令提交到版本库中。

接着我们使用git status命令查看当前状态,我们发现只提交了一行内容,有一行内容没有被提交。

回顾一下操作过程:

第一次修改 -> git add -> 第二次修改 -> git commit

因为Git管理的是修改,当使用git add命令后,在工作区的第一次修改被放入暂存区,准备提交,但是,在工作区的第二次修改并没有放入暂存区,所以,git commit只负责把暂存区的修改提交了,也就是第一次的修改被提交了,第二次的修改不会被提交。

接下来我们使用 git diff HEAD – README.txt 命令可以查看工作区和版本库里面最新版本的区别

本地的文件是 +,即工作区的文件,我们可以看到我们的第二次修改的确没有被提交。

接下来我们将第二次的修改上传到暂存区,并提交给版本库:

然后我们再次使用 git diff HEAD – README.txt 命令查看一下工作区和版本库里面最新版本的区别

我们发现工作区和版本库里面的内容已经都是最新版本了。


"管理修改"小结

  • 注意Git跟踪并管理的是修改,而非文件
  • 每次修改,如果不用git add到暂存区,那就不会commit到版本库中

撤销修改

如果我们发现文件有错误,此时需要撤销修改操作,那么此刻有三种情形:

  • 文件没有被提交到暂存区
  • 文件已被提交到暂存区
  • 文件已从暂存区提交到本地版本库中

1、文件没有被提交到暂存区
既然错误发现得很及时,就可以很容易地纠正它。可以删掉最后一行,手动把文件恢复到上一个版本的状态。

如果用git status查看一下,我们会发现git的提示:git checkout – < file >可以丢弃工作区的修改
在这里插入图片描述
接下来我们使用 git checkout – README.txt 命令撤销工作区的修改,然后查看文件内容,发现的确我们的修改被撤销。

git checkout – file命令中的-- 很重要,没有 --,就变成了“切换到另一个分支”的命令,我们在后面的分支管理中会再次遇到git checkout命令。


2、文件被提交到暂存区
如果我们将修改通过git add命令添加到暂存区了,但是如果我们在commit到版本库之前,发现了这个问题。用git status查看一下,修改只是添加到了暂存区,还没有提交:

Git同样告诉我们,用命令git reset HEAD < file > 可以把暂存区的修改撤销掉(unstage),重新放回工作区,当我们用HEAD时,表示最新的版本。再用git status查看一下,现在暂存区是干净的,工作区有修改:

接下来我们使用 git checkout – README.txt 命令撤销工作区的修改,然后查看文件内容,发现的确修改被撤销。再用git status查看一下,发现工作区是干净的。

3、文件被提交到本地版本库
如果文件从暂存区提交到了版本库,那么我们可以使用版本回退方式,可以回退到上一个版本。不过,这是有条件的,就是还没有把自己的本地版本库推送到远程仓库


"撤销修改"小结

  • git reset命令既可以回退版本,也可以把暂存区的修改回退到工作区。
  • 命令git checkout – file可以直接丢弃工作区的修改,条件是文件还未提交到暂存区
  • 如果文件已被提交到暂存区向撤销修改,那么两步:用命令git reset HEAD < file >,将修改撤回工作区,第二步使用命令git checkout – file撤销工作区修改
  • 已经提交了不合适的修改到版本库时,想要撤销本次提交,使用版本回退的方式撤销修改,不过前提是没有推送到远程库。

删除文件

在Git中,删除也是一个修改操作,我们实战一下,先添加一个新文件test.txt到Git并且提交:

一般情况下,你通常直接在文件管理器中把没用的文件删了,或者用rm命令删了:

$ rm test.txt
这个时候,Git知道你删除了文件,因此,工作区和版本库就不一致了git status命令会立刻告诉你哪些文件被删除了:

$ git status
On branch master
Changes not staged for commit:
(use “git add/rm …” to update what will be committed)
(use “git checkout – …” to discard changes in working directory)

deleted:    test.txt

no changes added to commit (use “git add” and/or “git commit -a”)
现在你有两个选择:一是确实要从版本库中删除该文件,那么使用git rm,并且git commit可以从版本库中删除:

现在,文件就从版本库中被删除了。

另一种情况是删错了,因为版本库里并没有删除,所以我们可以通过git checkout --< file >很轻松地把误删的文件恢复到最新版本

$ git checkout – test.txt
git checkout其实是用版本库里的版本替换工作区的版本,无论工作区是修改还是删除,都可以“一键还原”。


"删除文件"小结

  • 命令git rm用于删除一个文件。
  • 如果一个文件已经被提交到版本库,那么永远不用担心误删,但是注意,只能恢复文件到最新版本,会丢失最近一次提交后所修改的内容。

在这里插入图片描述

  • 11
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ZY-JIMMY

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值