Git 知识点梳理

Posted by icoding168 on 2020-06-20 23:20:31

分类: 技术和工具  

Git 是什么

Git 是一个分布式版本控制系统。

Git 的历史

2002 年,Linux 系统已经发展了十年了,代码库之大让 Linux 的创始人 Linus 很难继续通过手工方式管理了,于是 Linus 选择了一个商业的版本控制系统 BitKeeper,BitKeeper 的公司BitMover 公司出于人道主义精神,授权 Linux 社区免费使用这个版本控制系统。

2005 年 Linux 团队的一员 Andrew 试图破解 BitKeeper 的协议,被 BitMover 公司发现了,于是 BitMover 公司怒了,要收回免费使用权。Linus 花了两周时间自己用 C 写了一个分布式版本控制系统,这就是 Git。

什么是版本控制系统

可以把一个版本控制系统理解为一个“数据库”,它可以完整地保存一个项目的历史版本。当你需要查看一个之前的版本时,版本控制系统可以显示出当前版本与上一个版本之间的所有改动的细节。

版本控制系统只能跟踪文本文件的改动,对于非文本文件比如 Word 文档、音频文件、视频文件等无法知道文件内容改动了什么。

如果你用 Windows 系统学习 Git,请用 Notepad++ 编辑器替代记事本,原因是微软开发记事本的团队使用了一个不合理的方法来保存 UTF-8 编码的文件,他们在每个文件开头添加了 0xefbbbf(十六进制)的字符,你会遇到很多不可思议的问题,比如明明正确的程序一编译就报语法错误,这些问题都是由 Windows 记事本带来的。

集中式和分布式的比较

集中式版本控制系统的版本库是集中存放在服务器的,比如 SVN,每个使用者都要先从服务器取得最新的版本,如果有新的版本也要推送给服务器。

分布式版本控制系统不需要服务器也能使用,比如 Git,因为每个人的电脑上都有一个完整的版本库,你在自己电脑上改了文件A,你的同事也在他的电脑上改了文件A,你们俩之间只需通过局域网把各自的修改推送给对方,就可以互相看到对方的修改了。

在实际使用分布式版本控制系统的时候,通常也有一台充当服务器的电脑,但这个服务器的作用仅仅是用来方便交换大家的修改,没有它大家也一样能协作,只是交换修改不方便而已。简单来说,Git在本机就能使用版本控制功能,而 SVN 必须有服务器。

安装 Git

Windows 和 Mac OS 都可以到 Git 的官网下载安装包 https://git-scm.com/

Linux 不同的发行版有一些不同,像 Ubuntu 安装 Git 就非常方便,一句 apt install git 命令就搞定。 

创建仓库

mkdir hello-git

cd hello-git

git init

执行完 git init 命令后,会在当前目录生成一个 .git 目录,这个目录是隐藏目录,用来存放 Git 跟踪管理版本库的数据,同时 Git 会自动创建一个 master 分支。

Git 分区

Git 本地数据管理,大概可以分为三个区:工作区,暂存区,版本库。

工作区(Working Directory)

工作区其实就是项目文件所在目录。

暂存区(Stage 或 Index)

数据暂时存放的区域,可在工作区和版本库之间进行数据交换,一般存放在 ".git目录下" 下的index文件(.git/index)中,所以我们把暂存区有时也叫作索引(index)。

版本库(Commit History)

存放已经提交的数据,push 的时候,就是把这个区的数据 push 到远程仓库了。

Git 常用命令

首先在 hello-git 目录下编写一个 readme.txt 文件,文件内容随便。

添加文件

执行 git add 命令将文件从工作区加入到暂存区:

git add readme.txt

git add 是一个容易引起混淆的命令。SVN 的 svn add 命令是将某个文件加入版本控制,而 git add 是把工作区中的文件复制到暂存区。在 git 的后续版本中就做了修改,git stage 作为 git add 的一个同义词。

git add 提供了对要提交的内容进行控制的能力,把你修改了的并且想提交的文件和你修改了的但不想提交的文件区分开来。

提交文件

执行 git commit 命令将文件从暂存区加入到版本库:

