Git版本管理工具

一、版本控制

1.1、本地版本控制

什么是“版本控制”?我为什么要关心它呢? 版本控制是一种记录一个或若干文件内容变化,以便将来查阅特定版本修订情况的系统。

许多人习惯用复制整个项目目录的方式来保存不同的版本,或许还会改名加上备份时间以示区别。 这么做唯一的好处就是简单,但是特别容易犯错。 有时候会混淆所在的工作目录,一不小心会写错文件或者覆盖意想外的文件。

如果你在学校写过毕业论文,那你一定遇见过这样的问题

一个论文翻来覆去的改,写一点觉得有问题,写一点还觉得有问题,还不容易写好了,导师还挑刺,还让你改。。。。。无穷无尽。。

  • 看着这一堆乱七八糟的文件,你自己也不记得,每一个文件到底写了什么内容,还得一个个看,想删又不敢删。。。
  • 当你写完了毕业论文,你还得用U盘拷给导师,或者发个邮件给他,但是你回家可能还得改论文,那你发给导师的论文和你本地最新的论文又不一致了。。

于是我们希望有一个软件,帮我们记录文件变动的操作,并且同事还能一起操作,不需要自己传输文件,想知道变动了什么,只需要去软件里看看,这是不是就非常nice了?

版本文件名用户说明日期
1 美国皇家大学毕业论文v1.doc jason01 论文初稿 7/12 10:38
2 美国皇家大学毕业论文v2.doc jason02 论文修改版 7/12 18:09
3 美国皇家大学毕业论文v3.doc tony01 tony帮我修改论文 7/13 9:51
4 美国皇家大学毕业论文v4.doc kevin01 kevin帮我修改论文 7/14 15:17

1.2、Git与SVN

svn是集中式版本管理控制,git是分布式管理控制。

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

集中式版本控制,典型代表SVN

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

而且如果集中式版本服务器宕机了,所有人都没法工作。

分布式版本控制,没有中央服务器的概念,每个人都有自己的版本库,因此每个人在工作时候,不需要联网,版本库本地即可管理。

既然每个人都是一个完整的版本库,同事之间如果需要协作开发,就需要找一个用于“交换文件”的中央服务器,这个服务器不存在也不影响大家干活,只是用于交换文件内容。

GIT最强大的功能还有分支管理,远甩SVN等软件。

 

 

三、Git的下载与配置

3.1、Git的windows下安装

官网地址:https://git-scm.com/download

下载到本地磁盘

一路【next】安装

 

安装完成后,右击菜单栏,有如下菜单,表示安装完成

进入git bash选项:

3.2、配置

1
git config -l

第一次使用git一般都需要配置git的用户名和邮箱,表明提交者的身份。

git config --global user.name 'jason'
git config --global user.email '18817628568@613.com'
git config --system --list # 查看系统配置
git config --global --list # 查看本地配置

四、Git核心

4.1、Git分区

4.2、文件状态

针对与文件所处的不同分区,文件所处的状态:

(1)未追踪, 文件第一次出现在工作区, 版本库还没有存储该文件的状态

(2)已追踪, 只要第一次git add了文件, 文件就是已追踪

(3)未修改, 文件在工作区未被编辑

(4)已修改, 文件在工作区被修改

(5)未暂存, 文件已修改, 但是没有add到暂存区

(6)已暂存, 已经将修改的文件add到暂存区

(7)未提交, 已暂存的文件, 没有commit提交. 处于暂存区

(8)已提交, 提交到版本库的文件修改,只有commit以后才会有仓库的版本号生成

查看仓库状态:

1
2
git status
git status –s # 简约显示
  • 红色表示新建文件或者新修改的文件,都在工作区. git add 执行之前的效果
  • 绿色表示文件在暂存区,git add 执行以后的效果

4.3、demo演示

(1)git init

在项目的根目录下初始化:git init得到.git文件夹(隐藏文件夹)

1
 git init .  # 如果没有声明目录,则自动把当前目录作为git仓库

查看仓库状态命令:

1
2
git status  # 查看状态
git status –s # 简约显示
  • 红色表示新建文件或者新修改的文件,都在工作区. git add 执行之前的效果
  • 绿色表示文件在暂存区,git add 执行以后的效果

