🎯 这篇文章详细介绍了版本控制的重要性,特别是通过Git实现的分布式版本控制相对于SVN集中式控制的优势。文章首先解释了版本控制的基本概念,强调了在文档或项目多版本迭代中备份与恢复任意版本的能力。接着,重点阐述了Git的历史背景、安装及配置方法,以及其基本理论和工作流程。文中还具体描述了如何使用Git进行项目的创建、克隆,日常操作命令,文件状态切换,.gitignore的使用规则,还有Gitee平台上的操作方式和Git分支管理等内容。旨在为读者提供从入门到实践的全面指南。
文章目录
- **版本控制是什么**
- **Git 和 SVN 的区别**
- **SVN:集中式版本控制系统**
- **Git:分布式版本控制系统**
 
- **Git 发展历史**
- **Git 安装**
- **Git中常用的Linux命令**
- Git必要配置
- 查看所有配置
- 查看系统帮我们默认配置的项
- 查看需要自己配置的项
 
- Git基本理论
- Git的区域划分
- 文件、目录
- Git工作流程
 
- Git项目创建及克隆
- 对已有项目文件夹进行 `git init`
- 场景描述
- 具体步骤
 
- 直接 `git clone` 克隆远程项目到本地
 
- Git基本操作命令和文件状态切换
- .gitignore 忽略文件
- Gitee使用
- 用户名密码访问
- 配置SSH公钥
 
- Git分支使用
- 相关命令
- 如何将dev分支的代码合并到master
 
- 实践
- 新建dev分支、dev分支创建文件、合并到master分支
- 分支切换测试
- 合并冲突测试
 
 
- IDEA上操作Git
版本控制是什么
假如你在帮甲方写一个文档,途中对文档进行了多次迭代,改了十几个版本,最后甲方说要第一个版本,假如你没有对以前的版本进行备份,没办法找到前面的版本,就要吐血了。版本控制可以理解为:对每个版本都有一个备份,可以轻松回到任意选定的版本
Git 和 SVN 的区别
SVN:集中式版本控制系统
SVN是集中式版本控制系统,版本库是集中放在中央服务器的(一般都是用一台服务器下载 VisualSVN 来搭建仓库,其余用户可以只下载 TortoiseSVN 来拉取服务器的文件或者提交文件到服务器),工作的时候使用自己的电脑,首先从中央服务器得到最新的版本,然后进行工作,完成工作后,把自己做完的活推送到中央服务器。集中式版本控制系统是必须联网才能工作,对网络带宽要求较高。
Git:分布式版本控制系统
Git是分布式版本控制系统,没有中央服务器,每个人的电脑就是一个完整的版本库,每个人都拥有全部的代码!可以避免很多安全隐患! 所有版本信息仓库全部同步到本地的每个用户,这样就可以在本地查看所有版本历史,可以离线在本地提交,只需在连网时push至相应的服务器或其他用户那里。由于每个用户那里保存的都是所有的版本数据,只要有一个用户的设备没有问题就可以恢复所有的数据,不会因为服务器损坏或者网络问题,造成不能工作的情况。但这增加了本地存储空间的占用。
协同的方法是这样的:比如说自己在电脑上改了文件A,其他人也在电脑上改了文件A,这时,你们两之间只需把各自的修改推送给对方,就可以互相看到对方的修改了。Git可以直接看到更新了哪些代码和文件!
Git是目前世界上最先进的分布式版本控制系统。
Git 发展历史
- 起初,Linux 内核开源项目有着为数众广的参与者。绝大多数的 Linux 内核维护工作都花在了提交补丁和保存归档的繁琐事务上(1991-2002年间)。
- 到 2002 年,整个项目组开始启用一个专有的分布式版本控制系统 Bitkeeper 来管理和维护代码。Linux社区中有很多的大佬破解研究了BitKeeper !
- 2005 年,开发 Bitkeeper 的商业公司同 Linux 内核开源社区的合作关系结束,他们收回了 Linux 内核社区免费使用BitKeeper 的权力。这就迫使 Linux 开源社区(特别是 Linux 的缔造者 Linus Torvalds)基于使用 BitKeeper 时的经验教训,开发出自己的版本系统(花了2周左右的时间),也就是后来的 Git !
Git是免费、开源的,最初Git是为辅助 Linux 内核开发的,来替代 BitKeeper
Git 安装
https://blog.csdn.net/laodanqiu/article/details/133386063
Git中常用的Linux命令
右键打开终端之后,可以使用linux的相关命令来控制

