GIT简介

46 篇文章 0 订阅
21 篇文章 0 订阅

文档索引:

  • 简介
  • Git安装
  • 创建版本库
  • 时光穿梭机
  • 版本回退
  • 工作区和暂存区
  • 管理修改
  • 撤销修改
  • 删除文件
  • 分支管理
  • 创建和合并分支
  • 解决冲突
  • 分支管理策略
  • Bug分支

  • GIt简介;

Git是一个开源的分布式版本控制系统,用于敏捷高效地处理任何或小或大的项目。

Git 是 Linus Torvalds 为了帮助管理 Linux 内核开发而开发的一个开放源码的版本控制软件。

Git 与常用的版本控制工具 CVS, Subversion 等不同,它采用了分布式版本库的方式,不必服务器端软件支持

  • 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了。

  • 分布式和集中式

Linus一直痛恨的CVS及SVN都是集中式的版本控制系统,而Git是分布式版本控制系统,集中式和分布式版本控制系统有什么区别呢?

先说集中式版本控制系统,版本库是集中存放在中央服务器的,而干活的时候,用的都是自己的电脑,所以要先从中央服务器取得最新的版本,然后开始干活,干完活了,再把自己的活推送给中央服务器。中央服务器就好比是一个图书馆,你要改一本书,必须先从图书馆借出来,然后回到家自己改,改完了,再放回图书馆。

集中式版本控制系统最大的毛病就是必须联网才能工作,如果在局域网内还好,带宽够大,速度够快,可如果在互联网上,遇到网速慢的话,可能提交一个10M的文件就需要5分钟,这还不得把人给憋死啊。

那分布式版本控制系统与集中式版本控制系统有何不同呢?首先,分布式版本控制系统根本没有“中央服务器”,每个人的电脑上都是一个完整的版本库,这样,你工作的时候,就不需要联网了,因为版本库就在你自己的电脑上。既然每个人电脑上都有一个完整的版本库,那多个人如何协作呢?比方说你在自己电脑上改了文件A,你的同事也在他的电脑上改了文件A,这时,你们俩之间只需把各自的修改推送给对方,就可以互相看到对方的修改了。

和集中式版本控制系统相比,分布式版本控制系统的安全性要高很多,因为每个人电脑里都有完整的版本库,某一个人的电脑坏掉了不要紧,随便从其他人那里复制一个就可以了。而集中式版本控制系统的中央服务器要是出了问题,所有人都没法干活了。

在实际使用分布式版本控制系统的时候,其实很少在两人之间的电脑上推送版本库的修改,因为可能你们俩不在一个局域网内,两台电脑互相访问不了,也可能今天你的同事病了,他的电脑压根没有开机。因此,分布式版本控制系统通常也有一台充当“中央服务器”的电脑,但这个服务器的作用仅仅是用来方便“交换”大家的修改,没有它大家也一样干活,只是交换修改不方便而已

当然,Git的优势不单是不必联网这么简单,后面我们还会看到Git极其强大的分支管理,把SVN等远远抛在了后面。

CVS作为最早的开源而且免费的集中式版本控制系统,直到现在还有不少人在用。由于CVS自身设计的问题,会造成提交文件不完整,版本库莫名其妙损坏的情况。同样是开源而且免费的SVN修正了CVS的一些稳定性问题,是目前用得最多的集中式版本库控制系统。

除了免费的外,还有收费的集中式版本控制系统,比如IBM的ClearCase(以前是Rational公司的,被IBM收购了),特点是安装比Windows还大,运行比蜗牛还慢,能用ClearCase的一般是世界500强,他们有个共同的特点是财大气粗,或者人傻钱多。

微软自己也有一个集中式版本控制系统叫VSS,集成在Visual Studio中。由于其反人类的设计,连微软自己都不好意思用了。

分布式版本控制系统除了Git以及促使Git诞生的BitKeeper外,还有类似Git的Mercurial和Bazaar等。这些分布式版本控制系统各有特点,但最快、最简单也最流行的依然是Git!

四、案例:;

案例环境:

系统类型

IP地址

主机名

所需软件

Centos7.4

192.168.100.101

www.linuxfan.cn

git-2.18.0.tar.gz

案例步骤:

  • A 安装git

首先,你可以试着输入git,看看系统有没有安装Git:

[root@www ~]# git

usage: git [--version] [--help] [-C <path>] [-c <name>=<value>]

           [--exec-path[=<path>]] [--html-path] [--man-path] [--info-path]

           [-p | --paginate | -P | --no-pager] [--no-replace-objects] [--bare]

           [--git-dir=<path>] [--work-tree=<path>] [--namespace=<name>]

           <command> [<args>]

这些是各种场合常见的 Git 命令:

开始一个工作区(参见:git help tutorial)

   clone      克隆一个仓库到一个新目录

   init       创建一个空的 Git 仓库或重新初始化一个已存在的仓库

在当前变更上工作(参见:git help everyday)

   add        添加文件内容至索引

   mv         移动或重命名一个文件、目录或符号链接

   reset      重置当前 HEAD 到指定状态

   rm         从工作区和索引中删除文件

检查历史和状态(参见:git help revisions)   

bisect     通过二分查找定位引入 bug 的提交

   grep       输出和模式匹配的行

   log        显示提交日志

   show       显示各种类型的对象

   status     显示工作区状态

扩展、标记和调校您的历史记录

   branch     列出、创建或删除分支

   checkout   切换分支或恢复工作区文件

   commit     记录变更到仓库

   diff       显示提交之间、提交和工作区之间等的差异

   merge      合并两个或更多开发历史

   rebase     在另一个分支上重新应用提交

   tag        创建、列出、删除或校验一个 GPG 签名的标签对象

协同(参见:git help workflows)

   fetch      从另外一个仓库下载对象和引用

   pull       获取并整合另外的仓库或一个本地分支

   push       更新远程引用和相关的对象

