what-is-verion-control-systems-process.png

一、源起

代码,对于软件公司而言是最为宝贵的资产。如何保管代码才是是最高效的呢?
假设我们不使用任何工具,各自为政,那么将会至少存在以下几个问题:

  • 团队成员因为硬盘损坏或者离职等原因导致代码丢失,则该成员的代码丢失
  • 团队成员无法得到其他成员的代码。需要定期花时间将自己的代码与其他成员合并(两两合并),以便于得到完整的代码,项目一旦复杂,这个工作量极大
  • 如果项目开发过程中,发觉编码思路出错,需要将代码回退到三天前的状态,则需要全部重写
  • 项目上线后,发觉存在一个低级bug,需要确认这个bug谁写的(然后…)

这里涉及到的都是代码管理的问题。而且只是真实世界代码管理问题之中很少很少的一部分。
解决这类问题的专业工具,就是今天要介绍的代码管理工具,或者称为版本管理工具(VCS Version Control System)。

VCS 中每次将代码更改提交给VCS管理时,就会产生一个版本(Version),因此可以追踪到单个文件的更改。一般的VCS系统都存在一个服务器,可以将本地代码提交到远端服务器,并支持自动的代码合并,因此团队成员可以轻松地共享代码,合并代码的成本也大大降低。

市面上的VCS软件非常多,但群雄逐鹿的年代已经过去了。Git 就是现今最为流行和最为强大的版本管理系统。他的作者就是鼎鼎大名的linux内核作者linus torvalds。是大佬云集的linux社区用来管理linux内核代码的版本管理工具,看血统也知道必然强大。
8ogqpfkvqqpyfbs3w6p7.png

二、Git的安装

windows

访问git官网(git-scm.com/) 下载安装包,之后点击下一步到底安装。安装完成后,git提供了一个git-bash,是在windows下模拟的linux终端,可以使用基础的linux命令。

linux

使用包管理器直接下载安装。比如centos下 yum install git

mac

建议使用homebrew安装, brew install git

三、Git基本概念

我们来以Git为例,讲解下VCS常见的一些概念。

Git-Server 及 Git Remote

Git是C/S架构,意味着Git也存在一个服务器,一个本地客户端。一个Git服务器(git-server)可以托管多个git代码仓库(git-repository)。意味着,你可以在同一个git服务器上,为项目A创建一个代码仓库,也可以为项目B创建一个代码仓库,两个代码仓库独立管理,互不影响。每个在服务器上的代码仓库相较于本地代码仓库而言称为remote,每个本地客户端可以存在多个remote。也就是说,你可以将同一个项目的代码推送到多个remote。比如推送到国外的github,同时推送到国内的gitee.
image.png
git服务器可以自建(常用工具gitlab,gogs),也可以使用托管服务网站。最著名的就是github.com,但因为众所周知的原因速度稍慢。国内的主要有码云(gitee.com),阿里code等。

Git-Client 及 本地代码仓库

我们的代码在自己电脑上,要与git服务器交互,显然需要一个客户端,称为git-client。最早git是linux的一个命令行程序(毕竟人家是linux之父写的),所以Git-client在linux下就是git命令。随着技术发展,现在也有windows版本,也出现了一些GUI工具(最著名的有SourceTree)等。

Git本地代码仓库,是git远程仓库的一个本地副本。通常的表现形式是一个名为 .git 的文件夹。它支持本地提交,并支持跟远程仓库进行同步。

Git会在本地的每次提交会产生一个版本,git会分配一个独立的提交ID,提交包含了文件的修改内容、提交的说明信息、作者信息等。git可以在不联网的情况下浏览提交记录,包括本地提交以及已经同步过的远端提交记录。也可以单独查看某个文件的修改信息。git支持也支持回滚到某个特定的版本,方便撤销代码更改。当提交被推送到远端时,这些提交记录也会被提交。
image.png

git对文件的管理是需要主动添加的。一旦添加后,git会自动监控文件修改,并根据是否提交来更新文件状态。

Git分支