- ls:列出当前目录中的所有文件名称
dam@HelloDam MINGW64 /e/Projects/eda-standard-cell (master)
$ ls
Code/  LICENSE  Material/  README.en.md  README.md  test.txt
- ll:列出当前目录中的所有文件的较详细信息
dam@HelloDam MINGW64 /e/Projects/eda-standard-cell (master)
$ ll
total 28
drwxr-xr-x 1 dam 197121     0 Oct 23 20:02 Code/
-rw-r--r-- 1 dam 197121 18431 Oct 19 14:46 LICENSE
drwxr-xr-x 1 dam 197121     0 Oct 23 19:07 Material/
-rw-r--r-- 1 dam 197121   902 Oct 19 14:46 README.en.md
-rw-r--r-- 1 dam 197121   992 Oct 19 14:46 README.md
-rw-r--r-- 1 dam 197121     0 Oct 21 14:40 test.txt
- cd [文件名]:切换文件目录
dam@HelloDam MINGW64 /e/Projects/eda-standard-cell (master)
$ cd Code
- cd ..:回退到上一个目录
- pwd:显示当前所在目录
dam@HelloDam MINGW64 /e/Projects/eda-standard-cell/Code (master)
$ pwd
/e/Projects/eda-standard-cell/Code
- touch:在当前目录下新建一个文件
dam@HelloDam MINGW64 /e/Projects/eda-standard-cell/Code (master)
$ touch index.ks
- rm:删除一个文件
dam@HelloDam MINGW64 /e/Projects/eda-standard-cell/Code (master)
$ rm index.ks
- mkdir:新建一个文件夹
dam@HelloDam MINGW64 /e/Projects/eda-standard-cell/Code (master)
$ ls
eda-standard-cell-generation/  pythonProject/dam@HelloDam MINGW64 /e/Projects/eda-standard-cell/Code (master)
$ mkdir cssdam@HelloDam MINGW64 /e/Projects/eda-standard-cell/Code (master)
$ ls
css/  eda-standard-cell-generation/  pythonProject/
- rm -r:删除一个文件夹
dam@HelloDam MINGW64 /e/Projects/eda-standard-cell/Code (master)
$ ls
css/  eda-standard-cell-generation/  pythonProject/dam@HelloDam MINGW64 /e/Projects/eda-standard-cell/Code (master)
$ rm -r cssdam@HelloDam MINGW64 /e/Projects/eda-standard-cell/Code (master)
$ ls
eda-standard-cell-generation/  pythonProject/
- mv [文件名] [目标文件夹]:移动文件
dam@HelloDam MINGW64 /e/Projects/eda-standard-cell/Code (master)
$ touch index.htmldam@HelloDam MINGW64 /e/Projects/eda-standard-cell/Code (master)
$ ls
eda-standard-cell-generation/  index.html  pythonProject/dam@HelloDam MINGW64 /e/Projects/eda-standard-cell/Code (master)
$ mkdir htmldam@HelloDam MINGW64 /e/Projects/eda-standard-cell/Code (master)
$ ls
eda-standard-cell-generation/  html/  index.html  pythonProject/dam@HelloDam MINGW64 /e/Projects/eda-standard-cell/Code (master)
$ mv index.html htmldam@HelloDam MINGW64 /e/Projects/eda-standard-cell/Code (master)
$ ls
eda-standard-cell-generation/  html/  pythonProject/dam@HelloDam MINGW64 /e/Projects/eda-standard-cell/Code (master)
$ cd htmldam@HelloDam MINGW64 /e/Projects/eda-standard-cell/Code/html (master)
$ ls
index.html
- reset:重新初始化终端并清屏
- clear:清屏
- history:查看命令历史
dam@HelloDam MINGW64 /e/Projects/eda-standard-cell/Code (master)
$ history1  ls2  git pull3  ls4  ll5  cd Code6  pwd7  ls8  touch index.ks9  ls10  mkdir index.ks11  rm index.ks12  ls13  mkdir css14  ls15  rm -r css16  ls17  history
- help:帮助
- exit:退出终端
- #:表示注释
Git必要配置
查看所有配置
git config -l

