Git 是一个分布式版本控制系统,基于分布式技术实现用户对软件版本的管理控制。
版本控制其实就是管理一个软件项目的多个版本。
要管理版本,必须跟踪对项目中文件的每次更改(添加、编辑或删除)。因此,版本控制的草操作内容,就是记录对项目中文件(或一组文件)所做的每次更改,并提供撤消或回滚每个更改的方法。
使用版本控制的最重要优势之一是利于团队合作。当不止一个人在为一个项目做出贡献时,跟踪文件的变更就变成了一场噩梦,所以程序开发人员急需一个版本控制系统。
版本控制系统(Version Control Systems)有很多种,每种 CVS 都有自己的优点和缺点。
为了将程序员从”用复制整个项目目录的方式来保存不同的版本“这一容易犯错的操作中解脱出来,本地式版本控制系统(Local Version Control Systems)应运而生。
大多数 LCVS 采用某种简单的数据库来记录文件的历次更新差异,它们通过跟踪对本地存储的这个数据库中的文件所做的更改来实现版本控制,这实现起来非常简单。
由于 LVCS 的所有更改都保存在一台某平台下的计算机的某个数据库中,如果这个数据库出现问题,那么将丢失所有工作。最主要的是它们一次只能处理一个文件,没有办法跟踪整个项目。总之,就意味着团队合作是不可能的。
因此,为了实现协同工作,集中式版本控制系统(Centralized Version Control Systems)诞生。
CVCS 的工作原理是将文件更改的历史记录存储在客户端(作者)可以连接到的单个服务器上,从而实现与团队合作。这种方式让查看整体项目进度与基于权限的角色管理工作更加方便。
CVCS 的问题问题与 LVCS 的一样,服务器错误可能会使团队付出全部工作的代价。而且由于主项目存储在远程服务器中,导致团队协同工作需要网络连接支持。
分布式版本控制系统(Distributed Version Control Systems)面世了。它的工作方式与 CVCS 很大的不同在于:没有用于保存所有历史记录的主服务器,每个客户端都有一个项目的克隆(及其更改的历史记录)而不必一直连接到主服务器;它不会跟踪版本之间的变更,而是将所有变更作为“补丁”进行跟踪。
这种分布式特点大大降低了丢失所有内容的可能性,而且进一步激活了”分支“这一概念,分支使得开发人员能基于这些自由交换的”补丁“进行开发。
在2005年, 放弃使用 BitKeeper SCM 作为 Linux 内核开发的版本控制系统,转而开发自己的 DVCS ,不久之后,Git 诞生了!
相对于当时的其它 DVCS ,Git 速度更快、设计更简洁、对非线性开发模式的支持更好、性能更强大,且是完全分布式的。
为了更方便使用 Git,在2007年,GitHub 出现了,它是一个易于使用的网站:"The hosting of github is excellent"
Bitkeeper plays spoil-sport. Linux looking for a new SCM
10 Years of Git: An Interview with Git Creator Linus Torvalds
Git Features
上面提到的那些特点都太抽象了,Git到底能干什么呢?没什么,它只是
很擅长追踪变更而已。基于这点,它能:
总之,这种对文件变更过程进行存储与追溯的能力使得 Git 能很好地完成版本控制任务。
与许多版本控制系统不同的是,Git 不会跟踪文件的两个版本之间的差异,而是通过操作项目随时间改变的快照来实现变更过程的存储与追溯,进而实现版本控制。所以说,Git 将数据当作一个快照流来对待。
尽管以分布式实现的 Git 可以说是没有”主服务器“这一概念,但为了更好地进行团队间的协同开发,开发人员约定:在本地进行本人需要负责的功能开发或者问题修复,待一切处理完成后,将本地的变更与主项目合并。
这里就来关注本地开发中文件状态的变更及其所处的环境。
Git 中本地文件只能处于以下三种状态之一:
Git 中本地文件只能处于以下三种环境之一:
.git/
的目录。可以在其中编辑项目文件。.git/index
文件,执行”添加修改到暂存区“添加的就是项目当前的快照.git/
,其中保存了所有提交的结果,也就是项目的一系列快照信息。简单来说,这六者间的关系是这样的:
至于团队间如何协同开发,也放到后面来说:
为了更好地掌握 Git,后面会在主要讲 Git 命令的使用的时候,穿插 Git 底层原理的介绍。
接下来,我们将在 Ubuntu 20.10 中使用一些简单的命令来进行演示:在本地编辑项目,并推送到远程仓库,命令更完整的解释放到后面来说。
dang@DFLubuntu:~/HelloGit$ git --version # 查看版本
git version 2.27.0
sudo apt install git
进行安装,安装完成后还需要配置SSH Key。dang@DFLubuntu:~$ mkdir git-tutorial
dang@DFLubuntu:~$ cd git-tutorial
dang@DFLubuntu:~/git-tutorial$ ls -al
总用量 8
drwxrwxr-x 2 dang dang 4096 11月 14 02:00 .
drwxr-xr-x 20 dang dang 4096 11月 14 02:00 ..
dang@DFLubuntu:~/git-tutorial$
dang@DFLubuntu:~/git-tutorial$ git init
已初始化空的 Git 仓库于 /home/dang/git-tutorial/.git/
dang@DFLubuntu:~/git-tutorial$ ls -al
总用量 12
drwxrwxr-x 3 dang dang 4096 11月 14 02:01 .
drwxr-xr-x 20 dang dang 4096 11月 14 02:00 ..
drwxrwxr-x 7 dang dang 4096 11月 14 02:01 .git
dang@DFLubuntu:~/git-tutorial$ tree .git
.git
├── branches
├── config
├── description
├── HEAD
├── hooks
│ ├── applypatch-msg.sample
│ ├── commit-msg.sample
│ ├── fsmonitor-watchman.sample
│ ├── post-update.sample
│ ├── pre-applypatch.sample
│ ├── pre-commit.sample
│ ├── pre-merge-commit.sample
│ ├── prepare-commit-msg.sample
│ ├── pre-push.sample
│ ├── pre-rebase.sample
│ ├── pre-receive.sample
│ └── update.sample
├── info
│ └── exclude
├── objects
│ ├── info
│ └── pack
└── refs
├── heads
└── tags
9 directories, 16 files
init
初始化 Git 本地仓库。.git/
就是 Git 本地仓库,它所在的目录就是工作目录。.git/index
文件。dang@DFLubuntu:~/git-tutorial$ git status
位于分支 master
尚无提交
无文件要提交(创建/拷贝文件并使用 "git add" 建立跟踪)
dang@DFLubuntu:~/git-tutorial$ touch README.md
dang@DFLubuntu:~/git-tutorial$ git status
位于分支 master
尚无提交
未跟踪的文件:
(使用 "git add <文件>..." 以包含要提交的内容)
README.md
提交为空,但是存在尚未跟踪的文件(使用 "git add" 建立跟踪)
dang@DFLubuntu:~/git-tutorial$
status
,表明工作目录和暂存区暂时没有东西。status
,”未跟踪的文件“表明工作目录已经存在README.md文件,但还没添加到暂存区。dang@DFLubuntu:~/git-tutorial$ git add README.md
dang@DFLubuntu:~/git-tutorial$ git status
位于分支 master
尚无提交
要提交的变更:
(使用 "git rm --cached <文件>..." 以取消暂存)
新文件: README.md
dang@DFLubuntu:~/git-tutorial$
add
将工作目录中发生变更的README.md文件添加到暂存区。dang@DFLubuntu:~/git-tutorial$ git commit -m "First commit"
[master (根提交) c1fb4b1] First commit
1 file changed, 0 insertions(+), 0 deletions(-)
create mode 100644 README.md
dang@DFLubuntu:~/git-tutorial$ tree .git
.git
├── branches
├── COMMIT_EDITMSG
├── config
├── description
├── HEAD
├── hooks
│ ├── applypatch-msg.sample
│ ├── commit-msg.sample
│ ├── fsmonitor-watchman.sample
│ ├── post-update.sample
│ ├── pre-applypatch.sample
│ ├── pre-commit.sample
│ ├── pre-merge-commit.sample
│ ├── prepare-commit-msg.sample
│ ├── pre-push.sample
│ ├── pre-rebase.sample
│ ├── pre-receive.sample
│ └── update.sample
├── index
├── info
│ └── exclude
├── logs
│ ├── HEAD
│ └── refs
│ └── heads
│ └── master
├── objects
│ ├── c1
│ │ └── fb4b1d4dcee979818df7fb9e7589ad9bc6a46b
│ ├── e6
│ │ └── 9de29bb2d1d6434b8b29ae775ad8c2e48c5391
│ ├── f9
│ │ └── 3e3a1a1525fb5b91020da86e44810c87a2d7bc
│ ├── info
│ └── pack
└── refs
├── heads
│ └── master
└── tags
15 directories, 24 files
dang@DFLubuntu:~/git-tutorial$ git status
位于分支 master
无文件要提交,干净的工作区
dang@DFLubuntu:~/git-tutorial$
dang@DFLubuntu:~/git-tutorial$ git log
commit c1fb4b1d4dcee979818df7fb9e7589ad9bc6a46b (HEAD -> master)
Author: Your Name <[email protected]>
Date: Sun Nov 14 02:20:12 2021 +0800
First commit
dang@DFLubuntu:~/git-tutorial$
先在 GitHub 中手动创建项目远程仓库。
dang@DFLubuntu:~/git-tutorial$ git remote add origin your_remote_repository_address
dang@DFLubuntu:~/git-tutorial$ git branch -M master
dang@DFLubuntu:~/git-tutorial$ git push -u origin master
枚举对象: 3, 完成.
对象计数中: 100% (3/3), 完成.
写入对象中: 100% (3/3), 211 字节 | 211.00 KiB/s, 完成.
总共 3(差异 0),复用 0(差异 0),包复用 0
To github.com:xiaolu2333/git-tutorial.git
* [new branch] master -> master
分支 'master' 设置为跟踪来自 'origin' 的远程分支 'master'。
git-recipes