在项目根目录下创建一个hello.py文件,然后查看仓库状态:

1
git status

(2)git add

1
2
git add .    # . 表示当前目录所有文件
git status  

(3)git commit

git commit -m “版本历史的介绍或者描述信息” # m是 message的缩写

注意:git add . 和 git commit -m 两条命令可以合并为:git commit -a -m “版本描述信息” # a是add的缩写

(4)修改文件

1
 git commit -a -m "第二次提交apple项目"

到这为止,所有的文件都在本地仓库!

五、远程仓库

5.1、ssh远程连接

5.1.1、ssh命令

ssh命令是openssh套件中的客户端连接工具,可以给予ssh加密协议实现安全的远程登录服务器,实现对服务器的远程管理。

简单说,SSH是一种网络协议,用于计算机之间的加密登录。如果一个用户从本地计算机,使用SSH协议登录另一台远程计算机,我们就可以认为,这种登录是安全的,即使被中途截获,密码也不会泄露。最早的时候,互联网通信都是明文通信,一旦被截获,内容就暴露无疑。1995年,芬兰学者Tatu Ylonen设计了SSH协议,将登录信息全部加密,成为互联网安全的一个基本解决方案,迅速在全世界获得推广,目前已经成为Linux系统的标准配置。

SSH(远程连接工具)连接原理:ssh服务是一个守护进程(demon),系统后台监听客户端的连接,ssh服务端的进程名为sshd,负责实时监听客户端的请求(IP 22端口),包括公共秘钥等交换等信息。

ssh服务端由2部分组成: openssh(提供ssh服务) openssl(提供加密的程序)

  1. 检查主机上有没有安装SSH服务,使用命令:ssh 若提示命令未找到,则需要安装ssh服务;步骤如下:输入sudo apt-get update命令以实现更新Ubuntu系统–>输入sudo apt-get install openssh-server命令以安装ssh 若输出ssh命令的使用说明,则代表已经安装了。
  2. 检查主机上有没有启动SSH服务,使用命令:service –status-all | grep ssh 若服务已经启动的话,可以看到[+] ssh 若服务还没启动的话,可以看到[-] ssh
  3. 启动ssh服务,使用命令sudo service sshd start

5.1.2、SSH远程登录之口令登录

1
ssh 用户名@IP地址 -p 端口号

SSH的默认端口是22

5.1.3、SSH远程登录之免密登录(密钥登录)

(1)客户端生成公私钥

ssh-keygen -t rsa

linux下:运行结束以后,在$HOME/.ssh/目录下,会新生成两个文件:id_rsa.pub和id_rsa。前者是你的公钥,后者是你的私钥。

如果是window:

(2)公钥传到连接服务器

方式1:命令操作:

1
2
3
4
5
使用模式:
       ssh-copy-id [-i [identity_file]] [user@]machine              // -i:指定公钥文件

把本地的ssh公钥文件安装到远程主机对应的账户下:
ssh-copy-id -i ~/.ssh/id_rsa.pub user@server

方式2(手动操作):

1
2
3
4
5
6
首先在主机A上执行命令 
scp .ssh/id_rsa.pub user@server:~/home
命令执行成功后会将主机A的公钥传到主机B的家目录里。
切换到主机B,命令行执行
cat ~/home/id_rsa.pub >> ~/.ssh/authorized_keys
将主机A的公钥添加到主机B的授权列表中。

5.2、远程仓库介绍

我们做开发的时候,写程序,可能会有多个⼈⼀起开发,或者你⾃⼰有多个电脑,家⾥⼀个电脑,办公 室⼀个电脑,但是你如果刚开始的代码都是在家⾥的电脑写的,然后你到了公司,你想继续开发你的程 序,那么就需要你⾃⼰来回的拷⻉⾃⼰的代码,并随身携带,⾮常麻烦,你说对不对,所以现在就出现 了代码⽹络托管站(就类似于⾏李托管站⼀样),可以帮你保存你的代码,以及各个版本的代码和所有分 ⽀,这样的话,你在家⾥开发完了之后,把代码放到托管站,就不⽤⾃⼰随身携带了,等你到了公司, 使⽤公司的电脑开发的时候,就可以直接通过⽹络托管站把⾃⼰已经开发好的代码拉下来到⾃⼰的本 机,然后继续开发,开发完了之后,在交给托管站托管,这样就⽅便多了,有很多这样的托管站,⽐如 今天我们要说的GIthub,码云,还有GitLab、开源中国、CSDN等都在做代码托管平台。