查看系统帮我们默认配置的项
git config --system --list

查看需要自己配置的项
git config --global --list

用户名和邮箱必须要配置,这样才知道是谁提交了文件,配置方式如下:
git config --global user.emai] "你的邮箱地址'
git config --globa] user.name "你的帅名,可以给自己取一个帅帅的外号"
Git基本理论
Git的区域划分

- Workspace:工作区,就是你平时存放项目代码的地方
- Index/Stage:暂存区,用于临时存放你的改动,事实上它只是一个文件,保存即将其提交到文件列表信息
- Repository:仓库区(或本地仓库),就是安全存放数据的位置,这里面有你提交到所有版本的数据。其中HEAD指向最新放入仓库的版本
- Remote:远程仓库,托管代码的服务器
文件、目录

- Directory:使用Git管理的一个文件目录,也就是一个仓库,包含我们的工作空间和Git的管理空间
- WorkSpace:需要通过Git进行版本控制的目录和文件,这些目录和文件组成了工作空间
- .git:存放Git管理信息的目录,初始化仓库的时候自动创建
- Index/Stage: 暂存区,或者叫待提交更新区,在提交进入repo之前,我们可以把所有的更新放在暂存区
- Local Repo: 本地仓库,一个存放在本地的版本库;HEAD指向当前的开发分支( branch )
- Stash:隐藏,是一个工作状态保存栈,用于保存/恢复WorkSpace中的临时状态
Git工作流程
- 在工作目录中添加、修改文件
- 将需要进行版本管理的文件放入暂存区域
- 将暂存区域的文件提交到git仓库

- 工作区(workspace):这是你进行开发的地方,包含了你的项目文件。
- 暂存区(index):当你使用git add命令时,修改会被添加到暂存区。暂存区是Git用来保存你即将提交的文件的状态的地方。
- 本地仓库(local repository):这是存储在你本地计算机上的Git仓库,包含了所有的提交历史和分支信息。
- 远程仓库(remote repository):这是存储在远程服务器上的Git仓库,通常用于团队协作。
- 操作流程: - commit -a:将所有已修改的文件添加到暂存区,并创建一个新的提交。
- add (-u):将修改的文件添加到暂存区。
- commit:创建一个新的提交,将暂存区的文件状态保存到本地仓库。
- push:将本地仓库的提交推送到远程仓库。
- fetch:从远程仓库获取最新的提交信息,但不会自动合并到当前分支。
- pull or rebase:从远程仓库获取最新的提交信息,并将其合并或变基到当前分支。
- checkout HEAD:将工作区恢复到最近一次提交的状态。
- revert:撤销上次提交,但不会删除文件内容,而是创建一个新的提交来撤销之前的更改。
- diff HEAD:比较当前工作区与最近一次提交之间的差异。
- checkout:切换到另一个分支或提交。
 

Git项目创建及克隆
将一个项目托管到 Git 通常有两种主要方式,你可以根据具体情况选择最适合的一种:
对已有项目文件夹进行 git init
 
