文章对应教程:https://www.bilibili.com/video/BV1vy4y1s7k6
CVS、SVN(Subversion)、VSS
集中化的版本控制系统诸如 CVS、SVN 等,都有一个单一的集中管理的服务器,保存所有文件的修订版本,而协同工作的人们都通过客户端连到这台服务器,取出最新的文件或者提交更新。多年以来,这已成为版本控制系统的标准做法。
这种做法带来了许多好处,每个人都可以在一定程度上看到项目中的其他人正在做些什
么。管理员也可以轻松掌控每个开发者的权限,并且管理一个集中化的版本控制系统,要远比在各个客户端上维护本地数据库来得轻松容易。
事分两面,有好有坏。这么做显而易见的缺点是中央服务器的单点故障。如果服务器宕机一小时,那么在这一小时内,谁都无法提交更新,也就无法协同工作。
Git、Mercurial、Bazaar、Darcs…
像Git这种分布式版本控制工具,客户端提取的不是最新版本的文件快照,而是把代码仓库完整地镜像下来(本地库)。这样任何一处协同工作用的文件发生故障,事后都可以用其他客户端的本地仓库进行恢复。因为每个客户端的每一次文件提取操作,实际上都是一次对整个文件仓库的完整备份。
分布式的版本控制系统出现之后,解决了集中式版本控制系统的缺陷:
服务器断网的情况下也可以进行开发(因为版本控制是在本地进行的)
每个客户端保存的也都是整个完整的项目(包含历史记录,更加安全)
代码托管中心是基于网络服务器的远程代码仓库,一般我们简单称为远程库。
局域网中
GitLab
互联网中(广域网)
GitHub(国外网站)
Gitee 码云(国内网站
官网地址:Git 下载
右键任意位置,在右键菜单里选择 Git Bash Here 即可打开 Git Bash 命令行终端。
在 Git Bash 终端里输入 git --version 查看 git 版本,如下图所示,说明 Git 安装成功
命令 | 功能 |
---|---|
git config --global user.name 用户名 | 设置用户签名用户名 |
git config --global user.name 用户名 | 设置用户签名邮箱 |
git init | 初始化本地仓库 |
git status | 查看本地库状态 |
git add 文件名称 | 添加到暂存区 |
git commit -m “日志信息” 文件名 | 提交到本地库 |
git reflog | 查看历史记录 |
git reset --hard 版本号 | 版本穿梭 |
git config --global user.name 用户名
git config --global user.email 邮箱
# 设置用户名为Bear
git config --global user.name Bear
# 设置用户邮箱为 [email protected]
git config --global user.email [email protected]
PS: **签名的作用是区分不同操作者身份。用户的签名信息在每一个版本的提交信息中能够看到,以此确认本次提交是谁做的。**Git 首次安装必须设置一下用户签名,否则无法提交代码。
git init
代码示例
在D盘下的demo文件夹中初始化本地库
Bear@Xans MINGW64 /d/demo
$ git init
Initialized empty Git repository in D:/demo/.git/ # 表示初始化了一个空的git仓库
git status
代码演示
查看D盘的demo仓库状态(空目录则显示未提交未跟踪状态)
Bear@Xans MINGW64 /d/demo (master)
$ git status
On branch master # 在主分支上
No commits yet # 表示还没有提交
nothing to commit (create/copy files and use "git add" to track) # 没有被提交和跟踪的文件
Bear@Xans MINGW64 /d/demo (master)
$ vim 1.txt
# 添加以下内容
Hello China
Hello China
Hello China
Bear@Xans MINGW64 /d/demo (master)
$ git status
On branch master
No commits yet
Untracked files: # 显示未被跟踪的文件
(use "git add ..." to include in what will be committed)
1.txt
nothing added to commit but untracked files present (use "git add" to track)
git add 文件名称
Bear@Xans MINGW64 /d/demo (master)
$ git add 1.txt
warning: LF will be replaced by CRLF in 1.txt. # 警告信息
The file will have its original line endings in your working directory
Bear@Xans MINGW64 /d/demo (master)
$ git status
On branch master
No commits yet
Changes to be committed:
(use "git rm --cached ..." to unstage)
new file: 1.txt # 被提交到暂存区的新文件
基本语法
git commit -m “日志信息” 文件名
代码示例
Bear@Xans MINGW64 /d/demo (master)
$ git commit -m "my first commit" 1.txt # 提交1.txt文件
warning: LF will be replaced by CRLF in 1.txt.
The file will have its original line endings in your working directory
[master (root-commit) a0f668a] my first commit # 备注的提交信息
1 file changed, 3 insertions(+)
create mode 100644 1.txt
Bear@Xans MINGW64 /d/demo (master)
$ git status
On branch master
nothing to commit, working tree clean
将已提交的文件内容进行修改,在这之后仍需将其添加到暂存区,并且再进行提交操作。
Bear@Xans MINGW64 /d/demo (master)
$ vim 1.txt
Hello China
Hello China
Hello China
Hello Bear # 新增这一行内容
Bear@Xans MINGW64 /d/demo (master)
$ git status
On branch master
Changes not staged for commit:
(use "git add ..." to update what will be committed)
(use "git restore ..." to discard changes in working directory)
modified: 1.txt
no changes added to commit (use "git add" and/or "git commit -a")
Bear@Xans MINGW64 /d/demo (master)
$ git add 1.txt
warning: LF will be replaced by CRLF in 1.txt.
The file will have its original line endings in your working directory
Bear@Xans MINGW64 /d/demo (master)
$ git status
On branch master
Changes to be committed:
(use "git restore --staged ..." to unstage)
modified: 1.txt
将修改过的文件提交到本地库,这时会将修改的内容增加。
Bear@Xans MINGW64 /d/demo (master)
$ git commit -m "second commit" 1.txt
warning: LF will be replaced by CRLF in 1.txt.
The file will have its original line endings in your working directory
[master c430c84] second commit
1 file changed, 1 insertion(+)
基本语法
git reflog # 查看版本信息
git log # 查看版本详细信息
代码演示
首先查看本地库的历史版本
Bear@Xans MINGW64 /d/demo (master)
$ git reflog
c430c84 (HEAD -> master) HEAD@{0}: commit: second commit # 指针指向了第二次提交的版本
a0f668a HEAD@{1}: commit (initial): my first commit
git版本穿梭指的是可以在提交了多个版本的文件中自由的切换。
基本语法
git reset --hard 版本号
代码演示
使用命令切换到第一个提交的版本文件中去。
Bear@Xans MINGW64 /d/demo (master)
$ git reflog
c430c84 (HEAD -> master) HEAD@{0}: commit: second commit # 第二次提交的版本
a0f668a HEAD@{1}: commit (initial): my first commit # 第一次提交的文件版本
Bear@Xans MINGW64 /d/demo (master)
$ git reset --hard a0f668a # 穿梭回到第一次提交的版本
HEAD is now at a0f668a my first commit
Bear@Xans MINGW64 /d/demo (master)
$ git reflog
a0f668a (HEAD -> master) HEAD@{0}: reset: moving to a0f668a
c430c84 HEAD@{1}: commit: second commit
a0f668a (HEAD -> master) HEAD@{2}: commit (initial): my first commit # 指针已经指向了第一次提交的版本
Bear@Xans MINGW64 /d/demo (master)
$ cat 1.txt # 此时查看文件内容,发现已经切换到第一个版本文件添加的内容中去了。
Hello China
Hello China
Hello China
Git 切换版本,底层其实是移动的 HEAD 指针,具体原理如下图所示。
在版本控制过程中,同时推进多个任务,为每个任务,我们就可以创建每个任务的单独分支。使用分支意味着程序员可以把自己的工作从开发主线上分离开来,开发自己分支的时候,不会影响主线分支的运行。对于初学者而言,分支可以简单理解为副本,一个分支就是一个单独的副本。(分支底层其实也是指针的引用)
命令 | 作用 |
---|---|
git branch 分支名称 | 创建分支 |
git branch -v | 查看分支 |
git checkout 分支名称 | 切换分支 |
git merge 分支名称 | 把指定的分支合并到当前分支上 |
基本语法
git branch -v
代码示例
Bear@Xans MINGW64 /d/demo (master)
$ git branch -v
* master a0f668a my first commit # 指向当前所在的分支
基本语法
git branch 分支名
代码示例
Bear@Xans MINGW64 /d/demo (master)
$ git branch -v
hot-fix a0f668a my first commit # 创建了一个hot-fix分支
* master a0f668a my first commit
git checkout 分支名称
Bear@Xans MINGW64 /d/demo (master)
$ git checkout hot-fix
Switched to branch 'hot-fix' # 切换到了hot-fix分支上
Bear@Xans MINGW64 /d/demo (hot-fix)
$ vim 1.txt
Hello China
Hello China
Hello China
111 # 在hot-fix分支上添加这一行内容
Bear@Xans MINGW64 /d/demo (hot-fix)
$ git add 1.txt # 添加到暂存区
Bear@Xans MINGW64 /d/demo (hot-fix)
$ git commit -m "third commit in hot-fix" 1.txt # 在hot-fix分支上提交这个文件到本地库
[hot-fix 88a1225] third commit in hot-fix
1 file changed, 2 insertions(+)
Bear@Xans MINGW64 /d/demo (hot-fix)
$ git checkout master
Switched to branch 'master'
Bear@Xans MINGW64 /d/demo (master)
$ cat 1.txt # 查看master分支上的1.txt文件,两个分支的内容不同。
Hello China
Hello China
Hello China
在不同的分支上对文件做修改会有不同的显示结果,这时就需要进行分支内容的合并操作。
git merge 分支名
代码示例
在master分支上合并新建的hot-fix分支
Bear@Xans MINGW64 /d/demo (master)
$ git merge hot-fix # 将hot-fix分支合并到master主分支上。
Updating a0f668a..88a1225
Fast-forward
1.txt | 2 ++
1 file changed, 2 insertions(+)
分支的合并会将内容同步到被合并的分支上。
在两个分支中修改同一个文件同一个位置时,进行合并会产生冲突的现象,git无法确定使用哪一个分支的内容。
代码示例
首先修改master分支所在的1.txt文件
Bear@Xans MINGW64 /d/demo (master)
$ vim 1.txt # 使用vim打开
Hello China
Hello China
Hello China
111 master test # 在这一行添加上master test 内容
Bear@Xans MINGW64 /d/demo (master)
$ git add 1.txt # 将修改后的文件添加到暂存区
Bear@Xans MINGW64 /d/demo (master)
$ git commit -m "master test" 1.txt # 将修改后的文件提交到本地库。
[master 744007b] master test
1 file changed, 1 insertion(+), 1 deletion(-)
Bear@Xans MINGW64 /d/demo (master)
$ git checkout hot-fix # 切换到hot-fix分支下
Switched to branch 'hot-fix'
Bear@Xans MINGW64 /d/demo (hot-fix)
$ vim 1.txt # 使用vim打开hot-fix分支下的1.txt文件
Hello China
Hello China
Hello China
111 hot-fix test # 在这一行添加上 hot-fix test 内容
Bear@Xans MINGW64 /d/demo (hot-fix)
$ git add 1.txt # 添加到暂存区
Bear@Xans MINGW64 /d/demo (hot-fix)
$ git commit -m "hot-fix test" 1.txt # 提交修改后的文件到本地库
[hot-fix 11f9851] hot-fix test
1 file changed, 1 insertion(+), 1 deletion(-)
Bear@Xans MINGW64 /d/demo (hot-fix)
$ git checkout master
Switched to branch 'master'
Bear@Xans MINGW64 /d/demo (master)
$ git merge hot-fix # 合并hot-fix分支到master分支上
Auto-merging 1.txt
CONFLICT (content): Merge conflict in 1.txt # 报错信息,表示合并分支失败
Automatic merge failed; fix conflicts and then commit the result.
通过手动修改文件的方式去解决冲突,决定要合并的内容
Bear@Xans MINGW64 /d/demo (master|MERGING)
$ vim 1.txt # 在master分支打开1.txt文件
Hello China
Hello China
Hello China
<<<<<<< HEAD # 删除掉这一行
111 master test
======= # 删除掉这一行
111 hot-fix test
>>>>>>> hot-fix # 删除掉这一行
**特殊符号表示:<<<<<<< HEAD 是当前分支的代码 ======= 下面是合并过来的代码 >>>>>>> hot-fix**
Bear@Xans MINGW64 /d/demo (master|MERGING)
$ git add 1.txt
Bear@Xans MINGW64 /d/demo (master|MERGING)
$ git commit -m "merge hot-fix"
[master 7bf7b73] merge hot-fix # 显示已合并
master、hot-fix 其实都是指向具体版本记录的指针。当前所在的分支,其实是由 HEAD决定的。
**所以创建分支的本质就是多创建一个指针。
****HEAD 如果指向 master,那么我们现在就在 master 分支上。
**HEAD 如果执行 hotfix,那么我们现在就在 hotfix 分支上
所以切换分支的本质就是移动 HEAD 指针。
GitHub 网址:https://github.com/
New repository
命令 | 作用 |
---|---|
git remote -v | 查看当前所有远程地址别名 |
git remote add 别名 远程地址 | 起别名 |
git push 别名 分支 | 推送本地分支到远程仓库中 |
git clone 远程地址 | 将远程仓库的内容克隆到本地 |
git pull 远程仓库地址别名 | 将远程仓库分支的最细内容拉去到本地与当前本地分支合并 |
**git remote -v 查看当前所有远程地址别名
**git remote add 别名 远程地址
代码演示
给https://github.com/BearPessimist/git-test.git
远程仓库创建一个别名
Bear@Xans MINGW64 /d/demo (master)
$ git remote add git-demo https://github.com/BearPessimist/git-test.git
Bear@Xans MINGW64 /d/demo (master)
$ git remote -v
git-demo https://github.com/BearPessimist/git-test.git (fetch) # 这个表示用来拉取
git-demo https://github.com/BearPessimist/git-test.git (push) # 这个表示用于推送
git push 别名 分支
代码示例
将本地仓库分支推送到Github远程库
Bear@Xans MINGW64 /d/demo (master)
$ git push git-demo master # 推送master分支到以git-demo别名的远程仓库中
Enumerating objects: 15, done.
Counting objects: 100% (15/15), done.
Delta compression using up to 8 threads
Compressing objects: 100% (8/8), done.
Writing objects: 100% (15/15), 1.11 KiB | 161.00 KiB/s, done.
Total 15 (delta 1), reused 0 (delta 0), pack-reused 0
remote: Resolving deltas: 100% (1/1), done.
To https://github.com/BearPessimist/git-test.git
* [new branch] master -> master
在远程库的分支内容和本地库不相同时,可以命令进行双方的同步
git pull 远程库地址 分支名称
示例
修改远程库的文件内容
Bear@Xans MINGW64 /d/demo (master)
$ cat 1.txt
Hello China
Hello China
Hello China
111 master test
111 hot-fix test
============= 上面是没有拉取同步之前的内容 ==============
Bear@Xans MINGW64 /d/demo (master)
$ git pull git-demo master # 拉取别名为git-demo远程库的内容到本地master分支上。
remote: Enumerating objects: 5, done.
remote: Counting objects: 100% (5/5), done.
remote: Compressing objects: 100% (2/2), done.
remote: Total 3 (delta 0), reused 0 (delta 0), pack-reused 0
Unpacking objects: 100% (3/3), 650 bytes | 34.00 KiB/s, done.
From https://github.com/BearPessimist/git-test
* branch master -> FETCH_HEAD
7bf7b73..d9f8975 master -> git-demo/master
Updating 7bf7b73..d9f8975
Fast-forward
1.txt | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
============= 下面是拉取同步之后的内容 ==============
Bear@Xans MINGW64 /d/demo (master)
$ cat 1.txt
Hello China
Hello China
Hello China
master test
hot-fix test
git clone 远程库地址
代码演示
在D:\demo\clone_file 目录下克隆https://github.com/BearPessimist/git-test.git
远程库的内容.
Bear@Xans MINGW64 /d/demo/clone_file (master)
$ git clone https://github.com/BearPessimist/git-test.git
Cloning into 'git-test'...
remote: Enumerating objects: 18, done.
remote: Counting objects: 100% (18/18), done.
remote: Compressing objects: 100% (9/9), done.
remote: Total 18 (delta 1), reused 15 (delta 1), pack-reused 0
Receiving objects: 100% (18/18), done.
Resolving deltas: 100% (1/1), done.
PS:clone会进行如下操作:
通过邀请其它GitHub用户一起参与到项目的开发
在Bears521这个账号输入邀请链接的时候,就可以点击接受邀请参与团队协作。
Bear@Xans MINGW64 /d/demo (master)
$ git push https://github.com/BearPessimist/git-test.git master
warning: ----------------- SECURITY WARNING ----------------
warning: | TLS certificate verification has been disabled! |
warning: ---------------------------------------------------
warning: HTTPS connections may not be secure. See https://aka.ms/gcmcore-tlsverify for more information.
warning: ----------------- SECURITY WARNING ----------------
warning: | TLS certificate verification has been disabled! |
warning: ---------------------------------------------------
warning: HTTPS connections may not be secure. See https://aka.ms/gcmcore-tlsverify for more information.
Enumerating objects: 8, done.
Counting objects: 100% (8/8), done.
Delta compression using up to 8 threads
Compressing objects: 100% (4/4), done.
Writing objects: 100% (6/6), 473 bytes | 236.00 KiB/s, done.
Total 6 (delta 2), reused 0 (delta 0), pack-reused 0
remote: Resolving deltas: 100% (2/2), completed with 1 local object.
To https://github.com/BearPessimist/git-test.git
f6b4aeb..3cacf40 master -> master
PS:以上推送的用户是用的被邀请方Bears521操作的,因为这个用户被添加进了仓库的团队协同开发。
将别人的项目fork一份到自己的本地库,进行修改和提交的操作。
BearPessimist
用户下的git-test库到自己的本地库中图中forked form … 说明是从BearPessimist用户中叉入过来的仓库。
在idea中配置Git程序的安装目录
在 IDEA 的左下角点击 Version Control,然后点击 Log 查看版本
右键选择要切换的版本,然后在菜单里点击 Checkout Revision。
选择 Git,在 Repository 里面,点击 Branches 按钮。
在弹出的 Git Branches 框里,点击 New Branch 按钮。
填写分支名称,创建 hot-fix 分支。
**然后再 IDEA 的右下角看到 hot-fix,说明分支创建成功,并且当前已经切换成 hot-fix 分支
在 IDEA 窗口的右下角,切换到 master 分支
在 IDEA 窗口的右下角,将 hot-fix 分支合并到当前 master 分支。
如果代码没有冲突,分支直接合并成功,分支合并成功以后,代码自动提交,无需手动提交本地库。
例如在master分支和hot-fix分支都修改了代码,在合并分支的时候就会发生冲突
此时在master分支上合并hot-fix分支下的代码就会发生冲突
代码冲突时需要进行手动的合并,点击Merge按钮
将两边不一样的代码,进行转移合并到一起
点击File->setting->Version Control->GitHub
使用密码登录很容易出现401等连接失败的情况,是由于网络的原因,可以使用token的方式。
右键点击项目,可以将当前分支的内容 push 到 GitHub 的远程仓库中。
PS:push 是将本地库代码推送到远程库,如果本地库代码跟远程库代码版本不一致,push 的操作是会被拒绝的。也就是说,要想 push 成功,一定要保证本地库的版本要比远程库的版本高!因此一个成熟的程序员在动手改本地代码之前,一定会先检查下远程库跟本地代码的区别!如果本地的代码版本已经落后,切记要先 pull 拉取一下远程库的代码,将本地代码更新到最新以后,然后再修改,提交,推送
在idea中拉取远程仓库最新的代码到项目当中。
**注意:pull 是拉取远端仓库代码到本地同步,如果远程库代码和本地库代码不一致,会自动
**合并,如果自动合并失败,还会涉及到手动解决冲突的问题。
码云是一个和GayHub有着相同功能的代码托管网站,区别是GayHub服务器在国外,访问会出现卡顿或登录失败的现象,而码云是国内的网站,访问速度相对要快很多。
官网地址:https://gitee.com/
点击首页右上角的加号,选择新建仓库
填写仓库名称,路径和选择是否开源(共开库或私有库),点击创建按钮即可。
Idea 默认不带码云插件,所以第一步要安装 Gitee 插件。
自定义远程连接gitee仓库的链接地址
给远程库链接定义个name,然后在URL里面填入码云远程库的 HTTPS 链接即可。
只要码云远程库链接定义好以后,对码云远程库进行 pull 和 clone 的操作和 Github 一致。
码云提供了直接复制 GitHub 项目的功能,方便我们做项目的迁移和下载。
**GitLab 是由 GitLabInc.开发,使用 MIT 许可证的基于网络的 Git 仓库管理工具,且具有wiki 和 issue 跟踪功能。使用 Git 作为代码管理工具,并在此基础上搭建起来的 web 服务。GitLab 由乌克兰程序员 DmitriyZaporozhets 和 ValerySizov 开发,它使用 Ruby 语言写成。后来,一些部分用 Go 语言重写。截止 2018 年 5 月,该公司约有 290 名团队成员,以及 2000 多名开源贡献者。GitLab 被 IBM,Sony,JülichResearchCenter,NASA,Alibaba,
**Invincea,O’ReillyMedia,Leibniz-Rechenzentrum(LRZ),CERN,SpaceX 等组织使用。
官网地址
官网地址:https://about.gitlab.com/
**安装说明:https://about.gitlab.com/installation
**
需要一台CentOS7 虚拟机。
Yum 在线安装 gitlab-ce 时,需要下载几百MB的安装文件,非常耗时,所以提前把所需 RPM 包下载到本地,然后使用离线 rpm 的方式安装。
下载地址:
https://packages.gitlab.com/gitlab/gitlab-ce/packages/el/7/gitlab-ce-13.10.2-ce.0.el7.x86_64.rpm
这里将下载好的安装包拖动到/opt/module 目录下
安装 gitlab 步骤比较繁琐,因此我们可以参考官网编写 gitlab 的安装脚本。
sudo yum install -y curl policycoreutils-python openssh-server cronie
sudo lokkit -s http -s ssh
sudo yum install -y postfix
sudo service postfix start
sudo chkconfig postfix on
curl https://packages.gitlab.com/install/repositories/gitlab/gitlab-ce/script.rpm.sh | sudo bash
sudo EXTERNAL_URL="http://gitlab.example.com" yum -y install gitlab-ce
chmod 777 -R gitlab-install.sh
./gitlab-install.sh
gitlab-ctl reconfigure
执行以下命令启动 GitLab 服务,停止命令执行 gitlab-ctl stop
gitlab-ctl start
使用主机名或者 IP 地址即可访问 GitLab 服务
第一次登陆需要设置账号密码。
在登录后的界面点击new project按钮
点击创建空项目
填写仓库名称并且创建项目
创建完成后的仓库界面
第二步添加GitLab的服务器地址
复制GitLab上的HTTPS方式clone地址,注意需要将中间的gitlab.example示例主机名改成自己的本地主机名称。
在idea中push代码。并创建自定义的远程连接
最后查看gitlab的仓库信息,可以看到本地项目成功的被push推送到了GitLab服务器上。
只要 GitLab 的远程库连接定义好以后,对 GitLab 远程库进行 pull 和 clone 的操作和 Github 和码云一致,此处不再赘述