命令 'git help -a' 和 'git help -g' 显示可用的子命令和一些概念帮助。

查看 'git help <命令>' 或 'git help <概念>' 以获取给定子命令或概念的

帮助。

[root@www ~]# git --version

git version 1.8.3.1

[root@www ~]# rpm -e git --nodeps

[root@www ~]# mount /dev/cdrom /mnt

mount: /dev/sr0 写保护,将以只读方式挂载

[root@www ~]# ls

anaconda-ks.cfg  git-2.18.0.tar.gz

[root@www ~]# tar zxvf git-2.18.0.tar.gz

[root@www git-2.18.0]# ./configure --prefix=/usr/local/git

[root@www git-2.18.0]# make

GIT_VERSION = 2.18.0

    * new build flags

    CC credential-store.o

In file included from credential-store.c:1:0:

cache.h:19:18: 致命错误:zlib.h:没有那个文件或目录

 #include <zlib.h>

                  ^

编译中断。

make: *** [credential-store.o] 错误 1

[root@www git-2.18.0]# yum -y install zlib-devel

[root@www git-2.18.0]# make && make install

[root@www git-2.18.0]# git --version

-bash: /usr/bin/git: 没有那个文件或目录             ####git命令不在环境变量中

[root@www git-2.18.0]# cat <<END>> /etc/profile

  export PATH=$PATH:/usr/local/git/bin

END

[root@www git-2.18.0]# source /etc/profile

[root@www git-2.18.0]# cd

[root@www ~]# git --version

git version 2.18.0

  • B 创建版本库
[root@www ~]# cd /tmp    

[root@www tmp]# mkdir repository   ###创建版本库非常简单,选择一个合适的地方,创建一个空目录:

[root@www tmp]# cd repository   

[root@www repository]# pwd

/tmp/repository

[root@www repository]# git init      ##通过git init命令把这个目录变成Git可以管理的仓库:

已初始化空的 Git 仓库于 /tmp/repository/.git/   ###这个目录是Git来跟踪管理版本库的,没事千万不要手动修改这个目录里面的文件,不然改乱了,就把Git仓库给破坏了

[root@www repository]# ls

[root@www repository]# ls -ah      ###隐藏的,用ls -ah命令就可以看见

.  ..  .git

[root@www repository]# vi 1.txt

git is a free software.

git is a version control system.

[root@www repository]# git add 1.txt          ####第一步,用命令git add告诉Git,把文件添加到仓库:

执行上面的命令,没有任何显示,这就对了

[root@www repository]# git commit -m "liyu write it"   #####第二步,用命令git commit告诉Git,把文件提交到仓库:

[master(根提交) ae97fb0] liyu write it

 Committer: root <root@www.linuxfan.cn>

您的姓名和邮件地址基于登录名和主机名进行了自动设置请检查它们正确

与否。您可以对其进行设置以免再出现本提示信息。运行如下命令在编辑器

中编辑您的配置文件:

  

  git config --global --edit

设置完毕后,您可以用下面的命令来修正本次提交所使用的用户身份:

    git commit --amend --reset-author

 1 file changed, 2 insertions(+)       ### 1 file changed:1个文件被改动(我们新添加的1.txt文件)

2 insertions:插入了两行内容(1.txt有两行内容)

 create mode 100644 1.txt           ####   -m  后面输入的是本次提交的说明,可以输入任意内容,当然最好是有意义的

[root@www repository]#  git config --global --edit

# This is Git's per-user configuration file.

[user]

# Please adapt and uncomment the following lines:

#       name = liyu

#       email = change_jary@163.com

[root@www repository]# cd

为什么Git添加文件需要addcommit一共两步呢?因为commit可以一次提交很多文件,所以你可以多次add不同的文件

[root@www ~]# cd /tmp/repository/

[root@www repository]# touch {2..6}.txt

[root@www repository]# git add {2..6}.txt

[root@www repository]# git commit -m "liyu write these file"

[master 5d661ed] liyu write these file

 5 files changed, 0 insertions(+), 0 deletions(-)

 create mode 100644 2.txt

 create mode 100644 3.txt

 create mode 100644 4.txt

 create mode 100644 5.txt  

 create mode 100644 6.txt
  • C   时光穿梭机

已经成功地添加并提交了一个1.txt文件,现在继续修改1.txt文件,改成如下内容

[root@www repository]# vi 1.txt

git is not a free software.

git is not a version control system.

:wq

[root@www repository]# git status

位于分支 master

尚未暂存以备提交的变更:

  (使用 "git add <文件>..." 更新要提交的内容)

  (使用 "git checkout -- <文件>..." 丢弃工作区的改动)

修改:     1.txt

修改尚未加入提交(使用 "git add" 和/或 "git commit -a")

[root@www repository]# git diff 1.txt

diff --git a/1.txt b/1.txt

index 6f58a29..6822f13 100644

--- a/1.txt

+++ b/1.txt

@@ -1,2 +1,2 @@

-git is a free software.

-git is a version control system.

+git is not a free software.

+git is not a version control system.

知道了对readme.txt作了什么修改后,再把它提交到仓库,提交修改和提交新文件是一样的两步

[root@www repository]# git add 1.txt

[root@www repository]# git status

位于分支 master

要提交的变更:

  (使用 "git reset HEAD <文件>..." 以取消暂存)

修改:     1.txt

[root@www repository]# git commit -m "liyu change the file"

[master ed318f7] liyu change the file

 1 file changed, 2 insertions(+), 2 deletions(-)

[root@www repository]# git status

位于分支 master

无文件要提交,干净的工作区

[root@www repository]# vi 1.txt

git is not a simple free software.

git is not a version control system.

[root@www repository]# git status

位于分支 master