Git的一个重要的作用是支持并行开发,比如 A和B独立开发两个不相关的功能,可以同时开发,并且在合适的时间合并代码。这项支持的特性称为Git分支,是Git一项非常重要的特性。后续我们在其他文章中单独来讨论。

四、Git的使用

4.1 创建远端仓库

下面来讲解git的用法,首先我们需要有一个git的远端仓库。个人学习不建议自建,建议使用gitee。

  1. 首先访问 https://gitee.com/signup?from=homepage 注册gitee账号
  2. 然后点击头像旁的+ 号 创建仓库

image.png
image.png

  1. 如果是多人协作,可以在仓库管理界面中添加人员,操作如下

image.png
image.png
image.png
将链接或者二维码发给邀请的对象即可。

4.2 本地仓库操作

下面 我们来讲解本地仓库的几个基本的操作

  • 克隆:clone,从远程下载一个代码仓库的操作,在git称为clone克隆操作,这个操作不单是下载了仓库中的代码文件,也包括了提交记录,分支等等附属信息。克隆完成后,本地得到的是一个完整的仓库
  • 添加:add, 将一个文件添加到git管理范围中。
  • 提交:commit,这个提交是本地提交,在本地仓库中创建了一次提交,产生了一个版本,并且新增了提交记录。不需要联网。
  • 推送:push,将本地代码仓库的提交信息及代码更改推送给远程仓库,需要联网
  • 拉取:pull 从远程仓库下载代码更改及提交信息,需要联网

image.png

具体操作步骤:

  1. 打开一个git-bash终端,首先配置环境

    1. $ git config --global user.name "你的名字或昵称,用户名"
    2. $ git config --global user.email "你的邮箱,与【设置-多邮箱管理】中的“提交邮箱”保持一致"
  2. 使用 git clone 命令克隆一个远程仓库 ```bash $ git clone https://gitee.com/somename/somerepo.git Cloning into ‘somerepo’… remote: Enumerating objects: 273, done. remote: Counting objects: 100% (273/273), done. remote: Compressing objects: 100% (270/270), done. remote: Total 273 (delta 102), reused 0 (delta 0), pack-reused 0 Receiving objects: 100% (273/273), 117.85 MiB | 3.75 MiB/s, done. Resolving deltas: 100% (102/102), done. Updating files: 100% (79/79), done.

  1. 仓库地址在gitee仓库页面获取<br />![image.png](https://cdn.nlark.com/yuque/0/2021/png/953441/1626943474476-8464c939-3083-422b-a59c-5d5fd7bd539c.png#height=361&id=Ww6SI&margin=%5Bobject%20Object%5D&name=image.png&originHeight=361&originWidth=1101&originalType=binary&ratio=1&size=58262&status=done&style=none&width=1101)
  2. 3. 切换到clone完成的项目目录下,在文件夹中添加文件,并使用git add 将文件添加到git管理中
  3. ```bash
  4. # 切换到项目文件夹下
  5. $ cd somerepo/
  6. # 使用vi创建一个文本文件
  7. $ vi somecode.txt
  8. # 查看当前目录下的文件状态,可见是Untracked files
  9. $ git status
  10. On branch master
  11. Your branch is up to date with 'origin/master'.
  12. Untracked files:
  13. (use "git add <file>..." to include in what will be committed)
  14. somecode.txt
  15. nothing added to commit but untracked files present (use "git add" to track)
  16. # 使用git add将文件加入到git管理范围内
  17. $ git add somecode.txt
  18. warning: LF will be replaced by CRLF in somecode.txt.
  19. The file will have its original line endings in your working directory
  20. # 此时文件状态变为 new file
  21. $ git status
  22. On branch master
  23. Your branch is up to date with 'origin/master'.
  24. Changes to be committed:
  25. (use "git restore --staged <file>..." to unstage)
  26. new file: somecode.txt
  1. git status 查看工作区状态
  2. git commit 提交到本地的代码仓库 git commit -m 提交消息(说明本次提交的作用) ```bash $ git commit -m ‘新增重要代码’ [master bb5a735] 新增重要代码 1 file changed, 1 insertion(+) create mode 100644 somecode.txt
  1. 6. git push 推到远端,这一步可能会弹出验证框,需要你填入用户名,密码,则按照注册gitee时的用户名密码填写
  2. ```bash
  3. $ git push
  4. Enumerating objects: 4, done.
  5. Counting objects: 100% (4/4), done.
  6. Delta compression using up to 8 threads
  7. Compressing objects: 100% (2/2), done.
  8. Writing objects: 100% (3/3), 314 bytes | 157.00 KiB/s, done.
  9. Total 3 (delta 1), reused 0 (delta 0), pack-reused 0
  10. remote: Powered by GITEE.COM [GNK-6.0]
  11. To https://gitee.com/somename/somerepo.git
  12. afbb494..bb5a735 master -> master
  1. git log 查看日志记录,后面跟文件路径即可查看某个文件的变更记录 ```bash $ git log commit bb5a7350d504b5e26fc6d1932e2165cc31aedbff (HEAD -> master, origin/master, origin/HEAD) Author: xxx xx.xxx@163.com Date: Thu Jul 22 16:54:45 2021 +0800

    新增重要代码

  1. 8. gitee仓库管理页面,直接新增一个文件,随便填一些内容,便于模拟拉取
  2. ![image.png](https://cdn.nlark.com/yuque/0/2021/png/953441/1626944519570-c3a5d030-d0cd-4e4e-910f-36b9be8151c3.png#height=498&id=FYaR4&margin=%5Bobject%20Object%5D&name=image.png&originHeight=498&originWidth=881&originalType=binary&ratio=1&size=49814&status=done&style=none&width=881)
  3. 9. git pull 拉取远端的修改
  4. ```bash
  5. $ git pull
  6. remote: Enumerating objects: 4, done.
  7. remote: Counting objects: 100% (4/4), done.
  8. remote: Compressing objects: 100% (2/2), done.
  9. remote: Total 3 (delta 1), reused 0 (delta 0), pack-reused 0
  10. Unpacking objects: 100% (3/3), 268 bytes | 15.00 KiB/s, done.
  11. From https://gitee.com/somename/somerepo.git
  12. bb5a735..fd0f532 master -> origin/master
  13. Updating bb5a735..fd0f532
  14. Fast-forward
  15. abc.txt | 1 +
  16. 1 file changed, 1 insertion(+)
  17. create mode 100644 abc.txt