git commit -m “测试”

参数 m后面是关于本次 commit 的说明,不可忽略。

修改和删除

在 Git 中,修改和删除都跟新增文件一样也要使用 git add 命令来添加要 commit 的文件。

仓库状态

通过执行 git status 命令可以查看当前仓库的状态,比如说有哪些文件没有被跟踪管理,哪些文件有改动。

查看分支

git branch

这个命令可以列出所有分支,分支前带星号的就是当前分支。

创建分支

git branch dev

切换分支

git checkout dev

创建并切换分支

git checkout -b dev

合并分支

合并 dev分支到 master分支:

git checkout master

git merge dev

合并分支的时候要确保两个分支的代码都是最新的,而且假如你在某个分支上有改动,只要把改动都 commit 就行了,不需要 push 到远程分支。

删除分支

git branch -d dev 

分支使用原则

master 分支应该仅用来发布新版本,平时不能在 master 上写代码。写代码都在 dev 分支上,新版本发布时再把 dev 分支合并到 master 上。

每个人都在 dev 分支上干活,每个人也都可以有自己的分支,及时合并到 dev 分支上就可以了。修复 bug 也可以新开一条分支,等测试通过后再合并到 master 分支。

切换分支前,如果你改动了很多文件,但是又不想提交,可以使用 git stash 命令将所有暂存区和工作区的改动保存起来,后续可以通过命令恢复数据,git stash 有时候也可以避免切换分支时的代码冲突。

版本回退

回退到最新版本

git reset --hard HEAD 命令可以将现场还原到当前分支在版本库中的最新版本。  

在 Git 中,用 HEAD 表示当前版本,上一个版本就是 HEAD^ ,上上一个版本就是 HEAD^^ ,版本太多的话可以用数字代替,比如回退 10 个版本就写 HEAD~10。

如果要回退到某个特定的版本,可以用 commit id,比如 git reset –hard ea34578d5,通过 git log 命令可以知道 commit id。

git reset hard/mixed/soft的区别

--soft 、--mixed 以及 --hard 是三个恢复等级,使用 --soft 就仅仅将头指针恢复,已经add到暂存区以及工作区的所有东西都不变。

如果使用 --mixed,就将头指针恢复,已经 add 到暂存区的也会丢失掉,工作区的是不变的。

如果使用 --hard,那么头指针、暂存区、工作区都会全部恢复。

git revert 和 git reset 的区别

git revert 是用一次新的 commit 来恢复旧版本的数据,它不会影响已存在的 commit 历史记录,git reset 会删除指定的 commit id 之后的历史记录。

如果要推送到远程分支,git revert 跟普通的 commit 没有区别,但执行 git reset 之后,因为远程分支依然还是旧的 commit id,所以需要在推送时加 -f 参数强制推送:git push -f

部分提交

修改了多个文件,在不放弃任何修改的情况下,其中有一些文件不想提交,如何操作?

分两种情况:

  • 还没执行过 git add 的情况下,对将要提交的文件执行 git add 命令即可
  • 这些文件已经被执行了 git add 命令的情况下,执行 git reset --soft 将文件从暂存区回滚到工作区,重新执行 git add 命令

放弃修改

修改到一半的文件,突然间不需要或者放弃修改了,怎么恢复未修改前文件?

假如文件名是 readme.txt,那么执行 git checkout readme.txt 即可恢复文件。

忘记切换分支

代码改完了才发现用错分支了,怎么把代码移动到正确的分支 ?

如果还没有 commit 过代码

git stash

git checkout targetbranch 

git stash pop

git add .

git commit -m xxx

第一步,将修改的代码暂存到stash,第二步,切换到正确的分支,第三步,从stash中取出暂存的代码修改,后续的大家都懂的。

如果已经 commit 过代码

git checkout targetbranch

git merge master         

git checkout master

git reset --keep HEAD~3 (这里的 3 是指回退版本号,依照实际情况而定)

或者使用 cherry pick ,将代码提取到目标分支,原有分支再执行 git reset 操作。

远程仓库

Git 支持 SSH、Http 等网络协议来传输数据,大家平时用的挺多的了,此处不再多说。