如果你已经有了一个本地项目文件夹,并希望开始使用 Git 进行版本控制,你可以在该文件夹内执行 git init 命令。这会在你的项目文件夹中创建一个新的 Git 仓库,初始化一个新的 .git 目录来存储版本控制所需的所有必要元数据。之后,你可以添加文件到暂存区并提交到这个本地仓库。如果你需要与他人协作或备份代码,可以将这个本地仓库推送到远程仓库(例如 GitHub、GitLab 或 Gitee等)。
下面是一个具体的例子,展示如何使用这些命令来初始化一个项目,并将其推送到远程仓库。
场景描述
假设你正在开发一个新的网站项目,并且希望将该项目托管在 GitHub 上。你已经创建了一个空的 GitHub 仓库,URL 是 https://github.com/yourusername/newwebsite.git。现在你需要将本地的项目文件与这个远程仓库关联起来,并推送你的代码。
具体步骤
1、初始化 Git 仓库:首先,在你的项目根目录下打开终端(或命令行),然后执行以下命令初始化一个新的 Git 仓库。
git init
这会在你的项目目录中创建一个隐藏的 .git 文件夹,用于存储版本控制的相关信息。
2、添加所有文件到暂存区:接着,将当前目录下的所有文件添加到 Git 的暂存区,准备进行第一次提交。
git add .
3、提交更改:为这次提交添加一条描述性的信息。
git commit -m "Initial commit of the new website project"
4、添加远程仓库地址:然后,将你的 GitHub 仓库地址添加为远程仓库,命名为 origin。
git remote add origin https://github.com/yourusername/newwebsite.git
5、验证远程仓库设置:确保远程仓库配置正确。
git remote -v
你应该能看到类似如下的输出,显示了远程仓库的名称和地址:
origin  https://github.com/yourusername/newwebsite.git (fetch)
origin  https://github.com/yourusername/newwebsite.git (push)
6、推送本地分支到远程仓库:最后,推送你的本地 master 分支到远程仓库,并设置上游分支,这样以后只需使用 git push 就可以直接推送更新了。
git push --set-upstream origin master
或者使用简写形式:
git push -u origin master
请注意,如果你遇到远程仓库中有冲突或者需要覆盖远程内容的情况(例如远程仓库不是空的),你可能需要使用 -f 参数强制推送,但这种情况应该尽量避免,以免丢失他人的工作成果。
通过以上步骤,你就成功地将本地项目与 GitHub 仓库关联起来,并推送了首次提交。之后,你可以继续在本地进行开发,然后使用简单的 git push 命令同步更新到远程仓库。
直接 git clone 克隆远程项目到本地
 
如果你想要参与一个已有的项目或者你在远程已经有一个空的仓库,你可以使用 git clone 命令将远程仓库克隆到本地。这样做会自动创建一个与远程仓库对应的本地仓库副本,并设置好远程仓库地址以便后续的推送和拉取操作。这种方式适合于加入团队项目或是从远程仓库获取最新的项目源码进行开发的情况
Git基本操作命令和文件状态切换
- 未跟踪(untracked):未跟踪,此文件在文件夹中,但并没有加入到git库,不参与版本控制。通过- git add状态变为- Staged
- 已入库(unmodify):文件己经入库,未修改,即版本库中的文件快照内容与文件夹中完全一致。这种类型的文件有两种去处,如果它被修改,变为- Modified,如果使用- git rm移出版本库,则成为- Untracked文件
- 已修改(modified):文件已修改,仅仅是修改,并没有进行其他的操作,这个文件也有两个去处,通过- git add状态变为- Staged,或者使用- git checkout丢弃修改,返回到- unmodify状态,这个- git checkout即从库中取出文件,覆盖当前的修改
- 已暂存(staged):暂存状态,执行- git commit则将修改同步到库中,这时库中的文件和本地文件又变为一致,文件为- unmodify状态
- 已提交(committed):指的是文件或更改已经被保存到本地仓库中,成为项目历史记录的一部分。
.gitignore 忽略文件
有些时候我们不想把某些文件纳入版本控制中,比如数据库文件,临时文件,设计文件等。这是可以在主目录下建立.gitignore文件

此文件有如下规则:
- 注释和空行:在 .gitignore文件中,任何空行或者以#开始的行都会被视为注释,Git 会忽略这些内容。这允许用户添加注释来解释某些忽略规则的原因,或是简单地用空白行来组织文件内容。
- 通配符支持: - 星号(*)可以匹配零个或多个字符。例如,*.log将忽略所有扩展名为.log的文件。
- 问号(?)代表任意单个字符。比如,error?.log可以匹配error1.log,errorA.log等等,但不会匹配error10.log。
- 方括号([abc])表示可以匹配方括号内任何一个字符。例如,file_[ab].txt匹配file_a.txt和file_b.txt。
- 大括号({string1,string2,...})用来指定多个可选模式。如{*.jpg,*.png}忽略所有.jpg和.png文件。
 