使⽤码云有这么⼏步:

  • 注册码云账号

  • 创建仓库
  • 本地代码推送到仓库

5.3、在gitee平台创建工程

(1)创建仓库

(2)仓库生成后的介绍

Git 全局设置:

1
2
git config --global user.name "jason先生"
git config --global user.email "18817628568@163.com"

创建 git 仓库:

1
2
3
4
5
6
7
8
mkdir pythonproject
cd pythonproject
git init 
touch README.md
git add README.md
git commit -m "first commit"
git remote add origin git@gitee.com:pythonjasonjy/pythonproject.git
git push -u origin "master"

已有仓库?

1
2
3
4
5
6
cd existing_git_repo
# git remote -v # 查看当前origin
# git remote remove  # 删除绑定origin
# git remote add origin git@gitee.com:pythonjason/apple-pro.git  // 配置密钥,免密登录
git remote add origin https://gitee.com/pythonjason/apple-pro.git  # 输入用户名密码
git push -u origin "master"
  1. 关联远程库:git remote add origin(可修改) branch_Name(为空时默认为master) url。关联之后可以用git remote -v 来检查是否关联成功

  2. push到远程库:git push -u origin master

  3. 当关联http方式时需要填用户名密码(如果在git bash中会将用户名密码配置在window凭据中,第二次则不需要再输入用户名密码,如果没有这个动作则需要每次登录都要重复输入用户名和密码),ssh方式需要密钥方式登录。

     

     

5.4、免密码登录

 

1
ssh-keygen

1、在C:\Users\Administrator\.ssh路径下生成公私钥文件

2、将公钥字符串注册到码云公钥位置

C:\Users\Administrator\.ssh中的id_rsa.pub的公钥拷贝到码云中的ssh的公钥中,标题会自动生成!

配置好之后在提交push命令就不需要单独输入码云的用户名和密码了。

 

六、分支管理

6.1、分支命令

分⽀可以给使⽤者提供多个开发环境,也就是说可以将你的⼯作从主线中分离出来,以免影响开发主 线,等分⽀的代码开发完之后,再合并到主线代码上。

1
2
3
4
5
6
7
8
9
git branch # 查看当前分⽀
git branch dev # 创建⼀个名为dev的分⽀
git checkout dev # 将⼯作切换到dev分⽀上
git checkout -b dev # 创建并切换到dev分⽀上,和上⾯两个指令的效果⼀样
git merge bug # 分⽀合并---⾸先切换到master分⽀,然后在master分⽀上执⾏merge指令来合并bug分⽀的代码
git branch -d bug  # 删除bug分⽀
git push origin --delete 分支  # 删除某远程分支

clear # 清除

(1)列出当前项目的所有分支

master是git默认的主分支,是默认提供的。

1
2
3
git branch  # 表示当前本地开发者看到的版本的分支
* master    
git branch -r # 远程分支

(2)创建并切换分支到dev

6.2、分支使用

 

创建项目文件夹:

初始化

创建并切换开发分支

dev分支下开发代码功能,修改html下的index.html文件

存档,切换回master分支

此时master分支并未同步上dev的代码,需要merge:

依赖master分支可以将代码部署上线,如果网站出现bug,接下来创建一个bug分支进行修复。

将h3标签改为h1标签

存档,并merge到master。

接下来想在dev分支上继续开发新的功能,发现index.html中还是之前的h3标签(bug依然存在在dev分支),需要将master分支同步过来:

 

6.3、版本日志

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
git log  
git reflog
 
# 分页展示日志
git log –p 
# 退出按【q】键
# ctrl+f 向下分页
# ctrl+b 向上分页

# 显示指定日期之后的日志   
git log --after  '2018-11-6'
# 显示指定日期之前的日志   
git log --before '2018-11-6'
# 指定显示指定开发者的日志  
git log --author 'lisi'

