什么是版本控制?
版本控制:
解决多人协同工作中,容易引起的文件冲突。
记录文件和程序在修改的过程中呵轨迹这样方便咱么以后人员在修改的时候可以找到最新版本的文件内容进行修改,还可以找到次新版本的文件进行操作,,(回滚)。
作用:
用来把咱么的代码和配置文件进行记录和追踪,并且呢可以方便统一的管理。
方便回退。
git 是什么?
Git 简史
同生活中的许多伟大事物一样,Git 诞生于一个极富纷争大举创新的年代。
Linux 内核开源项目有着为数众广的参与者。 绝大多数的 Linux 内核维护工作都花在了提交补丁和保存归档的繁琐事务上(1991-2002年间)。 到 2002 年,整个项目组开始启用一个专有的分布式版本控制系统 BitKeeper 来管理和维护代码。
到了 2005 年,开发 BitKeeper 的商业公司同 Linux 内核开源社区的合作关系结束,他们收回了 Linux 内核社区免费使用 BitKeeper 的权力。 这就迫使 Linux 开源社区(特别是 Linux 的缔造者 Linus Torvalds)基于使用 BitKeeper 时的经验教训,开发出自己的版本系统。 他们对新的系统制订了若干目标:
-
速度
-
简单的设计
-
对非线性开发模式的强力支持(允许成千上万个并行开发的分支)
-
完全分布式
-
有能力高效管理类似 Linux 内核一样的超大规模项目(速度和数据量)
自诞生于 2005 年以来,Git 日臻成熟完善,在高度易用的同时,仍然保留着初期设定的目标。 它的速度飞快,极其适合管理大项目,有着令人难以置信的非线性分支管理系统。
1.git基础知识
直接记录快照,而非差异比较
Git 更像是把数据看作是对小型文件系统的一组快照。 每次你提交更新,或在 Git 中保存项目状态时,它主要对当时的全部文件制作一个快照并保存这个快照的索引。 为了高效,如果文件没有修改,Git 不再重新存储该文件,而是只保留一个链接指向之前存储的文件。 Git 对待数据更像是一个 快照流
近乎所有操作都是本地执行
在 Git 中的绝大多数操作都只需要访问本地文件和资源,一般不需要来自网络上其它计算机的信息
举个例子,要浏览项目的历史,Git 不需外连到服务器去获取历史,然后再显示出来——它只需直接从本地数据库中读取。 你能立即看到项目历史。 如果你想查看当前版本与一个月前的版本之间引入的修改,Git 会查找到一个月前的文件做一次本地的差异计算,而不是由远程服务器处理或从远程服务器拉回旧版本文件再来本地处理。
Git 保证完整性
Git 中所有数据在存储前都计算校验和,然后以校验和来引用。 这意味着不可能在 Git 不知情时更改任何文件内容或目录内容。 这个功能建构在 Git 底层,是构成 Git 哲学不可或缺的部分。 若你在传送过程中丢失信息或损坏文件,Git 就能发现。
Git 一般只添加数据
你执行的 Git 操作,几乎只往 Git 数据库中增加数据。 很难让 Git 执行任何不可逆操作,或者让它以任何方式清除数据。 同别的 VCS 一样,未提交更新时有可能丢失或弄乱修改的内容;但是一旦你提交快照到 Git 中,就难以再丢失数据,特别是如果你定期的推送数据库到其它仓库的话。
三种状态
好,请注意。 如果你希望后面的学习更顺利,记住下面这些关于 Git 的概念。 Git 有三种状态,你的文件可能处于其中之一:已提交(committed)、已修改(modified)和已暂存(staged)。 已提交表示数据已经安全的保存在本地数据库中。 已修改表示修改了文件,但还没保存到数据库中。 已暂存表示对一个已修改文件的当前版本做了标记,使之包含在下次提交的快照中。
由此引入 Git 项目的三个工作区域的概念:Git 仓库、工作目录以及暂存区域。
2.git的基本工作流程
-
在工作目录中修改文件。
-
暂存文件,将文件的快照放入暂存区域。
-
提交更新,找到暂存区域的文件,将快照永久性存储到 Git 仓库目录。
安装git
Git 版本控制,安装简单,不需要任何的配置,只需要git 一条命令搞定。
[root@server05 ~]# yum install -y git
1. 查看软件是否安装
[root@server05 ~]# rpm -qa | grep git
2. 使用git 命令查看帮助
[root@server05 ~]# git
usage: git [--version] [--exec-path[=GIT_EXEC_PATH]] [--html-path]
[-p|--paginate|--no-pager] [--no-replace-objects]
[--bare] [--git-dir=GIT_DIR] [--work-tree=GIT_WORK_TREE]
[--help] COMMAND [ARGS]
The most commonly used git commands are:
add Add file contents to the index
bisect Find by binary search the change that introduced a bug
branch List, create, or delete branches
checkout Checkout a branch or paths to the working tree
clone Clone a repository into a new directory
commit Record changes to the repository
diff Show changes between commits, commit and working tree, etc
fetch Download objects and refs from another repository
grep Print lines matching a pattern
init Create an empty git repository or reinitialize an existing one
log Show commit logs
merge Join two or more development histories together
mv Move or rename a file, a directory, or a symlink
pull Fetch from and merge with another repository or a local branch
push Update remote refs along with associated objects
rebase Forward-port local commits to the updated upstream head
reset Reset current HEAD to the specified state
rm Remove files from the working tree and from the index
show Show various types of objects
status Show the working tree status
tag Create, list, delete or verify a tag object signed with GPG
See 'git help COMMAND' for more information on a specific command.
参数详解:
http://www.ruanyifeng.com/blog/2015/12/git-cheat-sheet.html
参考此连接
创建版本库
什么是版本库呢?版本库又名仓库,英文名repository,你可以简单理解成一个目录,这个目录里面的所有文件都可以被Git管理起来,每个文件的修改、删除,Git都能跟踪,以便任何时刻都可以追踪历史,或者在将来某个时刻可以“还原”。
所以,创建一个版本库非常简单,首先,选择一个合适的地方,创建一个空目录:
1.创建一个目录
[root@server05 ~]# mkdir /dir
[root@server05 ~]# cd /dir/
[root@server05 dir]# pwd
/dir
2. 通过git init命令把这个目录变成Git可以管理的仓库:
[root@server05 dir]# git init
Initialized empty Git repository in /dir/.git/
[root@server05 dir]# ls -a
. .. .git
首先这里再明确一下,所有的版本控制系统,其实只能跟踪文本文件的改动,比如TXT文件,网页,所有的程序代码等等,Git也不例外。
现在我们编写一个git.txt文件,内容如下:
[root@server05 dir]# cat git.txt
git is software
注意:一定要放到dir目录下(子目录也行),因为这是一个Git仓库,放到其他地方Git再厉害也找不到这个文件。
用命令git add告诉Git,把文件添加到仓库:
[root@server05 dir]# git add git.txt
git add <file>,注意,可反复多次使用,添加多个文件;
用命令git commit告诉Git,把文件提交到仓库:
[root@server05 dir]# git commit -m "new is test"
[master (root-commit) e0be413] new is test
Committer: root <root@server05.linux.com>
Your name and email address were configured automatically based
on your username and hostname. Please check that they are accurate.
You can suppress this message by setting them explicitly:
git config --global user.name "Your Name"
git config --global user.email you@example.com
If the identity used for this commit is wrong, you can fix it with:
git commit --amend --author='Your Name <you@example.com>'
1 files changed, 1 insertions(+), 0 deletions(-)
create mode 100644 git.txt
解决屏幕打印过多信息:
使用git前的基本设置
[root@node01 ~]# git config --global user.name "Martin" 用户
[root@node01 ~]# git config --global user.email "Martin@qq.com" 邮箱
[root@node01 ~]# git config --global color.ui true 颜色
解释:简单解释一下git commit命令,-m后面输入的是本次提交的说明,可以输入任意内容,当然最好是有意义的,这样你就能从历史记录里方便地找到改动记录。
嫌麻烦不想输入-m "xxx"行不行?确实有办法可以这么干,但是强烈不建议你这么干,因为输入说明对自己对别人阅读都很重要。实在不想输入说明的 请自行google 不推荐
git commit命令执行成功后会告诉你,1个文件被改动(我们新添加的readme.txt文件),插入了两行内容(readme.txt有两行内容)。
时光穿梭机
我们已经成功地添加并提交了一git.txt文件,现在,是时候继续工作了,于是,我们继续修改git.txt文件,改成如下内容:
现在,运行git status命令看看结果:
git status命令可以让我们时刻掌握仓库当前的状态,上面的命令告诉我们,readme.txt被修改过了,但还没有准备提交的修改。
虽然Git告诉我们git.txt被修改了,但如果能看看具体修改了什么内容,自然是很好的。比如你休假两周从国外回来,第一天上班时,已经记不清上次怎么修改的readme.txt,所以,需要用git diff这个命令看看:
提交文件 git add
同样没有任何输出。在执行第二步git commit之前,我们再运行git status看看当前仓库的状态:
git status告诉我们,将要被提交的修改包括git.txt,下一步,就可以放心地提交了:
提交后,我们再用git status命令看看仓库的当前状态:
Git告诉我们当前没有需要提交的修改,而且,工作目录是干净(working directory clean)的。
我们已经成功地添加并提交了一个git.txt文件,现在,是时候继续工作了,于是,我们继续修改git.txt文件,改成如下内容:
现在,运行git status命令看看结果:
git status 命令可以让我们随时掌握仓库当前的状态,上面的命令告诉我们git.txt文件被修改过了
但修改并没有提交
git 虽然告诉我们 git.txt文件被修改过了 但是如果你出差几天后,忘了自己修改过什么;如果能看到不是更好吗 这时候就需要
用git diff 这个命令来查看
注意:只有在git status 后提示有修改 git diff 才会有显示
版本回退
像这样,你不断对文件进行修改,然后不断提交修改到版本库里。Git也是一样,每当你觉得文件修改到一定程度的时候,就可以“保存一个快照”,这个快照在Git中被称为commit。一旦你把文件改乱了,或者误删了文件,还可以从最近的一个commit恢复,然后继续工作,而不是把几个月的工作成果全部丢失。
当然了,在实际工作中,我们脑子里怎么可能记得一个几千行的文件每次都改了什么内容,不然要版本控制系统干什么。版本控制系统肯定有某个命令可以告诉我们历史记录,在Git中,我们用git log命令查看:
git log 命令 显示从最近到最远的提交日志,可以看到截图只显示了 两次提交 最近一次是22222
如果有太多的日志 不方便查看可以试试 添加 --pretty=oneline 参数
每提交一个新版本,实际上Git就会把它们自动串成一条时间线。如果使用可视化工具查看Git历史,就可以更清楚地看到提交历史的时间线:
好了,现在我们启动时光穿梭机,准备把git.txt回退到上一个版本,也就是“11111111111”的那个版本,怎么做呢?
首先,Git必须知道当前版本是哪个版本,在Git中,用HEAD表示当前版本,也就是最新的提交3628164...882e1e0(注意我的提交ID和你的肯定不一样),上一个版本就是HEAD^,上上一个版本就是HEAD^^,当然往上100个版本写100个^比较容易数不过来,所以写成HEAD~100。
使用git reset命令:
已经回退到了上一个版本 111111
还可以继续回退到上一个版本wrote a readme file,不过且慢,让我们用git log再看看现在版本库的状态:
最新的那个版本已经看不到了!好比你从21世纪坐时光穿梭机来到了19世纪,想再回去已经回不去了,肿么办?
办法其实还是有的,只要上面的命令行窗口还没有被关掉,你就可以顺着往上找啊找啊,于是就可以指定回到未来的某个版本:
果然,我胡汉三又回来了。
版本号没必要写全,前几位就可以了,Git会自动去找。当然也不能只写前一两位,因为Git可能会找到多个版本号,就无法确定是哪一个了 写前7位。
现在,你回退到了某个版本,关掉了电脑,第二天早上就后悔了,想恢复到新版本怎么办?找不到新版本的commit id怎么办?
在Git中,总是有后悔药可以吃的。当你用$ git reset --hard HEAD^回退到1111111111111版本时,再想恢复到2222222222,就必须找到2222222222222的commit id。Git提供了一个命令git reflog用来记录你的每一次命令:
现在总结一下:
HEAD指向的版本就是当前版本,因此,Git允许我们在版本的历史之间穿梭,使用命令git reset --hard commit_id。
穿梭前,用git log可以查看提交历史,以便确定要回退到哪个版本。
要重返未来,用git reflog查看命令历史,以便确定要回到未来的哪个版本。
工作区 和暂存区
Git和其他版本控制系统如SVN的一个不同之处就是有暂存区的概念。
工作区(Working Directory)
就是你在电脑里能看到的目录,比如我的git文件夹就是一个工作区:
版本库(Repository)
工作区有一个隐藏目录.git,这个不算工作区,而是Git的版本库。
Git的版本库里存了很多东西,其中最重要的就是称为stage(或者叫index)的暂存区,还有默认Git为我们自动创建的第一个分支master。
前面描述了我们把文件往Git版本库里添加的时候,是分两步执行的:
第一步是用git add把文件添加进去,实际上就是把文件修改添加到暂存区;
第二步是用git commit提交更改,实际上就是把暂存区的所有内容提交到当前分支。
因为我们创建Git版本库时,Git自动为我们创建了唯一一个master分支,所以,现在,git commit就是往master分支上提交更改。
你可以简单理解为,需要提交的文件修改通通放到暂存区,然后,一次性提交暂存区的所有修改。
管理修改
为什么Git比其他版本控制系统设计得优秀,因为Git跟踪并管理的是修改,而非文件。
你会问,什么是修改?比如你新增了一行,这就是一个修改,删除了一行,也是一个修改,更改了某些字符,也是一个修改,删了一些又加了一些,也是一个修改,甚至创建一个新文件,也算一个修改。
为什么说Git管理的是修改,而不是文件呢?我们还是做实验。第一步,对git.txt做一个修改,比如加一行内容:
提交
再次修改
直接 提交到仓库
看状态
怎么第二次的修改没有被提交?
我们回顾一下刚才的操作
第一次修改 -> git add -> 第二次修改 -> git commit
你看,我们前面讲了,Git管理的是修改,当你用git add命令后,在工作区的第一次修改被放入暂存区,准备提交,但是,在工作区的第二次修改并没有放入暂存区,所以,git commit只负责把暂存区的修改提交了,也就是第一次的修改被提交了,第二次的修改不会被提交。
提交后,用git diff HEAD -- readme.txt命令可以查看工作区和版本库里面最新版本的区别:
可见,第二次修改确实没有被提交。
那怎么提交第二次修改呢?你可以继续git add再git commit,也可以别着急提交第一次修改,先git add第二次修改,再git commit,就相当于把两次修改合并后一块提交了:
第一次修改 -> git add -> 第二次修改 -> git add -> git commit
结论:每次修改,如果不add到暂存区,那就不会加入到commit中。
撤销修改
自然 谁都会犯错 ,当凌晨两点你正在赶一份工作报告,你在 git.txt中添加了一行“stupid boss” 当你准备提交时 已被咖啡起了作用 想起这可能让你丢了这个月的奖金~
现在发现及时,就可以很容易纠正,你可以删掉这一行手动把文件恢复到上个版本 ,但是你查看状态的时候
不必担心你的老板会看到你做过修改 git提示你 ”git checkout -- <file>“ 可以丢弃工作区得修改
命令git checkout -- git.txt意思就是,把readme.txt文件在工作区的修改全部撤销,这里有两种情况:
一种是git.txt自修改后还没有被放到暂存区,现在,撤销修改就回到和版本库一模一样的状态;
一种是git.txt已经添加到暂存区后,又作了修改,现在,撤销修改就回到添加到暂存区后的状态。总之,就是让这个文件回到最近一次git commit或git add时的状态。
git checkout -- file命令中的--很重要,没有--,就变成了“切换到另一个分支”的命令,我们在后面的分支管理中会再次遇到git checkout命令。
现在假定是凌晨3点,你不但写了一些胡话,还git add到暂存区了:
幸的是,在commit之前,你发现了这个问题。用git status查看一下,修改只是添加到了暂存区,还没有提交:
Git同样告诉我们,用命令git reset HEAD file可以把暂存区的修改撤销掉(unstage),重新放回工作区:
git reset命令既可以回退版本,也可以把暂存区的修改回退到工作区。当我们用HEAD时,表示最新的版本。
再用git status查看一下,现在暂存区是干净的,工作区有修改
好了 又恢复干净了
现在,假设你不但改错了东西,还从暂存区提交到了版本库,怎么办呢?还记得版本回退一节吗?可以回退到上一个版本。不过,这是有条件的,就是你还没有把自己的本地版本库推送到远程。还记得Git是分布式版本控制系统吗?我们后面会讲到远程版本库,一旦你把不合适得 内容发送到远程版本库,你就真得惨了
删除文件
在git中 删除也时一个修改得操作,
先添加文件test.txt 到git 并且 提交
一般情况下 直接rm -f 直接把没用得文件删除了,这个时候 git 知道你删除了文件,因此工作区和版本库不一致了
git status 命令会告诉你哪些文件被删除了
撤销删除
第二种选择 你要确认删除 该文件,那就用命令git rm 删掉 并且 用git commit 提交
命令git rm用于删除一个文件。如果一个文件已经被提交到版本库,那么你永远不用担心误删,但是要小心,你只能恢复文件到最新版本,你会丢失最近一次提交后你修改的内容。