尚未暂存以备提交的变更:

  (使用 "git add <文件>..." 更新要提交的内容)

  (使用 "git checkout -- <文件>..." 丢弃工作区的改动)

修改:     1.txt

修改尚未加入提交(使用 "git add" 和/或 "git commit -a")

[root@www repository]# git add 1.txt

[root@www repository]# git commit -m "liyu is very cool"

[master 18169b6] liyu is very cool

 1 file changed, 2 insertions(+), 1 deletion(-)

[root@www repository]# git status

位于分支 master

无文件要提交,干净的工作区

#######在实际工作中,我们脑子里怎么可能记得一个几千行的文件每次都改了什么内容,不然要版本控制系统干什么。版本控制系统肯定有某个命令可以告诉我们历史记录,在Git中,我们用git log命令查看

[root@www repository]# git log

commit 18169b682b3f3c3642915d2fd7596da947a6f572 (HEAD -> master)

Author: liyu666 <867839624@qq.com>

Date:   Thu Aug 30 16:27:50 2018 +0800



    liyu is very cool



commit ed318f77c882497bfe4b6ef40f4d0beddb568929

Author: liyu666 <867839624@qq.com>

Date:   Thu Aug 30 16:19:42 2018 +0800



    liyu change the file



commit 5d661edb6e9eac21b06b3b5c89aacef6f97b300e

Author: liyu666 <867839624@qq.com>

Date:   Thu Aug 30 16:05:56 2018 +0800



    liyu write these file



commit ae97fb08aeec0c7e7afa467b341bfe7f24fe8cff

Author: root <root@www.linuxfan.cn>

Date:   Thu Aug 30 15:16:54 2018 +0800



liyu write it
#####嫌输出信息太多,看得眼花缭乱的,可以试试加上--pretty=oneline参数[root@www repository]# git log --pretty=oneline     

18169b682b3f3c3642915d2fd7596da947a6f572 (HEAD -> master) liyu is very cool

ed318f77c882497bfe4b6ef40f4d0beddb568929 liyu change the file

5d661edb6e9eac21b06b3b5c89aacef6f97b300e liyu write these file

ae97fb08aeec0c7e7afa467b341bfe7f24fe8cff liyu write it

版本回退:

现在我们启动时光穿梭机,准备把readme.txt回退到上一个版本;

[root@www repository]# git reset --hard HEAD^

HEAD 现在位于 ed318f7 liyu change the file

[root@www repository]# git reset --hard HEAD^^

HEAD 现在位于 ae97fb0 liyu write it

[root@www repository]# cat 1.txt

git is a free software.

git is a version control system.

[root@www repository]# git log

commit ae97fb08aeec0c7e7afa467b341bfe7f24fe8cff (HEAD -> master)

Author: root <root@www.linuxfan.cn>

Date:   Thu Aug 30 15:16:54 2018 +0800

最新的那个版本append GPL已经看不到了!好比你从21世纪坐时光穿梭机来到了19世纪,想再回去已经回不去了,肿么办?办法其实还是有的,只要上面的命令行窗口还没有被关掉,你就可以顺着往上找啊找啊,找到那个append GPL的commit id是1816...,于是就可以指定回到未来的某个版本:

[root@www repository]# git reset --hard 1816

HEAD 现在位于 18169b6 liyu is very cool

[root@www repository]# cat 1.txt

git is not a simple free software.

git is not a version control system.

果然,我胡汉三又回来了!

[root@www repository]# git reflog

18169b6 (HEAD -> master) HEAD@{0}: reset: moving to 1816

ae97fb0 HEAD@{1}: reset: moving to HEAD^^

ed318f7 HEAD@{2}: reset: moving to HEAD

ed318f7 HEAD@{3}: reset: moving to HEAD^

18169b6 (HEAD -> master) HEAD@{4}: commit: liyu is very cool

ed318f7 HEAD@{5}: commit: liyu change the file

5d661ed HEAD@{6}: commit: liyu write these file

ae97fb0 HEAD@{7}: commit (initial): liyu write it

工作区和暂存区

Git和其他版本控制系统如SVN的一个不同之处就是有暂存区的概念。

先来看名词解释。

工作区(Working Directory)

就是你在电脑里能看到的目录

版本库(Repository)

工作区有一个隐藏目录.git,这个不算工作区,而是Git的版本库。

Git的版本库里存了很多东西,其中最重要的就是称为stage(或者叫index)的暂存区,还有Git为我们自动创建的第一个分支master,以及指向master的一个指针叫HEAD

前面讲了我们把文件往Git版本库里添加的时候,是分两步执行的:

第一步是用git add把文件添加进去,实际上就是把文件修改添加到暂存区;

第二步是用git commit提交更改,实际上就是把暂存区的所有内容提交到当前分支。

因为我们创建Git版本库时,Git自动为我们创建了唯一一个master分支,所以,现在,git commit就是往master分支上提交更改。

你可以简单理解为,需要提交的文件修改通通放到暂存区,然后,一次性提交暂存区的所有修改。

现在,我们练习一遍,先对1.txt做个修改,比如加上一行内容:

[root@www repository]# vi 1.txt     

git is not a simple free software.

git is not a version control system.

zs is a good student

[root@www repository]# vi 1.file      ####工作区新增一个1.file文本文件(内容随便写)。

Suibianxie

[root@www repository]# git status   ####查看git状态###

位于分支 master

尚未暂存以备提交的变更

  (使用 "git add <文件>..." 更新要提交的内容)

  (使用 "git checkout -- <文件>..." 丢弃工作区的改动)

修改:     1.txt

未跟踪的文件:

  (使用 "git add <文件>..." 以包含要提交的内容)

1.file

修改尚未加入提交(使用 "git add" 和/或 "git commit -a")

Git非常清楚地告诉我们,1.txt被修改了,而1.file还从来没有被添加过,所以它的状态是未跟踪

