1. 主要的两类版本控制模式
1.1 集中式控制(代表:SVN)
1.11 简介
- 有一台主要的服务器,所有的版本信息都保存在该服务器当中,每当有成员修改了项目,需要提交到服务器当中,另一个成员要使用项目时,需要从服务器当中下载最新的项目
1.12 优点
- 具有隐私性,当所有的项目信息只存在于服务器当中
- 易查看所有保存的版本信息
1.13 缺点
- 当服务器瘫痪或损坏时,就不能进行进行版本控制了,甚至可能导致数据丢失
- 当断网时,不可进行版本控制
1.2 分布式控制(代表:GIT)
1.21 简介
- 和集中式相反,每个成员都保存着所有的版本信息,每当有成员提交项目时,会先保存在本机上,然后再上传至主服务器和其他成员,而每当有成员要修改项目内容时,只需要在修改完本地的项目后相互推送给对方即可,就可以互相看到双方的修改了
1.22 优点
- 不易丢失数据,当主服务器或者成员电脑损坏后,可以直接从其他成员那备份到完成的数据过来
- 断网时仍然可以更新版本,因为所有的版本都在自己的电脑上了,不会因为暂时性没网而停止工作
1.23 缺点
- 容易导致隐私泄漏,因为每个成员的电脑上均保存着所有的版本信息,所以成员可以直接将电脑上的所有信息泄漏出去
2. GIT的环境安装
2.1 通过Homebrew安装
- 如果电脑有装homebrew的话,直接终端执行brew install git即可
2.2 官网下载安装包安装
- 官网链接:https://git-scm.com
-
-
3. GIT使用教程
3.1 介绍
- GIT有三种基本的操作方式
- Bash:Linux命令行
- Gui:图形操作界面
- CMD:Windows命令行
- 最方便且最通用的是Bash操作方式
3.2 GIT环境配置
-
# 查看当前用户的所有配置 git config -l # 查看本地系统配置 -- 系统自动配置的信息 git config --system --list # 查看本地用户配置 -- 用户自己配置的信息 git config --global --list # 设置用户配置 -- 因为在使用git提交项目时,其他成员需要知道是谁提交的 # 所以每个成员需要设置自己的用户名、邮箱 git config --global user.name "用户名" git config --global user.email "邮箱"
3.3 GIT基本理论
3.31 工作区域
- Git本地有三个工作区域:
- 工作区(Working Directory):平时存放项目代码的地方
- 暂存区(Stage/index):用于临时存放项目的改动,实际上只是一个文件,保存即将提交到文件列表信息
- 资源库(Git Directory):本地仓库,存放数据的地方,里面存放着提交到所有版本的数据,其中HEAD文件指向最新放入仓库的版本
- Git远程有一个工作区域:
- Git仓库(Remote Directory):像类似GitHub、Gitee等远程托管仓库,存放着我们推送上去的版本信息
3.32 工作流程
- 在工作区添加,修改文件
git add 文件 # 将工作区的文件放入暂存区
- 将需要进行版本管理的文件放入暂存区
git commit # 将暂存区文件提交到本地仓库
- 将暂存区的文件提交到本地仓库
git push # 将本地仓库文件推送到远程仓库
- 如果需要提交到远程仓库,则继续将本地仓库的数据提交到远程仓库进行托管
3.4 GIT仓库搭建
3.41 本地仓库搭建
- 用cd切换进工作目录
- 输入
git init
初始化工作区,会在工作目录中创建一个**.git**的隐藏文件
3.42 克隆远程仓库进本地
- 在GitHub/Gitee的仓库中,会有一个克隆按钮,复制其中的链接
-
- 利用cd切换进工作目录
- 使用如下命令将远程服务器上的仓库完全镜像一份到本地仓库中
git clone 在GitHub/Gitee上所复制的链接
3.43 克隆本地仓库到远程
-
使用
git remote add [远程名称] [仓库ssh链接]
来给当前仓库添加一个远程仓库并命名 -
使用
git remote
可查看当前仓库所绑定的所有远程仓库 -
使用
git push [-f] [--set-upstream] [远程名称] [本地分支名]:[远端分支名]
来将本地仓库的[本地分支名]推送至名为[远程名称]的远程仓库中的[远端分支名]里-f
:强制覆盖本地至远程(一般不使用)--set-upstream
:建立本地和远程分支的联系(若当前分支已经和远程关联,则可省去分支名和远程名,仅使用git push
即可)
-
例如:
git push --set-upstream origin main:main
(将本地的main分支推送至远程名为origin的远程仓库中,并将本地的main分支和远程的main分支所绑定,前一个main为本地分支名,后一个为远程分支名,若远程没有该分支,则会自动创建该分支) -
使用
git branch -vv
来显示分支关联情况(本地哪个分支和远程哪个分支关联起来了)
3.5 GIT文件操作
3.51 文件的四种状态
- 未跟踪(Untracked):文件在文件目录内,但并没有加到本地仓库中,所以不参与版本控制,可以通过
git add
将状态变成暂存状态 - 未修改(Unmodify):文件已入库,但是没有修改,即本地仓库内的文件快照与文件目录下的数据完全一致,因为我们进行版本控制的目的是为了控制每次所修改的文件,而文件若没有修改,就无需使用版本控制了,可以使用如下两种方法改变此状态
- 修改该文件,文件就会自动变成已修改状态
- 使用
git rm
进行移出本地仓库,则会变成未跟踪状态
- 已修改(Modified):文件已修改,但是还未进行其他操作,有以下操作改变此状态
- 使用
git add
将其放入暂存区,使其变成暂存状态 - 使用
git checkout
丢弃已修改的内容,将会返回成未修改状态
- 使用
- 暂存状态(Staged):当更新或修改完的要进行版本控制的文件后,文件则会变成暂存状态,有如下操作
- 执行
git commit
将已修改的文件同步至本地仓库,此时本地仓库的文件与本地目录的文件又变成一致的,此时本地的文件又会变成未修改状态 - 执行
git reset HEAD filename
取消保存本地仓库,文件状态为已修改
- 执行
3.52 文件操作
- 使用
git status
来查看文件状态- 当文件目录没有文件时,在终端中输入上述命令会显示如下信息
-
- 当在文件目录创建了一个未跟踪的文件hello.txt时
-
- 当将该文件用
git add .
添加进暂存区时,会显示 -
- 当使用
git commit -m
将文件提交至本地仓库中,会显示 -
- 当文件目录没有文件时,在终端中输入上述命令会显示如下信息
3.53 忽略文件
- 当我们不想提交某些文件进入仓库中时,可以在工作目录下建立**.gitignore**文件,该文件规则如下
- 忽略文件中以#或空格开头的行将被忽略
- 可以使用Linux通配符来忽略
- 例如:
*.txt # 忽略所有以.txt结尾的文件
- 例如:
- 在文件名前加!表示例外规则,该文件将不被忽略
!lib.txt # 该文件不会被忽略
- 文件名前加/表示该文件内除子目录以外的所有文件均忽略
- 例如有一个这样的文件结构
-
- 可以看到git_test_file里有一个文件hello.txt,和一个子目录lalala
- 当使用
/git_test_file
的时候,只会忽略hello.txt,而不会忽略lalala子目录里的内容
- 文件名后加/忽略目录下所有文件
git_test_file/ # 会忽略该目录下的所有文件,包括子目录
- 上述操作可以嵌套使用
doc/*.txt # 忽略doc目录下的所有以.txt结尾的文件
3.54 查看日志
- 当我们想查看过去所提交的修改记录,可以使用
git log
来查看- options
--all
: 显示所有分支--pretty=oneline
: 将提交信息显示为一行--abbrev-commit
: 使得输出的commit ID更简短--graph
: 以图的形式显示
- options
3.55 版本回退
- 用于切换版本,比如修改过后还是觉得以前的版本好,就可以使用版本回退
- 使用
git reset --hard <commit ID>
来切换至commit ID所提交的版本 - 如果对回退的操作不满意的话,也可使用
git reflog
来查看已经删除的操作
3.6 使用远程仓库(以码云为例)
3.61 实现免密码登陆
- 设置本地绑定SSH公钥
- 首先进入本地的**.ssh**目录,MacOs在
/Users/用户名/.ssh
下 - 生成公钥,在终端中输入
ssh-keygen
,若想加密自己的公钥,可以输入ssh-keygen -t rsa
- 生成公钥后,会在**.ssh**下生成两个文件,id_rsa是私钥,id_rsa.pub为公钥
-
- 将刚生成的公钥打开,将里面的内容复制到码云信息当中去
-
- 添加完成后在当前页面出现已绑定的公钥,到这步就完成了本机仓库与远程仓库之间的免密码登陆
-
3.62 远程仓库操作
- 新建远程仓库
-
-
- 创建完远程仓库后将本地仓库链接到远程仓库
git clone 远程仓库链接
见3.42
3.7 GIT分支
3.71 简介
- 每个项目都有一个主分支,一般设置成master或main
-
- 如上图所示,该项目有6个分支,分支可以用来当作某个大版本,比如你想要你的项目有版本1版本2等等,就可以弄出两个版本分支
3.72 分支命令
-
# 列出所有本地分支 git branch # 列出远程所有分支 git branch -r # 新建一个分支,但还是停留在原分支 git branch [branch-name] # 新建一个分支,并切换至该分支 git branch -b [branch-name] # 合并指定分支到当前分支 git merge [branch-name] # 删除本地分支 git branch -d [branch-name] # 删除远程分支 git push origin --delete [branch-name] git branch -dr [remote/branch] # 切换分支 git checkout [branch-name]
3.73 分支冲突
- 当多个分支存在冲突时,比如存在两个分支,A分支和B分支,B分支上的程序需要用到A分支的内容,于是就将A分支拉取下来合并到了B分支中,而且在使用A分支内容的时候,又修改了A分支的数据,而在这个时候,A分支的开发者又在A上修改了一定的数据,从而导致了仓库不知道保存哪个开发者的信息了,这就是冲突
- 解决办法:我们可以互相协商后,然后修改冲突文件重新提交即可,比如是保存A所修改的内容还是B所修改的内容
- 一般在开发的时候,主分支应该保持稳定的状态,所以一般不在主分支上进行工作,会创建其他的分支进行工作,当在其他的分支完成工作后且测试温度后,再将其和主分支进行合并发布
4. IDEA中集成GIT操作(PyCharm)
4.1 新建项目并绑定GIT
- 用pycharm把项目创建在工作区内
-
- 打开远程仓库所克隆的本地项目目录,将该目录下所有文件替换拷贝进pycharm所创建的项目目录内即可完成Git绑定(包括隐藏文件,Mac上用“command+shift+.”显示隐藏文件)
4.2 使用PyCharm操作GIT
- 一般的IDEA都会嵌入Git操作,PyCharm如下图所示
-
- 版本控制按钮可以看到仓库的所有进行过的操作
-
- 然后就可以进行Git操作了
- 可以直接在pycharm里的终端输入命令来提交推送
- 也可以手动点击按钮来提交推送
5. GitLab(自建代码托管平台)
5.1介绍
- GitLab是一个自建代码托管平台,可以安装在自己服务器当中,效果类似于GitHub/Gitee,只不过GitHub/Gitee是他人代码平台
5.2 如何安装
5.21 服务器准备
GIT命令快查表
仓库
# 在当前目录新建一个Git代码库
$ git init
# 新建一个目录,将其初始化为Git代码库
$ git init [project-name]
# 下载一个项目和它的整个代码历史
$ git clone [url]
配置
# 显示当前的Git配置
$ git config --list
# 编辑Git配置文件
$ git config -e [--global]
# 设置提交代码时的用户信息
$ git config [--global] user.name "[name]"
$ git config [--global] user.email "[email address]"
增加/删除文件
# 添加指定文件到暂存区
$ git add [file1] [file2] ...
# 添加指定目录到暂存区,包括子目录
$ git add [dir]
# 添加当前目录的所有文件到暂存区
$ git add .
# 添加每个变化前,都会要求确认
# 对于同一个文件的多处变化,可以实现分次提交
$ git add -p
# 删除工作区文件,并且将这次删除放入暂存区
$ git rm [file1] [file2] ...
# 停止追踪指定文件,但该文件会保留在工作区
$ git rm --cached [file]
# 改名文件,并且将这个改名放入暂存区
$ git mv [file-original] [file-renamed]
代码提交
# 提交暂存区到仓库区
$ git commit -m [message]
# 提交暂存区的指定文件到仓库区
$ git commit [file1] [file2] ... -m [message]
# 提交工作区自上次commit之后的变化,直接到仓库区
$ git commit -a
# 提交时显示所有diff信息
$ git commit -v
# 使用一次新的commit,替代上一次提交
# 如果代码没有任何新变化,则用来改写上一次commit的提交信息
$ git commit --amend -m [message]
# 重做上一次commit,并包括指定文件的新变化
$ git commit --amend [file1] [file2] ...
分支
# 列出所有本地分支
$ git branch
# 列出所有远程分支
$ git branch -r
# 列出所有本地分支和远程分支
$ git branch -a
# 新建一个分支,但依然停留在当前分支
$ git branch [branch-name]
# 新建一个分支,并切换到该分支
$ git checkout -b [branch]
# 新建一个分支,指向指定commit
$ git branch [branch] [commit]
# 新建一个分支,与指定的远程分支建立追踪关系
$ git branch --track [branch] [remote-branch]
# 切换到指定分支,并更新工作区
$ git checkout [branch-name]
# 切换到上一个分支
$ git checkout -
# 建立追踪关系,在现有分支与指定的远程分支之间
$ git branch --set-upstream [branch] [remote-branch]
$ git branch --set-upstream-to=[remote-branch] [branch]
# 合并指定分支到当前分支
$ git merge [branch]
# 选择一个commit,合并进当前分支
$ git cherry-pick [commit]
# 删除分支
$ git branch -d [branch-name]
# 删除远程分支
$ git push origin --delete [branch-name]
$ git branch -dr [remote/branch]
标签
# 列出所有tag
$ git tag
# 新建一个tag在当前commit
$ git tag [tag]
# 新建一个tag在指定commit
$ git tag [tag] [commit]
# 删除本地tag
$ git tag -d [tag]
# 删除远程tag
$ git push origin :refs/tags/[tagName]
# 查看tag信息
$ git show [tag]
# 提交指定tag
$ git push [remote] [tag]
# 提交所有tag
$ git push [remote] --tags
# 新建一个分支,指向某个tag
$ git checkout -b [branch] [tag]
查看信息
# 显示有变更的文件
$ git status
# 显示当前分支的版本历史
$ git log
# 显示commit历史,以及每次commit发生变更的文件
$ git log --stat
# 搜索提交历史,根据关键词
$ git log -S [keyword]
# 显示某个commit之后的所有变动,每个commit占据一行
$ git log [tag] HEAD --pretty=format:%s
# 显示某个commit之后的所有变动,其"提交说明"必须符合搜索条件
$ git log [tag] HEAD --grep feature
# 显示某个文件的版本历史,包括文件改名
$ git log --follow [file]
$ git whatchanged [file]
# 显示指定文件相关的每一次diff
$ git log -p [file]
# 显示过去5次提交
$ git log -5 --pretty --oneline
# 显示所有提交过的用户,按提交次数排序
$ git shortlog -sn
# 显示指定文件是什么人在什么时间修改过
$ git blame [file]
# 显示暂存区和工作区的差异
$ git diff
# 显示暂存区和上一个commit的差异
$ git diff --cached [file]
# 显示工作区与当前分支最新commit之间的差异
$ git diff HEAD
# 显示两次提交之间的差异
$ git diff [first-branch]...[second-branch]
# 显示今天你写了多少行代码
$ git diff --shortstat "@{0 day ago}"
# 显示某次提交的元数据和内容变化
$ git show [commit]
# 显示某次提交发生变化的文件
$ git show --name-only [commit]
# 显示某次提交时,某个文件的内容
$ git show [commit]:[filename]
# 显示当前分支的最近几次提交
$ git reflog
远程同步
# 下载远程仓库的所有变动
$ git fetch [remote]
# 显示所有远程仓库
$ git remote -v
# 显示某个远程仓库的信息
$ git remote show [remote]
# 增加一个新的远程仓库,并命名
$ git remote add [shortname] [url]
# 取回远程仓库的变化,并与本地分支合并
$ git pull [remote] [branch]
# 上传本地指定分支到远程仓库
$ git push [remote] [branch]
# 强行推送当前分支到远程仓库,即使有冲突
$ git push [remote] --force
# 推送所有分支到远程仓库
$ git push [remote] --all
撤销
# 恢复暂存区的指定文件到工作区
$ git checkout [file]
# 恢复某个commit的指定文件到暂存区和工作区
$ git checkout [commit] [file]
# 恢复暂存区的所有文件到工作区
$ git checkout .
# 重置暂存区的指定文件,与上一次commit保持一致,但工作区不变
$ git reset [file]
# 重置暂存区与工作区,与上一次commit保持一致
$ git reset --hard
# 重置当前分支的指针为指定commit,同时重置暂存区,但工作区不变
$ git reset [commit]
# 重置当前分支的HEAD为指定commit,同时重置暂存区和工作区,与指定commit一致
$ git reset --hard [commit]
# 重置当前HEAD为指定commit,但保持暂存区和工作区不变
$ git reset --keep [commit]
# 新建一个commit,用来撤销指定commit
# 后者的所有变化都将被前者抵消,并且应用到当前分支
$ git revert [commit]
暂时将未提交的变化移除,稍后再移入
$ git stash
$ git stash pop
其他
# 生成一个可供发布的压缩包
$ git archive