目录
一、git简介
1.1 历史
git是目前世界上最先进的分布式版本控制系统。
Linus在1991年创建了开源的Linux,从此,Linux系统不断发展,已经成为最大的服务器系统软件了。Linus虽然创建了Linux,但Linux的壮大是靠全世界热心的志愿者参与的,这么多人在世界各地为Linux编写代码,那Linux的代码是如何管理的呢?事实是,在2002年以前,世界各地的志愿者把源代码文件通过diff的方式发给Linus,然后由Linus本人通过手工方式合并代码!你也许会想,为什么Linus不把Linux代码放到版本控制系统里呢?不是有CVS、SVN这些免费的版本控制系统吗?因为Linus坚定地反对CVS和SVN,这些集中式的版本控制系统不但速度慢,而且必须联网才能使用。有一些商用的版本控制系统,虽然比CVS、SVN好用,但那是付费的,和Linux的开源精神不符。不过,到了2002年,Linux系统已经发展了十年了,代码库之大让Linus很难继续通过手工方式管理了,社区的弟兄们也对这种方式表达了强烈不满,于是Linus选择了一个商业的版本控制系统BitKeeper,BitKeeper的东家BitMover公司出于人道主义精神,授权Linux社区免费使用这个版本控制系统。安定团结的大好局面在2005年就被打破了,原因是Linux社区牛人聚集,不免沾染了一些梁山好汉的江湖习气。开发Samba的Andrew试图破解BitKeeper的协议(这么干的其实也不只他一个),被BitMover公司发现了(监控工作做得不错!),于是BitMover公司怒了,要收回Linux社区的免费使用权。Linus可以向BitMover公司道个歉,保证以后严格管教弟兄们,嗯,这是不可能的。实际情况是这样的:Linus花了两周时间自己用C写了一个分布式版本控制系统,这就是Git!一个月之内,Linux系统的源码已经由Git管理了!牛是怎么定义的呢?大家可以体会一下。Git迅速成为最流行的分布式版本控制系统,尤其是2008年,GitHub网站上线了,它为开源项目免费提供Git存储,无数开源项目开始迁移至GitHub,包括jQuery,PHP,Ruby等等。历史就是这么偶然,如果不是当年BitMover公司威胁Linux社区,可能现在我们就没有免费而超级好用的Git了。
1.2 特点
- 版本控制:可以解决多人同时开发的代码问题,也可以解决找回历史代码的问题。
- 分布式:Git是分布式版本控制系统,同一个Git仓库,可以分布到不同的机器上。首先找一台电脑充当服务器的角色,每天24小时开机,其他每个人都从这个“服务器”仓库克隆一份到自己的电脑上,并且各自把各自的提交推送到服务器仓库里,也从服务器仓库中拉取别人的提交。可以自己搭建这台服务器,也可以使用GitHub网站。
二、安装与配置并创建一个版本库
2.1 安装配置
windows:Git,在windows环境也包含有linux界面的操作,这里主要在ubuntu上进行操作,安装命令如下
sudo apt-get install git
安装完成后执行git会出现以下界面说明安装成功
2.2 创建一个版本库
新建一个目录git_test,在此目录下创建一个版本库:git init
xm@ubuntu:~/xm-git$ mkdir git_test
xm@ubuntu:~/xm-git$ cd git_test/
xm@ubuntu:~/xm-git/git_test$ ls -al
total 8
drwxr-xr-x 2 xm xm 4096 Apr 6 04:54 .
drwxr-xr-x 3 xm xm 4096 Apr 6 04:54 ..
xm@ubuntu:~/xm-git/git_test$ git init
Initialized empty Git repository in /home/xm/xm-git/git_test/.git/
xm@ubuntu:~/xm-git/git_test$ la -al
total 12
drwxr-xr-x 3 xm xm 4096 Apr 6 04:54 .
drwxr-xr-x 3 xm xm 4096 Apr 6 04:54 ..
drwxr-xr-x 7 xm xm 4096 Apr 6 04:54 .git
三、版本的创建与回退
3.1 创建一个版本
3.1.1 git add与git commit命令
新建一个文件code,并添加一些内容,执行git add code.txt和git commit -m 'verson 1',-m这个指令可以添加版本注释,这两个命令在后面工作区和暂存区解释,当执行到git commit的时候,提示我们需要认证一下用户名和邮箱
xm@ubuntu:~/xm-git/git_test$ vi code.txt
xm@ubuntu:~/xm-git/git_test$ cat code.txt
this is the first line
xm@ubuntu:~/xm-git/git_test$ git add code.txt
xm@ubuntu:~/xm-git/git_test$ git commit -m 'verson 1'
*** Please tell me who you are.
Run
git config --global user.email "you@example.com"
git config --global user.name "Your Name"
to set your account's default identity.
Omit --global to set the identity only in this repository.
fatal: unable to auto-detect email address (got 'xm@ubuntu.(none)')
3.1.2 认证
根据提示我们输入我们的邮箱和用户名,然后再次执行git commit -m 'verson 1',这里注释版本一
xm@ubuntu:~/xm-git/git_test$ git config --global user.email "1006962425@qq.com"
xm@ubuntu:~/xm-git/git_test$ git config --global user.name "Xiaoma"
xm@ubuntu:~/xm-git/git_test$ git commit -m 'verson 1'
[master (root-commit) 2522dc5] verson 1
1 file changed, 1 insertion(+)
create mode 100644 code.txt
3.1.3 git log命令
执行git log命令,可以查看版本记录
commit 2522dc5642ded17edaeca49f4c31b46c6d65cca5 (HEAD -> master)
Author: Xiaoma <1006962425@qq.com>
Date: Tue Apr 6 05:04:15 2021 -0700
verson 1
继续编辑code.txt,在里面再增加一行,再次执行git add和git commit可以看到我们的版本2,这时的版本2与版本1的差别只是添加了一行,这并不意味着版本2是完整的一份代码,版本2只不过是添加了暂存区修改的部分(暂存区在后面解释),需要依赖于前一个版本
xm@ubuntu:~/xm-git/git_test$ cat code.txt
this is the first line
this is the second line
xm@ubuntu:~/xm-git/git_test$ git add code.txt
xm@ubuntu:~/xm-git/git_test$ git commit -m 'verson 2'
[master 399f3d2] verson 2
1 file changed, 1 insertion(+)
xm@ubuntu:~/xm-git/git_test$ git log
commit 399f3d2c26af9e11434460b3a71403f56d1e6bf7 (HEAD -> master)
Author: Xiaoma <1006962425@qq.com>
Date: Tue Apr 6 05:10:51 2021 -0700
verson 2
commit 2522dc5642ded17edaeca49f4c31b46c6d65cca5
Author: Xiaoma <1006962425@qq.com>
Date: Tue Apr 6 05:04:15 2021 -0700
verson 1
执行git log --help可以看到指令的用法,当我们的版本很多,可以缩简信息来显示,执行git log --pretty=oneline
xm@ubuntu:~/xm-git/git_test$ git log --pretty=onelin
399f3d2c26af9e11434460b3a71403f56d1e6bf7 verson 2
2522dc5642ded17edaeca49f4c31b46c6d65cca5 verson 1
3.2 版本指针HEAD
HEAD会先指向master主支路,支路参考Git学习笔记(二),再指向最新版本,那么前一个版本的表示方式HEAD^,前前个版本的表示方式HEAD^^,如果我们想找到前100个版本的时候是不是要加100个^呢,可以用HEAD~100来表示当前版本的前100个版本
3.2.1 git reset命令
如果当前版本想要回到之前的版本一的话,执行git reset --hard HEAD^,再次执行git log就可以看到当前版本就是上一个版本了,这里是不是意味着第二个版本就消失了呢,其实不是这样的,版本2依然存在
xm@ubuntu:~/xm-git/git_test$ git reset --hard HEAD^
HEAD is now at 2522dc5 verson 1
xm@ubuntu:~/xm-git/git_test$ git log
commit 2522dc5642ded17edaeca49f4c31b46c6d65cca5 (HEAD -> master)
Author: Xiaoma <1006962425@qq.com>
Date: Tue Apr 6 05:04:15 2021 -0700
verson 1
如果我们想要将当前版本设置为之前的版本2怎么办,从上面我们可以知道每个版本的版本编号,版本2的版本编号为399f3d2c26af9e11434460b3a71403f56d1e6bf7,执行git reset --hard+版本编号如下所示,编号不需要整条复制,复制前面一段就可以实现了,这叫版本的回退,可以看到我们的版本2又回来了
xm@ubuntu:~/xm-git/git_test$ git reset --hard 399f3d2c2
HEAD is now at 399f3d2 verson 2
xm@ubuntu:~/xm-git/git_test$ git log
commit 399f3d2c26af9e11434460b3a71403f56d1e6bf7 (HEAD -> master)
Author: Xiaoma <1006962425@qq.com>
Date: Tue Apr 6 05:10:51 2021 -0700
verson 2
commit 2522dc5642ded17edaeca49f4c31b46c6d65cca5
Author: Xiaoma <1006962425@qq.com>
Date: Tue Apr 6 05:04:15 2021 -0700
verson 1
xm@ubuntu:~/xm-git/git_test$ cat code.txt
this is the first line
this is the second line
3.2.2 git reflog命令
假设我们的终端关闭了不知道之前的版本编号,再次将当前版本指向版本1,这个时候想回到之前的版本2但是又不知道版本2的编号,执行git reflog命令可以查看之前我们的操作记录,这时可以看到前面就是版本2的编号399f3d2
xm@ubuntu:~/xm-git/git_test$ git log
commit 2522dc5642ded17edaeca49f4c31b46c6d65cca5 (HEAD -> master)
Author: Xiaoma <1006962425@qq.com>
Date: Tue Apr 6 05:04:15 2021 -0700
verson 1
xm@ubuntu:~/xm-git/git_test$ git reflog
2522dc5 (HEAD -> master) HEAD@{0}: reset: moving to HEAD^
399f3d2 HEAD@{1}: reset: moving to 399f3d2c2
2522dc5 (HEAD -> master) HEAD@{2}: reset: moving to HEAD^
399f3d2 HEAD@{3}: commit: verson 2
2522dc5 (HEAD -> master) HEAD@{4}: commit (initial): verson 1
3.3 工作区和暂存区
- 工作区:电脑中的目录,比如我们此时的git_test就是一个工作区
- 版本库:工作区有一个隐藏目录.git,这个不是工作区,而是git的版本库
git的版本库里存了很多东西,其中最重要的就是称为stage(或者叫index)的暂存区,还有git为我们自动创建的第一个分支master,以及指向master的一个指针叫HEAD,因为我们创建git版本库时,git自动为我们创建了唯一一个master分支,所以,现在,git commit就是往master分支上提交更改。你可以简单理解为,需要提交的文件修改通通放到暂存区,然后,一次性提交暂存区的所有修改。
前面讲了我们把文件往git版本库里添加的时候,是分两步执行的:
- 第一步是用git add把文件添加进去,实际上就是把文件修改添加到暂存区,文件修改多次可以进行多次git add,再进行一次git commit版本记录
- 第二步是用git commit提交更改,实际上就是把暂存区的所有内容提交到当前分支
git status命令
在git_test目录下再创建一个文件code2.txt增加一行,同时在code.txt中再次增加一行,执行git status可以查看当前工作树的状态,提示code.txt为修改的状态,而code2.txt为未跟踪的状态
xm@ubuntu:~/xm-git/git_test$ vi code.txt
xm@ubuntu:~/xm-git/git_test$ cat code.txt
this is the first line
this is the second line
this is the third line
xm@ubuntu:~/xm-git/git_test$ cat code2.txt
the code2 first line
xm@ubuntu:~/xm-git/git_test$ git status
On branch master
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: code.txt
Untracked files:
(use "git add <file>..." to include in what will be committed)
code2.txt
no changes added to commit (use "git add" and/or "git commit -a")
把code.txt和code2.txt加入暂存区中,然后再执行git status命令,git add命令就是把所有提交的修改存放到暂存区中,然后执行git commit就可以一次性把暂存区的所有修改提交到分支,一旦提交后如果没有对工作区做任何修改,那么工作区就是干净的
xm@ubuntu:~/xm-git/git_test$ git add code.txt code2.txt
xm@ubuntu:~/xm-git/git_test$ git status
On branch master
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
modified: code.txt
new file: code2.txt
xm@ubuntu:~/xm-git/git_test$ git commit -m 'verson 3'
[master 8598432] verson 3
2 files changed, 2 insertions(+)
create mode 100644 code2.txt
xm@ubuntu:~/xm-git/git_test$ git log
commit 85984321ceebb6b56fb336d11c3b287e966072d2 (HEAD -> master)
Author: Xiaoma <1006962425@qq.com>
Date: Tue Apr 6 05:57:27 2021 -0700
verson 3
commit 399f3d2c26af9e11434460b3a71403f56d1e6bf7
Author: Xiaoma <1006962425@qq.com>
Date: Tue Apr 6 05:10:51 2021 -0700
verson 2
commit 2522dc5642ded17edaeca49f4c31b46c6d65cca5
Author: Xiaoma <1006962425@qq.com>
Date: Tue Apr 6 05:04:15 2021 -0700
verson 1
此时我们的版本如下所示
3.4 管理修改
编辑code.txt,并使用git add命令添加到暂存区中,git commit创建一个版本,并使用git status查看,发现第二次修改code.txt内容之后,并没有将其添加的工作区,所以创建版本的时候并没有被提交,版本4依然只是对暂存区的修改内容进行创建
xm@ubuntu:~/xm-git/git_test$ cat code.txt
this is the first line
this is the second line
this is the third line
this is the forth line
xm@ubuntu:~/xm-git/git_test$ git add code.txt
xm@ubuntu:~/xm-git/git_test$ vi code.txt
xm@ubuntu:~/xm-git/git_test$ cat code.txt
this is the first line
this is the second line
this is the third line
this is the forth line
this is the new line
xm@ubuntu:~/xm-git/git_test$ git commit -m 'verson 4'
[master 7dfafe0] verson 4
1 file changed, 1 insertion(+)
xm@ubuntu:~/xm-git/git_test$ git status
On branch master
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: code.txt
no changes added to commit (use "git add" and/or "git commit -a")
3.4.1 git checkout命令
对上面的操作,提示我们可以使用 git checkout -- <文件> 来丢弃工作区的改动。执行如下命令,发现工作区干净了,第二次的改动内容也没了
xm@ubuntu:~/xm-git/git_test$ git checkout -- code.txt
xm@ubuntu:~/xm-git/git_test$ cat code.txt
this is the first line
this is the second line
this is the third line
this is the forth line
xm@ubuntu:~/xm-git/git_test$ git status
On branch master //位于分支master
nothing to commit, working tree clean //无文件要提交,干净的工作区
继续编译code.txt,继续添加一行内容,并添加到暂存区,git同样告诉我们,用命令git reset HEAD file可以把暂存区的修改撤销掉,重新放回工作区,这个时候再查看git status会告诉我们code.txt为修改状态需要提交
xm@ubuntu:~/xm-git/git_test$ vi code.txt
xm@ubuntu:~/xm-git/git_test$ cat code.txt
this is the first line
this is the second line
this is the third line
this is the forth line
this is the new line
xm@ubuntu:~/xm-git/git_test$ git add code.txt
xm@ubuntu:~/xm-git/git_test$ git status
On branch master
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
modified: code.txt
xm@ubuntu:~/xm-git/git_test$ git reset HEAD code.txt
Unstaged changes after reset:
M code.txt
xm@ubuntu:~/xm-git/git_test$ git status
On branch master
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: code.txt
no changes added to commit (use "git add" and/or "git commit -a")
xm@ubuntu:~/xm-git/git_test$ git checkout -- code.txt
3.4.2 小结
- 当你改乱了工作区某个文件的内容,想直接丢弃工作区的修改时,用命令git checkout -- file
- 当你不但改乱了工作区某个文件的内容,还添加到了暂存区时,想丢弃修改,分两步,第一步用命令git reset HEAD file,就回到了场景1,第二步按场景1操作
- 场景3:已经提交了不合适的修改到版本库时,想要撤销本次提交,参考版本回退一节
3.5 对比文件的不同
对比工作区和某个版本文件的不同
继续编译文件code.txt,在其中添加一行内容,现在要对比工作区中code.txt和HEAD版本中code.txt的不同。使用如下命令:git diff HEAD -- code.txt,--- a/code.txt:-代表HEAD版本中的code.txt,+++ b/code.txt:代表工作区中的code.txt,+the new line:表示工作区中的code.txt比HEAD版本中的code.txt多了一行,没有+和-代表是共有的部分
xm@ubuntu:~/xm-git/git_test$ vi code.txt
xm@ubuntu:~/xm-git/git_test$ cat code.txt
this is the first line
this is the second line
this is the third line
this is the forth line
the new line
xm@ubuntu:~/xm-git/git_test$ git diff HEAD -- code.txt
diff --git a/code.txt b/code.txt
index 66f9219..324317f 100644
--- a/code.txt
+++ b/code.txt
@@ -2,3 +2,4 @@ this is the first line
this is the second line
this is the third line
this is the forth line
+the new line
xm@ubuntu:~/xm-git/git_test$ git checkout -- code.txt
对于两个版本间文件的不同
现在要对比HEAD和HEAD^版本中的code.txt不同,使用如下命令git diff HEAD HEAD^ -- code.txt,-代表HEAD版本code.txt内容,+代表HEAD^版本中code.txt内容,-this is the forth line:代表HEAD版本中比HEAD^多了一行
xm@ubuntu:~/xm-git/git_test$ git diff HEAD HEAD^ -- code.txt
diff --git a/code.txt b/code.txt
index 66f9219..01e1274 100644
--- a/code.txt
+++ b/code.txt
@@ -1,4 +1,3 @@
this is the first line
this is the second line
this is the third line
-this is the forth line
3.6 删除文件
我们把目录中的code2.txt删除
xm@ubuntu:~/xm-git/git_test$ rm code2.txt
xm@ubuntu:~/xm-git/git_test$ git status
On branch master
Changes not staged for commit:
(use "git add/rm <file>..." to update what will be committed)
(use "git checkout -- <file>..." to discard changes in working directory)
deleted: code2.txt
no changes added to commit (use "git add" and/or "git commit -a")
3.6.1 git rm命令
现在我们有两种情况
- 一是确实要从版本库中删除改文件 那就用命令git rm删除,并且git commit
xm@ubuntu:~/xm-git/git_test$ git rm code2.txt
rm 'code2.txt'
xm@ubuntu:~/xm-git/git_test$ git status
On branch master
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
deleted: code2.txt
xm@ubuntu:~/xm-git/git_test$ git commit -m 'rm code2.txt'
[master ce6352f] rm code2.txt
1 file changed, 1 deletion(-)
delete mode 100644 code2.txt
- 而是删错了,git checkout -- code2.txt,这样文件就可以回来了
3.6.2 小结
命令git rm用于删除一个文件。如果一个文件已经被提交到版本库,那么你永远不用担心误删,但是要小心,你只能恢复文件到最新版本,你会丢失最近一次提交后你修改的内容