[root@www repository]# git add 1.txt     ###将两个文件提交####

[root@www repository]# git add 1.file

[root@www repository]# git status

位于分支 master

要提交的变更:

  (使用 "git reset HEAD <文件>..." 以取消暂存)

新文件:   1.file

修改:     1.txt

现在,暂存区的状态就变成这样了:

所以,git add命令实际上就是把要提交的所有修改放到暂存区(Stage),然后,执行git commit就可以一次性把暂存区的所有修改提交到分支

[root@www repository]# git commit -m "zs is an people"    

[master dbe9d83] zs is an people

 2 files changed, 2 insertions(+)

 create m[root@www repository]# git status

位于分支 master

无文件要提交,干净的工作区ode 100644 1.file

######一旦提交后,如果你又没有对工作区做任何修改,那么工作区就是“干净”的:###

现在版本库变成了这样,暂存区就没有任何内容了;

管理修改;

现在,假定你已经完全掌握了暂存区的概念。下面,我们要讨论的就是,为什么Git比其他版本控制系统设计得优秀,因为Git跟踪并管理的是修改,而非文件;

什么是修改?比如你新增了一行,这就是一个修改,删除了一行,也是一个修改,更改了某些字符,也是一个修改,删了一些又加了一些,也是一个修改,甚至创建一个新文件,也算一个修改。

为什么说Git管理的是修改,而不是文件呢?我们还是做实验。第一步,对1.txt做一个修改,比如加一行内容:

[root@www repository]# cat 1.txt

git is not a simple free software.

git is not a version control system.

zs is a good student



[root@www repository]# vi 1.txt

git is not a simple free software.

git is not a version control system.

zs is a good student

ls is a bad student

:wq

[root@www repository]# git add 1.txt

[root@www repository]# git status

位于分支 master

要提交的变更:

  (使用 "git reset HEAD <文件>..." 以取消暂存)

修改:     1.txt

[root@www repository]# vi 1.txt

git is not a simple free software.

git is not a version control system.

zs is a good student

ls is a bad student

ww is a bad student too

[root@www repository]# git commit -m "ww is a bad student too"

[master ff917f2] ww is a bad student too

 1 file changed, 1 insertion(+), 1 deletion(-)

[root@www repository]# git status

位于分支 master

尚未暂存以备提交的变更:

  (使用 "git add <文件>..." 更新要提交的内容)

  (使用 "git checkout -- <文件>..." 丢弃工作区的改动)

修改:     1.txt

修改尚未加入提交(使用 "git add" 和/或 "git commit -a")

发现第二次的修改没有被提交?

我们回顾一下操作过程:

第一次修改 -> git add -> 第二次修改 -> git commit

你看,我们前面讲了,Git管理的是修改,当你用git add命令后,在工作区的第一次修改被放入暂存区,准备提交,但是,在工作区的第二次修改并没有放入暂存区,所以,git commit只负责把暂存区的修改提交了,也就是第一次的修改被提交了,第二次的修改不会被提交。

提交后,用git diff HEAD -- readme.txt命令可以查看工作区和版本库里面最新版本的区别:

[root@www repository]# git diff HEAD -- 1.txt

diff --git a/1.txt b/1.txt

index 6ca4b02..a1ad8dc 100644

--- a/1.txt

+++ b/1.txt

@@ -2,3 +2,4 @@ git is not a simple free software.

 git is not a version control system.

 zs is a good student

 ls is a bad student

+ww is a bad student too     ####可见第二次的修改没有背提交####

管理修改

阅读: 698379

现在,假定你已经完全掌握了暂存区的概念。下面,我们要讨论的就是,为什么Git比其他版本控制系统设计得优秀,因为Git跟踪并管理的是修改,而非文件。

你会问,什么是修改?比如你新增了一行,这就是一个修改,删除了一行,也是一个修改,更改了某些字符,也是一个修改,删了一些又加了一些,也是一个修改,甚至创建一个新文件,也算一个修改。

为什么说Git管理的是修改,而不是文件呢?我们还是做实验。第一步,对readme.txt做一个修改,比如加一行内容:

$ cat readme.txt

Git is a distributed version control system.

Git is free software distributed under the GPL.

Git has a mutable index called stage.

Git tracks changes.

然后,添加:

$ git add readme.txt$ git status# On branch master# Changes to be committed:#   (use "git reset HEAD <file>..." to unstage)##       modified:   readme.txt#

然后,再修改readme.txt:

$ cat readme.txt

Git is a distributed version control system.

Git is free software distributed under the GPL.

Git has a mutable index called stage.

Git tracks changes of files.

提交:

$ git commit -m "git tracks changes"

[master 519219b] git tracks changes

 1 file changed, 1 insertion(+)

提交后,再看看状态:

$ 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:   readme.txt

no changes added to commit (use "git add" and/or "git commit -a")

咦,怎么第二次的修改没有被提交?

别激动,我们回顾一下操作过程:

第一次修改 -> git add -> 第二次修改 -> git commit

你看,我们前面讲了,Git管理的是修改,当你用git add命令后,在工作区的第一次修改被放入暂存区,准备提交,但是,在工作区的第二次修改并没有放入暂存区,所以,git commit只负责把暂存区的修改提交了,也就是第一次的修改被提交了,第二次的修改不会被提交。

提交后,用git diff HEAD -- readme.txt命令可以查看工作区和版本库里面最新版本的区别:

$ git diff HEAD -- readme.txt

diff --git a/readme.txt b/readme.txt

index 76d770f..a9c5755 100644

--- a/readme.txt

+++ b/readme.txt@@ -1,4 +1,4 @@

 Git is a distributed version control system.

 Git is free software distributed under the GPL.

 Git has a mutable index called stage.

-Git tracks changes.

+Git tracks changes of files.

可见,第二次修改确实没有被提交。