- 星号(
- 例外规则(!):如果某个模式前加上感叹号(!),则表示这是一个例外规则,即使符合之前被忽略条件的文件或目录也将被包含进来。例如,如果忽略了所有的.log文件,但希望保留特定的日志文件,可以使用!important.log来确保这个文件不会被忽略。
- 根目录限定(/):在模式前面加上斜杠(/)表示只在仓库的根目录下应用此忽略规则。例如,/config/local.env仅忽略位于仓库根目录下的config/local.env文件,而不会影响其他子目录中的同名文件。
- 目录忽略规则(/):如果模式末尾有斜杠(/),表示这是一个目录,只有当名称与目录名相同时才会被忽略,而不是文件。例如,logs/表示忽略logs目录下的所有内容,但不包括顶级目录下的名为logs的文件。如果没有斜杠,像logs这样的条目既会忽略名为logs的文件也会忽略名为logs的目录。
【案例】
# 为注释
*.txt        # 忽略所有 .txt 结尾的文件
!lib.txt     # 但 lib.txt 除外
/temp         # 仅忽略项目根目录下的 temp 文件,不包括其它目录 temp
build/       # 忽略 build/ 目录下的所有文件
doc/*.txt    # 会忽略 doc/notes.txt 但不包括 doc/server/arch.txt
Gitee使用
用户名密码访问
如果是刚安装git,拉取一个仓库的时候,可能会让输入gitee的用户名和密码,输入即可
配置SSH公钥
配置本地公钥到Gitee之后可以实现免密码登录
# 进入 C:\Users\Administrator\.ssh 目录
# 生成公钥
ssh-keygen

ssh-keygen -t rsa

复制


粘贴

Git分支使用
分支就是科幻电影里面的平行宇宙,如果两个平行宇宙互不干扰,那对现在的你也没啥影响。不过,在某个时间点,两个平行宇宙合并了,我们就需要处理一些问题了!

- 一般软件在master这个分支上运行,当需要增加功能时,就把master复制一份出来到其他分支,然后在其他分支进行开发,在开发完功能并测试之后就可以将开发分支合并到Master分支
- 若引入新功能之后有bug,可以从master分支再引出一个分支hot-fix(热修分支),对代码进行修改,修改后再合并到master
如果同一个文件在合并分支时都被修改了则会引起冲突:解决的办法是我们可以修改冲突文件后重新提交!选择要保留他的代码还是你的代码!
master主分支应该非常稳定,用来发布新版本,一般情况下不允许在上面工作,工作一般情况下在新建的dev分支上工作,工作完后,比如上要发布,或者说dev分支代码稳定后可以合并到主分支master上来。

相关命令
# 列出所有本地分支
git branch# 列出所有远程分支
git branch -r# 新建一个分支,但依然停留在当前分支
git branch [branch-name]# 新建一个分支,并切换到该分支
git checkout -b [branch]# 切换分支
git checkout [branch]# 合并指定分支到当前分支
git merge [branch]# 删除分支
git branch -d [branch-name]# 删除远程分支
git push origin --delete [branch-name]
git branch -dr [remote/branch]
如何将dev分支的代码合并到master
首先在dev分支pull,确保dev代码最新
git checkout dev
git pull origin dev
然后切换master分支,使用merge命令将dev分支的代码合并过来
git checkout master
git merge dev
接着就是将合并过来的代码提交到远程的master分支即可
实践
新建dev分支、dev分支创建文件、合并到master分支
一开始只有一个master分支


所新建的dev分支推送到远程仓库之后,可以看到远程仓库有两个分支了

这时候master分支还是没有所提交的hahaha.txt文件的

而dev分支中已经有hahaha.txt文件了


远程的dev分支中又多了一个txt文件
 
假设开发已经结束,希望将所创建的txt文件合并到master分支中

这时候master分支就有刚刚创建的文件了

分支切换测试
假如dev分支比master多了一个文件test.csv,克隆项目的时候先克隆的是master分支,这时候如果切换成dev分支,会重新将test.csv文件拉取到本地项目中


同理,当切换回master分支时,这个test.csv文件又会消失掉


合并冲突测试
为了方便测试,我使用两台电脑来进行演示
首先使用电脑1来创建一个txt文件并上传到远程的dev分支中

使用电脑2将电脑1上传的文件拉取下来

使用电脑2编辑冲突.txt文件

使用电脑1的master分支先merge dev分支的文件下来,然后也对冲突.txt文件进行修改
 

使用电脑2将编辑之后的冲突.txt上传到远程dev分支

使用电脑1来取远程的dev文件,并将dev的文件合并到master中,触发冲突

合并之后的冲突.txt是这样的

这时候就需要处理冲突了,看看是保留电脑1的修改还是电脑2的修改,我这里保留电脑1的修改,首先将其他多余的东西删除

处理完冲突之后,直接将文件提交到远程仓库即可,最后远程仓库的文件就没有问题了
IDEA上操作Git
