上期漫谈版本控制系统中我们谈到了版本控制系统的四个演进过程,即悲观锁版本 -> 乐观锁版本 -> 多分支版本 -> 分布式版本,目前我们使用最多的是分布式版本,本期我们就来介绍下分布式版本控制系统的具体实现Git和GitHub。
Git不用于其他版本控制系统主要体现在以下几点:1. Git对待数据的方法,直接记录快照,而非差异比较;2. 暂存区;3.高效的分支模型。
File A
在version2发生了修改,因此全量存储文件信息,而在version3并没有修改,因此保留一个链接指向A1。git commit
进行提交操作时,会计算每一个子目录的校验和,然后在Git仓库中将这些校验和保存为树对象,随后,Git便会创建一个提交对象,它除了包含上面提到的那些信息外,还包含指向这个树对象的指针。如下图所示,现在Git仓库包含五个对象:三个blob对象(保存着文件快照)、一个树对象(记录着目录结构和blob对象索引)以及一个提交对象。choco install git
,也可以通过普通安装完成brew install git
yum install git
git --version
用户信息 当安装完Git之后应该做的第一件事就是设置你的用户名称和邮件地址,这样做很重要,因为每一次Git提交都会使用这些信息。
git config --global user.name "mukedada"
git config --global user.email mukedada@126.com
注意--global
选项表示全局设置。
检查配置信息
通过git config --list
命令列出所有Git当前能找到的配置,还可以通过git config <key>
来检查某一项配置,例如:git config user.name
,结果:
$ git config user.name
mukedada
目前有两种方式获取Git项目仓库的方法。第一种方法是把现有目录下的所有文件导入到Git中;第二种方法是一个服务器克隆一个现有的Git仓库。 在现有目录中初始化仓库
$ cd test
$ git init
在test目录下创建一个名为.git
的子目录。
克隆现有的仓库
克隆仓库的命令格式是git clone [url]
。比如,要克隆木可大大的code仓库,可以用下面的命令:
$ git clone git@github.com:mukedada/code.git
这回在当前目录下创建一个名为"code"的目录,并在这个目录下初始化一个.git
文件夹。
test目录下的每个文件都不外乎两个状态:已跟踪或未跟踪。已跟踪的文件是指那些被纳入了版本控制的文件,在上一次快照中有它们的记录,在工作一段时间后,它们的状态可能处于未修改或已修改或一放入暂存区。test目录下除了已跟踪的文件以外,剩下的文件都属于未跟踪的文件,它们既不存在于上次快照的记录中,也没有放入暂存区。初次克隆的test仓库,此时该工作目录中的所有文件都属于已跟踪文件,并处于未修改状态。编辑过某些文件之后,由于自上次提交后我们对它们做了修改,Git将它们标记为已修改文件。我们逐步将这些修改过的文件放入暂存区,然后提交所有暂存区中的修改,如此反复。
使用git status
名称查看当前文件处于什么状态。
$ git status
On branch master
Your branch is up to date with 'origin/master'.
nothing to commit, working tree clean
nothing to commit,working tree clean
说明当前工作目录中所有已跟踪的文件在上次提交之后没有修改过;On branch master
说明当前处于master
分支。
现在,我们在test项目下创建text.txt文件,再使用git status
命令。
$ echo 'my project' > test.txt
$ git status
On branch master
Your branch is up to date with 'origin/master'.
Untracked files:
(use "git add <file>..." to include in what will be committed)
test.txt
nothing added to commit but untracked files present (use "git add" to track)
从中我们可以发现,test.txt在Untracked files
下面,这就意味着该文件并未在之前的快照中,如果我们想让该文件纳入到Git的跟踪范围内,需要使用git add
命令。
git add + 文件或目录
,如果是目录,则将递归跟踪该目录下所有的文件。
$ git add test.txt
$ git status
On branch master
Your branch is up to date with 'origin/master'.
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
new file: test.txt
只要出现Changes to be committed
说明test.txt已经进入暂存区。
现在我们修改test.txt,发现该文件既出现在Changes to be committed
下面,又出现在Changes not staged for commit
下面,前一句说明该文件在暂存区,而后一句说明该文件在非暂存区,这怎么可能呢?其实,文件在暂存区是因为暂存区保存的是我们上一次运行git add
命令时的版本,接着我们没有运行git commit
命令,而是对文件进行修改,所以出现了Changes not staged for commit
,因此,我们需要对修改后的文件重新运行git add
命令把最新版本重新暂存起来。
$ vim test.txt
$ git status
On branch master
Your branch is up to date with 'origin/master'.
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
new file: test.txt
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git checkout -- <file>..." to discard changes in working directory)
modified: test.txt
通过上面代码我们知道我们对已暂存的test.txt进行了修改,还没有执行git add
命令,但是我们不知道具体修改了什么内容,此时,我们就可以用git diff
命令来查看修改的内容。
$ git diff
diff --git a/test.txt b/test.txt
index a159320..b3b1c1b 100644
--- a/test.txt
+++ b/test.txt
@@ -1 +1,2 @@
hello 'my project'
+haha~
使用 git commit -m "备注"
命令提交存放在暂存区的快照,-m
选项表示提交时备注信息。
git commit
加上-a
选项表示跳过git add
步骤直接将文件保存到暂存区。
git tag
命令:$ git tag
v0.1
$ git tag -a v1.0 -m 'my version 1.0'
$ git tag
v0.1
v1.0
Git分支,本质上就是指向提交对象的可变指针。每当提交一次,都会生成一个新的提交对象,它包含一个指向上次提交对象的指针,如下图所示。
分支创建
通过使用git branch
命令创建分支,譬如:
$ git branch testing
当有两个指向相同提交历史的分支,Git怎么知道当前在哪一个分支上呢?Git有一个特殊指针HEAD
,它指向当前所在的本地分支。
分支切换
通过使用git checkout
命令进行分支切换,譬如:我们切换到新创建的testing分支上:
$ git checkout testing
此时,HEAD就指向testing
分支。
分支合并
目前Git分支合并主要有两种方法:merge
和 rebase
。
hotfix branch
合并到master
分支上,由于当前master
分支所指向的提交是hotfix
分支的之间上游,因此Git知识简单的将指针向前移动,这就是快进(fast-forward)。$ git checkout master
$ git merge hotfix
Updating f42c576..3a0874c
Fast-forward
index.html | 2 ++
1 file changed, 2 insertions(+)
由于master
分支和hotfix
分支指向同一个位置,我们可以使用git branch -d
指令删除分支:
$ git branch -d hotfix
接下来,我们继续在iss53
工作,最后一个提交对象是C5
,此时,如何合并iss53
分支和C5
分支?
我们需要将HEAD
指向master
,然后执行git merge
命令:
$ git checkout master
Switched to branch 'master'
$ git merge iss53
Merge made by the 'recursive' strategy.
index.html | 1 +
1 file changed, 1 insertion(+)
这和之前合并hotfix
分支看起来有些不同,Git会使用两个分支的末端所指的快照(C4
和C5
)以及这两个分支的工作祖先(C2
),做一个简单的三方合并。
C4
分支和C3
分支进行合并,首先提取C4
的修改,然后在C3
上重新播放一遍。
$ git checkout experiment
$ git rebase master
First, rewinding head to replay your work on top of it...
Applying: added staged command
执行完上述代码之后,形成如下结构。
对于上述结构,我们还需要进行一次合并。
$ git checkout master
$ git merge experiment
目前,GitHub是最大的Git版本库托管商,大部分开源项目都托管在Github,因此学习Github就比不可少了。
ssh-keygen -t rsa -C "mukedada@126.com"
生成主机的公私密钥对,如果是Mac,则使用ssh-keygen
命令上。注意:运行上述指令时,不要输入任何信息,只需按enter就可以,成功之后,公私钥文件会存放于当前用户目录的.ssh目录下,例如C:\Users\kwy\.ssh
。接着,将生成出的公钥放到github中。
git clone git@github.com:mukedada/artical.git
欢迎关注微信公众号:木可大大,所有文章都将同步在公众号上。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。