那怎么提交第二次修改呢?你可以继续git addgit commit,也可以别着急提交第一次修改,先git add第二次修改,再git commit,就相当于把两次修改合并后一块提交了:

第一次修改 -> git add -> 第二次修改 -> git add -> git commit

撤销修改;

[root@www repository]# vi 1.txt     ##当你加班到深夜,困到不行,无意间写了一句###

git is not a simple free software.

git is not a version control system.

zs is a good student

ls is a bad student

ww is a bad student too

my boss is a pig

:wq

####写完以后,突然发现!这句话可能会让自己打包滚蛋###

####既然错误发现得很及时,就可以很容易地纠正它。你可以删掉最后一行,手动把文件恢复到上一个版本的状态。如果用git status查看一下:####、

[root@www repository]# vi 1.txt



git is not a simple free software.

git is not a version control system.

zs is a good student

ls is a bad student

ww i[root@www repository]# git status

位于分支 master

尚未暂存以备提交的变更:

  (使用 "git add <文件>..." 更新要提交的内容)

  (使用 "git checkout -- <文件>..." 丢弃工作区的改动)

修改:     1.txt

修改尚未加入提交(使用 "git add" 和/或 "git commit -a")

#####你可以发现,Git会告诉你,git checkout -- 文件可以丢弃工作区的修改:###

命令git checkout -- 1.txt意思就是,把1.txt文件在工作区的修改全部撤销,这里有两种情况:

一种是1.txt自修改后还没有被放到暂存区,现在,撤销修改就回到和版本库一模一样的状态;

一种是1.txt已经添加到暂存区后,又作了修改,现在,撤销修改就回到添加到暂存区后的状态。

总之,就是让这个文件回到最近一次git commitgit add时的状态。

现在,看看1.txt的文件内容:

[root@www repository]# cat 1.txt

git is not a simple free software.

git is not a version control system.

zs is a good student

ls is a bad student

ww is a bad student too

###文件内容果然复原了。

git checkout -- file命令中的--很重要,没有--,就变成了“切换到另一个分支”的命令,我们在后面的分支管理中会再次遇到git checkout命令###

现在假定,你不但写了一些胡话,还git add到暂存区了:

[root@www repository]# vi 1.txt

git is not a simple free software.

git is not a version control system.

zs is a good student

ls is a bad student

ww is a bad student too

my boss is a pig

[root@www repository]# git add 1.txt

[root@www repository]# git status

位于分支 master

要提交的变更:

  (使用 "git reset HEAD <文件>..." 以取消暂存)

修改:     1.txt

##庆幸的是,在commit之前,你发现了这个问题。用git status查看一下,修改只是添加到了暂存区,还没有提交:###

##可以用命令git reset HEAD <file>可以把暂存区的修改撤销掉(unstage),重新放回工作区:###

[root@www repository]# git reset HEAD 1.txt

重置后取消暂存的变更:

M 1.txt

[root@www repository]# git status

位于分支 master

尚未暂存以备提交的变更:

  (使用 "git add <文件>..." 更新要提交的内容)

  (使用 "git checkout -- <文件>..." 丢弃工作区的改动)

修改:     1.txt

修改尚未加入提交(使用 "git add" 和/或 "git commit -a")

[root@www repository]# git checkout -- 1.txt   ##运行命令进行工作区的修改###

[root@www repository]# git status

位于分支 master

无文件要提交,干净的工作区         ######整个世界终于清静了!#####

  • d删除文件

在Git中,删除也是一个修改操作,我们实战一下,先添加一个新文件test.txt到Git并且提交:

[root@www repository]# vi test.txt

你猜我猜不猜!

[root@www repository]# git add test.txt

[root@www repository]# git commit -m "caibucai"

[master 1498b57] caibucai

 1 file changed, 1 insertion(+)

 create mode 100644 test.txt

###一般情况下,你通常直接在文件管理器中把没用的文件删了,或者用rm命令删了:####

[root@www repository]# rm -rf test.txt

####这个时候,Git知道你删除了文件,因此,工作区和版本库就不一致了,git status命令会立刻告诉你哪些文件被删除了:###

[root@www repository]# git status

位于分支 master

尚未暂存以备提交的变更:

  (使用 "git add/rm <文件>..." 更新要提交的内容)

  (使用 "git checkout -- <文件>..." 丢弃工作区的改动)

删除:     test.txt

修改尚未加入提交(使用 "git add" 和/或 "git commit -a")

##现在你有两个选择,一是确实要从版本库中删除该文件,那就用命令git rm删掉,并且git commit###

[root@www repository]# git rm test.txt    ####小提示:先手动删除文件,然后使用git rm <file>和git add<file>效果是一样的。######

rm 'test.txt'

[root@www repository]# git commit -m "remove test.txt"

[master d3fea2b] remove test.txt

 1 file changed, 1 deletion(-)

 delete mode 100644 test.txt       ####现在,文件就从版本库中被删除了。###

##另一种情况是删错了,因为版本库里还有呢,所以可以很轻松地把误删的文件恢复到最新版本:###

[root@www repository]# git checkout -- test.txt

###git checkout其实是用版本库里的版本替换工作区的版本,无论工作区是修改还是删除,都可以“一键还原”。###

  • D  分支管理;

分支就是科幻电影里面的平行宇宙,当你正在电脑前努力学习Git的时候,另一个你正在另一个平行宇宙里努力学习SVN。

如果两个平行宇宙互不干扰,那对现在的你也没啥影响。不过,在某个时间点,两个平行宇宙合并了,结果,你既学会了Git又学会了SVN!

分支在实际中有什么用呢?假设你准备开发一个新功能,但是需要两周才能完成,第一周你写了50%的代码,如果立刻提交,由于代码还没写完,不完整的代码库会导致别人不能干活了。如果等代码全部写完再一次提交,又存在丢失每天进度的巨大风险。