4.3 解决冲突

冲突的产生是因为两个客户端同时修改了同一个文件的同一个位置,git无法自动合并,因此爆出冲突。
解决冲突的原则:先商量,再操作,严禁不商量直接覆盖别人的代码

模拟方式:同时在本地和gitee仓库管理页修改somecode.txt 的同一行
1)修改gitee仓库中的somecode.txt,提交编辑(无须推送,立即就应用到代码仓库里了)

  • 点击文件,进入文件界面,选择编辑文件

image.png

  • 内容改为 java123

2)提交本地代码,并push,会直接报错

  1. # 修改同一文件,内容改为 java456
  2. $ vi somecode.txt
  3. # 再次添加修改
  4. $ git add somecode.txt
  5. warning: LF will be replaced by CRLF in somecode.txt.
  6. The file will have its original line endings in your working directory
  7. # 提交
  8. $ git commit -m 制造冲突
  9. [master 61fca79] 鍒堕€犲啿绐? 1 file changed, 1 insertion(+), 1 deletion(-)
  10. # 推送,与远端冲突,无法推送,要求先拉取(pull)
  11. $ git push
  12. To https://gitee.com/maizdotme/class56phrase3.git
  13. ! [rejected] master -> master (fetch first)
  14. error: failed to push some refs to 'https://gitee.com/maizdotme/class56phrase3.git'
  15. hint: Updates were rejected because the remote contains work that you do
  16. hint: not have locally. This is usually caused by another repository pushing
  17. hint: to the same ref. You may want to first integrate the remote changes
  18. hint: (e.g., 'git pull ...') before pushing again.
  19. hint: See the 'Note about fast-forwards' in 'git push --help' for details.
  20. # 拉取后报文件冲突
  21. $ git pull
  22. remote: Enumerating objects: 5, done.
  23. remote: Counting objects: 100% (5/5), done.
  24. remote: Compressing objects: 100% (2/2), done.
  25. remote: Total 3 (delta 1), reused 0 (delta 0), pack-reused 0
  26. Unpacking objects: 100% (3/3), 261 bytes | 16.00 KiB/s, done.
  27. From https://gitee.com/maizdotme/class56phrase3
  28. e9d1c58..9ceecd7 master -> origin/master
  29. Auto-merging somecode.txt
  30. CONFLICT (content): Merge conflict in somecode.txt
  31. Automatic merge failed; fix conflicts and then commit the result.