6.4、回退版本

方式1

  • HEAD表示当前最新版本
  • HEAD^表示当前最新版本的前一个版本
  • HEAD^^表示当前最新版本的前两个版本,以此类推…
  • HEAD~1表示当前最新版本的前一个版本
  • HEAD~10表示当前最新版本的前10个版本,以此类推…
1
git reset --hard HEAD^

方式2

当版本非常多时可选择的方案,通过每个版本的版本号回退到指定版本

1
  git reset --hard 版本号

七、拉取代码

1. git clone

git clone顾名思义就是将其他仓库克隆到本地,包括被clone仓库的版本变化。举个例子,你当前目录比方说是在e:/course/中,此时若想下载远程仓库,本地无需**git init**,直接git clone url(url是你远程仓库的地址,直接复制就可以了)。执行git clone等待clone结束,e:/course/目录下自动会有一个.git的隐藏文件夹(如果看不见,请尝试设置隐藏文件夹可见),因为是clone来的,所以.git文件夹里存放着与远程仓库一模一样的版本库记录。clone操作是一个从无到有的**克隆**操作,再次强调不需要git init初始化。

git clone的用法:

$ git clone <版本库的url>
1
git clone https://gitee.com/pythonjasonjy/pythonproject.git

或者使用SSH协议:

1
git clone git@gitee.com:pythonjasonjy/pythonproject.git

这样就会在本地生成一个目录,该目录与远程仓库同名。

However,如果本地目录不想与远程仓库同名怎么办??也有办法,将目录名作为git clone命令的第二个参数:

1
$ git clone <版本库的网址> <本地目录名>

2. git fetch 更新远程代码到本地仓库

理解 fetch 的关键, 是理解 FETCH_HEAD,FETCH_HEAD指的是: 某个branch在服务器上的最新状态’。这个列表保存在 .Git/FETCH_HEAD 文件中, 其中每一行对应于远程服务器的一个分支。当前分支指向的FETCH_HEAD, 就是这个文件第一行对应的那个分支. 一般来说, 存在两种情况:

  • 如果没有显式的指定远程分支, 则远程分支的master将作为默认的FETCH_HEAD
  • 如果指定了远程分支, 就将这个远程分支作为FETCH_HEAD

git fetch更新本地仓库的两种用法:

1
2
3
4
5
6
7
8
9
# 方法一
$ git fetch origin master                # 从远程的origin仓库的master分支下载代码到本地的origin maste
$ git log -p master.. origin/master      # 比较本地的仓库和远程参考的区别
$ git merge origin/master                # 把远程下载下来的代码合并到本地仓库,远程的和本地的合并
# 方法二
$ git fetch origin master:temp           # 从远程的origin仓库的master分支下载到本地并新建一个分支temp
$ git diff temp                          # 比较master分支和temp分支的不同
$ git merge temp                         # 合并temp分支到master分支
$ git branch -d temp                     # 删除temp

3. git pull

git pull是拉取远程分支更新到本地仓库的操作。比如远程仓库里的学习资料有了新内容,需要把新内容下载下来的时候,就可以使用git pull命令。事实上,git pull是相当于从远程仓库获取最新版本,然后再与本地分支merge(合并)。   即:git pull = git fetch + git merge

注:git fetch不会进行合并,执行后需要手动执行git merge合并,而git pull拉取远程分之后直接与本地分支进行合并。更准确地说,git pull是使用给定的参数运行git fetch,并调用git merge将检索到的分支头合并到当前分支中。

git pull的用法:

1
$ git pull <远程主机名> <远程分支名>:<本地分支名>

举例:将远程主机origin的master分支拉取过来,与本地的branchtest分支合并。

1
$ git pull origin master:branchtest

如果将冒号和后面的branchtest去掉,则表示将远程origin仓库的master分支拉取下来与本地当前分支合并。以上的git pull操作如果用git fetch来表示:

1
2
$ git fetch origin master:brantest
$ git merge brantest

相比起来,git fetch更安全也更符合实际要求,因为可以在merge前,我们可以查看更新情况,根据实际情况再决定是否合并。

八、基于IDEA的Git使用