现在有了分支,就不用怕了。你创建了一个属于你自己的分支,别人看不到,还继续在原来的分支上正常工作,而你在自己的分支上干活,想提交就提交,直到开发完毕后,再一次性合并到原来的分支上,这样,既安全,又不影响别人工作。

其他版本控制系统如SVN等都有分支管理,但是用过之后你会发现,这些版本控制系统创建和切换分支比蜗牛还慢,简直让人无法忍受,结果分支功能成了摆设,大家都不去用。

但Git的分支是与众不同的,无论创建、切换和删除分支,Git在1秒钟之内就能完成!无论你的版本库是1个文件还是1万个文件

创建和合并分支;

版本回退里,你已经知道,每次提交,Git都把它们串成一条时间线,这条时间线就是一个分支。截止到目前,只有一条时间线,在Git里,这个分支叫主分支,即master分支。HEAD严格来说不是指向提交,而是指向mastermaster才是指向提交的,所以,HEAD指向的就是当前分支。

一开始的时候,master分支是一条线,Git用master指向最新的提交,再用HEAD指向master,就能确定当前分支,以及当前分支的提交点:

每次提交,master分支都会向前移动一步,这样,随着你不断提交,master分支的线也越来越长:

当我们创建新的分支,例如dev时,Git新建了一个指针叫dev,指向master相同的提交,再把HEAD指向dev,就表示当前分支在dev上:

你看,Git创建一个分支很快,因为除了增加一个dev指针,改改HEAD的指向,工作区的文件都没有任何变化!

不过,从现在开始,对工作区的修改和提交就是针对dev分支了,比如新提交一次后,dev指针往前移动一步,而master指针不变:

假如我们在dev上的工作完成了,就可以把dev合并到master上。Git怎么合并呢?最简单的方法,就是直接把master指向dev的当前提交,就完成了合并:

所以Git合并分支也很快!就改改指针,工作区内容也不变!

合并完分支后,甚至可以删除dev分支。删除dev分支就是把dev指针给删掉,删掉后,我们就剩下了一条master分支:

下面开始实战。

首先,我们创建dev分支,然后切换到dev分支:

[root@www repository]# git checkout -b dev

切换到一个新分支 'dev'

git checkout命令加上-b参数表示创建并切换,相当于以下两条命令:

git branch dev

git checkout dev

git branch命令查看当前分支

[root@www repository]# git branch

* dev

  Master

git branch命令会列出所有分支,当前分支前面会标一个*号。

然后,我们就可以在dev分支上正常提交,比如对1.txt做个修改,加上一行:

[root@www repository]# vi 1.txt

git is not a simple free software.

git is not a version control system.

zs is a good student

ls is a bad student

addcess dev

然后提交:

[root@www repository]# git add 1.txt

[root@www repository]# git commit -m "dev laile"

[dev 5fe8e15] dev laile

 1 file changed, 1 insertion(+)

现在,dev分支的工作完成,我们就可以切换回master分支:

[root@www repository]# git checkout master

切换到分支 'master'

切换回master分支后,再查看一个readme.txt文件,刚才添加的内容不见了!因为那个提交是在dev分支上,而master分支此刻的提交点并没有变:

现在,我们把dev分支的工作成果合并到master分支上:

[root@www repository]# git merge dev

更新 d3fea2b..5fe8e15

Fast-forward

 1.txt | 1 +

 1 file changed, 1 insertion(+)

git merge命令用于合并指定分支到当前分支。合并后,再查看1.txt的内容,就可以看到,和dev分支的最新提交是完全一样的。

[root@www repository]# cat 1.txt

git is not a simple free software.

git is not a version control system.

zs is a good student

ls is a bad student

addcess dev

注意到上面的Fast-forward信息,Git告诉我们,这次合并是“快进模式”,也就是直接把master指向dev的当前提交,所以合并速度非常快。

当然,也不是每次合并都能Fast-forward,我们后面会讲其他方式的合并。

合并完成后,就可以放心地删除dev分支了:

[root@www repository]# git branch -d dev

已删除分支 dev(曾为 5fe8e15)。

###删除后,查看branch,就只剩下master分支了:###

[root@www repository]#  git branch

* master

因为创建、合并和删除分支非常快,所以Git鼓励你使用分支完成某个任务,合并后再删掉分支,这和直接在master分支上工作效果是一样的,但过程更安全。###

解决分支冲突;

准备新的try分支,继续我们的新分支开发:

[root@www repository]# git checkout -b try

切换到一个新分支 'try'

[root@www repository]# vi 1.txt  ###修改1.TXT文件###

git is not a simple free software.

git is not a version control system.

zs is a good student

ls is a bad student

addcess dev

addcess toy

[root@www repository]# git add 1.txt   ####在try分支上提交###

[root@www repository]# git commit -m "toy it"

[try 1f123e8] toy it

 1 file changed, 2 insertions(+), 1 deletion(-)

[root@www repository]# git checkout master   ###切换到主分支master###

切换到分支 'master'

[root@www repository]# cat 1.txt    ###修改1.TXT文件###

git is not a simple free software.

git is not a version control system.

zs is a good student

ls is a bad student

addcess dev

addcess tay

[root@www repository]# git add 1.txt    ##在主分支上提交1.TXT###

[root@www repository]# git commit -m "tay it"

[master 61817ac] tay it

 1 file changed, 1 insertion(+), 1 deletion(-)

现在,master分支和try分支各自都分别有新的提交,变成了这样:

这种情况下,Git无法执行“快速合并”,只能试图把各自的修改合并起来,但这种合并就可能会有冲突,我们试试看:

[root@www repository]# git merge try

自动合并 1.txt

冲突(内容):合并冲突于 1.txt

自动合并失败,修正冲突然后提交修正的结果。