3)解决冲突
冲突后的文件内容改为:

  1. <<<<<<< HEAD
  2. java456
  3. =======
  4. java123
  5. >>>>>>> 9ceecd77ce954380e3f4a75e0aa4a9df6b67ce4f

======= 之上的内容为本地内容 ,之下的是远端服务器上的
手工修改文件内容,之后再add、commit、push即可

  1. # 修改内容为 java123456
  2. $ vi somecode.txt
  3. $ git add somecode.txt
  4. $ git commit -m 合并冲突
  5. [master 0415e1e] 合并冲突
  6. # 推送成功
  7. $ git push
  8. Enumerating objects: 10, done.
  9. Counting objects: 100% (10/10), done.
  10. Delta compression using up to 8 threads
  11. Compressing objects: 100% (4/4), done.
  12. Writing objects: 100% (6/6), 552 bytes | 184.00 KiB/s, done.
  13. Total 6 (delta 2), reused 0 (delta 0), pack-reused 0
  14. remote: Powered by GITEE.COM [GNK-6.0]
  15. To https://gitee.com/maizdotme/class56phrase3.git
  16. 9ceecd7..0415e1e master -> master

五、IDE集成

以上介绍了git的基本操作。但通常我们的开发是在IDE中进行的。如何在IDE中使用GIT呢?
这里以idea为例介绍一般IDE中的集成用法。
idea可以自动识别git项目,因此当你将一个git项目导入idea时,idea就会自动添加git支持。
根据个人经验,如果想在idea中使用git管理项目。建议按如下步骤操作:

  1. 在云端创建git仓库
  2. clone到本地
  3. 将项目代码放到该代码仓库中 或者 创建项目时将项目代码位置指向该代码仓库
  4. 导入项目到idea中,idea会自动识别

常见操作支持:

clone

选择菜单栏VCS > Get from version control
image.png
填入git仓库地址,选择文件夹路径
image.png
结束后会弹出询问框,是否打开新项目

add

idea会在新建文件之后询问是否加入到git,也可以勾选记住选项
image.png
这里需要提一下 .gitignore 文件,这个文件可以放置在项目的根目录下,列出git需要忽略的文件,比如,maven项目的target文件夹, .idea 文件夹,idea的 .iml 文件等。git每次提交时会自动忽略这些文件。建议使用上。

commit

使用快捷键 ctrl+k
image.png

push

使用快捷键 ctrl+shift+k
image.png

pull

使用快捷键 ctrl+t
image.png

log

idea识别出git项目后会提供git日志查看界面
image.png

解决冲突

当出现冲突时,选择点击冲突文件即可进入以下的冲突解决界面,点击④和⑤处的加入到结果或者取消
VCS系列之Git快速入门 - 图19

其他

另外,还有两个地方是跟git有关的,这两个地方就可以完成所有的git相关的功能了
一个是在项目上右击选择Git菜单
image.png

另一个 是在顶部菜单 VCS 菜单下
image.png

六、总结

本文主要是介绍VCS的概念,及Git的基本使用。内容比较粗浅,旨在帮助大家快速了解到Git的基本概念及基本使用。细节有不清晰的地方,可以提出探讨。

资源:

  1. Git官方的开源书籍 《Pro Git》在线中文版 https://git-scm.com/book/zh/v2
  2. 廖雪峰的GIT教程 https://www.liaoxuefeng.com/wiki/896043488029600
  3. backlog的有趣GIT教程 https://backlog.com/git-tutorial/cn/