###果然冲突了!Git告诉我们,1.txt文件存在冲突,必须手动解决冲突后再提交。git status也可以告诉我们冲突的文件:###

[root@www repository]# git status    ###查看状态,提示终止合并!###

位于分支 master

您有尚未合并的路径。

  (解决冲突并运行 "git commit")

  (使用 "git merge --abort" 终止合并)

未合并的路径:

  (使用 "git add <文件>..." 标记解决方案)

双方修改:   1.txt

修改尚未加入提交(使用 "git add" 和/或 "git commit -a")

[root@www repository]# cat 1.txt   ##查看1.TXT,发现有提示不同的地方###

git is not a simple free software.

git is not a version control system.

zs is a good student

ls is a bad student

addcess dev

<<<<<<< HEAD

addcess tay

=======

addcess toy



>>>>>>> try

Git用<<<<<<<,=======,>>>>>>>标记出不同分支的内容,我们修改如下后保存:

[root@www repository]# vi 1.txt



git is not a simple free software.

git is not a version control system.

zs is a good student

ls is a bad student

addcess dev

addcess tay

[root@www repository]# git add 1.txt   ###提交###

[root@www repository]# git commit -m "zuizhong"

[master 18dd3a0] zuizhong

现在,master分支和feature1分支变成了下图所示:

##用带参数的git log也可以看到分支的合并情况:###

[root@www repository]# git log --graph --pretty=oneline --abbrev-commit

*   18dd3a0 (HEAD -> master) zuizhong

|\  

| * 1f123e8 (try) toy it

* | 61817ac tay it

|/  

* dbbf718 try it

* 5fe8e15 dev laile

* d3fea2b remove test.txt

* 1498b57 caibucai

* ff917f2 ww is a bad student too

* dbe9d83 zs is an people

* 18169b6 liyu is very cool

* ed318f7 liyu change the file

* 5d661ed liyu write these file

* ae97fb0 liyu write it

###最后,删除feature1分支:###

[root@www repository]# git branch -d try

已删除分支 try(曾为 1f123e8)。

[root@www repository]# git branch -d try

已删除分支 try(曾为 1f123e8)。

分支管理策略:

通常,合并分支时,如果可能,Git会用Fast forward模式,但这种模式下,删除分支后,会丢掉分支信息。

如果要强制禁用Fast forward模式,Git就会在merge时生成一个新的commit,这样,从分支历史上就可以看出分支信息。

下面我们实战一下--no-ff方式的git merge

[root@www repository]# git checkout -b dev  ##首先,仍然创建并切换dev分支:##

切换到一个新分支 'dev'

[root@www repository]# vi 1.txt     ###修改1.txt文件,并提交一个新的commit:###

git is not a simple free software.

git is not a version control system.

zs is a good student

ls is a bad student

addcess dev

addcess tay

bk01    liyu

[root@www repository]# git add 1.txt

[root@www repository]# git commit -m "bk01 www"

[dev b683128] bk01 www

 1 file changed, 1 insertion(+)

[root@www repository]# git checkout master     ####现在,我们切换回master:##

切换到分支 'master'

[root@www repository]# git merge --no-ff -m "bk01 mmm" dev   ##准备合并dev分支,请注意--no-ff参数,表示禁用Fast forward:###

Merge made by the 'recursive' strategy.

 1.txt | 1 +

 1 file changed, 1 insertion(+)

##因为本次合并要创建一个新的commit,所以加上-m参数,把commit描述写进去。

合并后,我们用git log看看分支历史:##

[root@www repository]# git log --graph --pretty=oneline --abbrev-commit

*   c3f69d6 (HEAD -> master) bk01 mmm

|\  

| * b683128 (dev) bk01 www

|/  

*   18dd3a0 zuizhong

|\  

| * 1f123e8 toy it

* | 61817ac tay it

|/  

* dbbf718 try it

* 5fe8e15 dev laile

* d3fea2b remove test.txt

* 1498b57 caibucai

可以看到,不使用Fast forward模式,merge后就像这样:

策略1.master分支应该是非常稳定的,也就是仅用来发布新版本,平时不能在上面干活;

策略2.合并分支时,加上--no-ff参数就可以用普通模式合并,合并后的历史有分支,能看出来曾经做过合并,而fast forward合并就看不出来曾经做过合并

策略3.(团队合作)干活都在dev分支上,也就是说,dev分支是不稳定的,到某个时候,比如1.0版本发布时,再把dev分支合并到master上,在master分支发布1.0版本;

你和你的小伙伴们每个人都在dev分支上干活,每个人都有自己的分支,时不时地往dev分支上合并就可以了。

所以,团队合作的分支看起来就像这样

BUG 分支;

软件开发中,bug就像家常便饭一样。有了bug就需要修复,在Git中,由于分支是如此的强大,所以,每个bug都可以通过一个新的临时分支来修复,修复后,合并分支,然后将临时分支删除。

当你接到一个修复一个代号101的bug的任务时,很自然地,你想创建一个分支BUG-101来修复它,但是,等等,当前正在dev上进行的工作还没有提交:

修复bug时,我们会通过创建新的bug分支进行修复,然后合并,最后删除;

[root@www repository]# git checkout -b bug-101

切换到一个新分支 'bug-101'

[root@www repository]# vi 1.txt



git is not a simple free software.

git is not a version control system.

zs is a good student

ls is a bad student

addcess dev

addcess tay

bk001    liyu

[root@www repository]# git add 1.txt

[root@www repository]# git commit -m "bug-xiufu"

[bug-101 4bd36af] bug-xiufu

 1 file changed, 1 insertion(+), 1 deletion(-)

[root@www repository]# git checkout master

切换到分支 'master'

[root@www repository]# cat 1.txt

git is not a simple free software.

git is not a version control system.

zs is a good student

ls is a bad student

addcess dev

addcess tay

bk01    liyu

[root@www repository]# git merge --no-ff -m "bug-xiufu01" bug-101

Merge made by the 'recursive' strategy.

 1.txt | 2 +-

 1 file changed, 1 insertion(+), 1 deletion(-)

[root@www repository]# git log --graph --pretty=oneline --abbrev-commit

*   a961085 (HEAD -> master) bug-xiufu01

|\  

| * 4bd36af (bug-101) bug-xiufu

|/  

*   c3f69d6 bk01 mmm

|\  

| * b683128 (dev) bk01 www

|/  

*   18dd3a0 zuizhong

|\  

| * 1f123e8 toy it

* | 61817ac tay it

|/  

* dbbf718 try it

* 5fe8e15 dev laile

* d3fea2b remove test.txt

* 1498b57 caibucai

* ff917f2 ww is a bad student too

* dbe9d83 zs is an people

* 18169b6 liyu is very cool

* ed318f7 liyu change the file

* 5d661ed liyu write these file

* ae97fb0 liyu write it

[root@www repository]# cat 1.txt

git is not a simple free software.

git is not a version control system.

zs is a good student

ls is a bad student

addcess dev

addcess tay

bk001    liyu

###BUG修复成功####

如果,当前正在dev上进行的工作还没有提交:
[root@www repository]# git checkout dev

切换到分支 'dev'

[root@www repository]# vi 1.txt



git is not a simple free software.

git is not a version control system.

zs is a good student

ls is a bad student

addcess dev

addcess tay

bk01    liyu

i am busy

[root@www repository]# git status

位于分支 dev

尚未暂存以备提交的变更:

  (使用 "git add <文件>..." 更新要提交的内容)

  (使用 "git checkout -- <文件>..." 丢弃工作区的改动)

修改:     1.txt

修改尚未加入提交(使用 "git add" 和/或 "git commit -a")

并不是你不想提交,而是工作只进行到一半,还没法提交,预计完成还需1天时间。但是,必须在两个小时内修复该bug,怎么办?

幸好,Git还提供了一个stash功能,可以把当前工作现场“储藏”起来,等以后恢复现场后继续工作:

[root@www repository]# git stash

保存工作目录和索引状态 WIP on dev: b683128 bk01 www

##现在,用git status查看工作区,就是干净的(除非有没有被Git管理的文件),因此可以放心地创建分支来修复bug。##

[root@www repository]# git status

位于分支 dev

无文件要提交,干净的工作区

##首先确定要在哪个分支上修复bug,假定需要在master分支上修复,就从master创建临时分支:###

[root@www repository]# git checkout -b bug-102   ##创建新分支##

切换到一个新分支 'bug-102'

[root@www repository]# vi 1.txt   ###修改文件BUG##

git is not a simple free software.

git is not a version control system.

zs is a good student

ls is a bad student

addcess dev

addcess tay

bk0001    liyu

[root@www repository]# git add 1.txt     ###提交###

[root@www repository]# git commit -m "bug-102-xiufu"

[bug-102 037f3ca] bug-102-xiufu

 1 file changed, 1 insertion(+), 1 deletion(-)

[root@www repository]# git checkout mster

error: pathspec 'mster' did not match any file(s) known to git.

[root@www repository]# git checkout master   ###切换主分支,合并提交###

切换到分支 'master'

[root@www repository]# git merge --no-ff -m "bug-102-xiufu-hebin" bug-102

Merge made by the 'recursive' strategy.

 1.txt | 2 +-

 1 file changed, 1 insertion(+), 1 deletion(-)

[root@www repository]# cat 1.txt

git is not a simple free software.

git is not a version control system.

zs is a good student

ls is a bad student

addcess dev

addcess tay

bk0001    liyu

###太棒了,原计划两个小时的bug修复只花了5分钟!现在,是时候接着回到dev分支干活了!####

[root@www repository]# git checkout dev

切换到分支 'dev'

[root@www repository]# git status

位于分支 dev

无文件要提交,干净的工作区

[root@www repository]# git stash list   ###工作区是干净的,刚才的工作现场存到哪去了?用git stash list命令看看:###

stash@{0}: WIP on dev: b683128 bk01 www

[root@www repository]# git stash pop   ###一种方式是用git stash pop,恢复的同时把stash内容也删了###

位于分支 dev

尚未暂存以备提交的变更:

  (使用 "git add <文件>..." 更新要提交的内容)

  (使用 "git checkout -- <文件>..." 丢弃工作区的改动)

修改:     1.txt

修改尚未加入提交(使用 "git add" 和/或 "git commit -a")

丢弃了 refs/stash@{0} (74e2c222ebc6419c7b14e4bb832cc6d6218af685)

[root@www repository]# git stash list

[root@www repository]# git stash     

保存工作目录和索引状态 WIP on dev: b683128 bk01 www

[root@www repository]# git stash list   

stash@{0}: WIP on dev: b683128 bk01 www

[root@www repository]# git stash apply    ###用git stash apply恢复,但是恢复后,stash内容并不删除###

位于分支 dev

尚未暂存以备提交的变更:

  (使用 "git add <文件>..." 更新要提交的内容)

  (使用 "git checkout -- <文件>..." 丢弃工作区的改动)

修改:     1.txt

修改尚未加入提交(使用 "git add" 和/或 "git commit -a")

[root@www repository]# git stash list

stash@{0}: WIP on dev: b683128 bk01 www

[root@www repository]# git stash drop   ###用git stash drop来删除###

丢弃了 refs/stash@{0} (2995b85ff2dad93cea1375c0a48ff53165285b44)

[root@www repository]# git stash list

[root@www repository]#

小结

修复bug时,我们会通过创建新的bug分支进行修复,然后合并,最后删除;

当手头工作没有完成时,先把工作现场git stash一下,然后去修复bug,修复后,再git stash pop,回到工作现场。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值