https://learngitbranching.js.org/?locale=zh_CN在线练习git
1. Git
安装好Git以后, 先检查是否已经绑定了用户名和邮箱
git config --list
再检查C:\Users\xxx.ssh 下是否存在 id_rsa.pub , 存在的话复制其内容到 GitHub 的 SSH KEY 中
没有这一步, PUSH操作的时候会报错:
Successfully created project 'test3' on GitHub, but initial push failed: git@github.com: Permission denied (publickey). Could not read from remote repository. Please make sure you have the correct access rights and the repository exists.
1.1 为什么要使用版本控制?
从个人角度:
在做项目时,如果一点点去改代码会很乱,不利于我们的开发和进度。
使用版本控制可以让每一个历史版本都被记录,可以回到某一个历史状态,接着在这个历史状态下进行修改。
通俗来讲就是可以回退和撤销操作。
从团队合作角度:每一个都需要开发自己负责的功能,多个人在开发同一个项目时,必须使用版本控制协调好每个人对项目的更改
1.2 集中式版本控制
用户从远程仓库获取到的,只是最新版本的文件快照。
集中式的版本控制系统,所有的版本库是放在中央服务器中的
也就是说我们每一次的修改上传都是保存在中央服务器中的。
中央服务器就是个大仓库,大家把产品都堆里面,每一次需要改进和完善的时候,需要去仓库里面把文件给提出来,然后再操作。
集中式版本控制的缺点主要是
- 需要联网。无论是局域网还是互联网,电脑必须要与中央仓库联网。
- 仅中央仓库掌握完整的项目档案库(即所有文件即对应的修订版本),一旦中央仓库宕机,整个项目组都会停工;一旦中央仓库数据丢失,公司直接倒闭。
1.2.1 集中式版本控制的两种模式
1.2.1.1 锁定模式
在锁定模式下,当开发者想要修改某档案、签出该档案后,该档案便会进入锁定状态,其他开发成员便无法加以修改,直到签出者将该档案签回为止。
对于维持同步来说,这当然是一个十分保险的作法,因为永远不会有两个或以上的开发者同时修改同一个档案。
只是这种方法造成了开发者对于档案修改的互斥效应,大大降低了开发效率。
1.2.1.2 合并模式
在合并模式下,允许多位开发者同时针对同一档案进行修改
但是,若当他们分别将档案提交回仓库时发生冲突,便会自动进行合并,而若自动合并失败,再要求人工合并。
不过即使如此,最终目的还是要维持多个开发者间的同步。毕竟,版本控制的结果在集中式档案库中是唯一的,也是每位开发者都需与此结果保持一致的。
1.3 分布式版本控制
分布的含义是每台计算机上都还有一个完整的版本库。
也就是说,当用户 Clone 远程仓库时,并不只提取最新版本的文件快照,而是把代码仓库完整地镜像下来,包括完整的历史记录
不同于集中式版本控制系统的“中央服务器”,分布式版本控制系统可以通过推送版本库,实现不同的计算机之间的版本共享。
什么意思呢?就是说对于同一个文件A,如果两个人同时对A文件进行了修改,最新的版本应该都保存在各自的计算机中,想要实现协同开发,只需要将各自的最新版本库推送给对方,就可以得到最新的版本库了。
但是这里面有个问题,就是一个团队很大的情况下,大家都去修改,到底找谁同步版本库,不乱套了嘛。而且,大的开发项目也不是简单的两台计算机之间的版本互推就可以得到完整的版本库的。
所以,分布式版本控制系统中通常也会有一台充当“中央服务器”的计算机,大家都把版本推送到这台计算机上,而需要同步的人只需同步这一台固定的计算机就可以。
读到这,可能觉得又绕回到集中式版本管理系统了。
实则不然,所谓的分布式管理中的“中央服务器”是用来“交换意见”,或者说充当中介作用的。每一台计算机通过和这台固定的中介交换意见以后,都会拥有完整的版本库。
举个不恰当的例子,分布式中的“中央管理器”就是《乡村爱情》中的大脚超市,刘能、赵四以及长贵都掌握了最新的绯闻,通过大脚超市的意见交换后,每个人都掌握了整个象牙山的绯闻。我们可以看到,在这样的绯闻生态下,即便是王长贵挂了,象牙山的故事仍然可以继续。但是如果长贵是集中式的“中央管理器”,每个人可以将自己知道的绯闻、秘密吐槽给他且不外传,那么他的死将会直接导致《乡村爱情》的终结。
单枪匹马的工作流
团队协作的工作流
其中, pull request 与 pull 区别很大
pull request : 请求远程仓库拉取本人的 commt
pull : 将远程仓库同步更新到本地
1.4 Git管理本地仓库
1.4.1
以下所谈三个区,文件并不只是简单地在三个区转移,而是以复制副本的方式转移
使用 Git 管理的项目,拥有三个区域,分别是
- 工作区、
- 暂存区、
- Git 仓库
对应地,Git 中的文件有三种状态
- modified 已修改 :若工作区的文件被修改了,但还没有放到暂存区,就是 modified 状态。
- staged 已暂存 :若被修改的文件已经从工作区到了暂存区,就是 staged 状态,因此我们也可以说,文件处于暂存区 = 文件是 staged 状态。此外,Git 会为 staged 状态的文件打上标记,以使其包含在下次 commit 的列表中
- committed 已提交 :表示文件已经 “复制一份” 到了本地 Git 仓库中
1.4.2 演示
初始化仓库(⭐)
现在F盘里创建一个文件夹demoProject,文件夹中建一个index.html。
① 在项目目录中,通过鼠标右键打开 CMD
② 执行 git init 命令将当前的目录转化为 Git 仓库
git init 命令会创建一个名为 .git 的隐藏目录,这个 .git 目录就是当前项目的 Git 仓库,里面包含了初始的必要文件,这些文件是 Git 仓库的必要组成部分
检查文件的状态(⭐⭐)
使用 git status 输出的状态
git status -s 输出简要状态
??代表图1的Untracked 状态,该文件处于工作区
跟踪新文件(⭐⭐⭐)
#使用命令 git add 开始跟踪 index.html 文件
git add index.html
# 如果文件过多,你项跟踪目录下所有文件
git add *.*
之后再运行 git status 命令,会看到 index.html 文件在 Changes to be committed 这行的下面,说明已被跟踪,并处于暂存区,staged 状态:
提交更新(⭐⭐⭐⭐)
现在暂存区中有一个 index.html 文件等待被提交到 Git 仓库中进行保存。
执行 git commit 命令进行提交,其中 -m 选项用来附带备注
commit 之后的文件就处于本地 Git 仓库中了,commited状态
git commit -m "这是一个备注,刚刚新建了index.html 文件"
修改并更新(⭐⭐⭐⭐⭐)
目前,index.html 文件已经被 Git 跟踪,并且工作区和 Git 仓库中的 index.html 文件内容保持一致。
当我们修改了工作区中 index.html 的内容之后,再次运行 git status 命令,会看到如下的内容:
文件 index.html 出现在 Changes not staged for commit 这行下面
运行 git status -s 命令,会看到如下的内容:M 代表着 Modified,即修改过的、没有放入暂存区的文件
总而言之,现在文件处于工具区,但是 modified 状态,等待add到暂存区
接下来,我们可以相继 add 和 commit,以将修改后的文件保存到本地 Git 仓库
1.4.3 add 命令
add是个多功能的命令,主要有如下 3 个功效:
① 可以用它开始跟踪新文件,并放到暂存区
② 把已跟踪的、且已修改的文件放到暂存区
③ 把有冲突的文件标记为已解决状态
此外,当存在多个文件需要添加到暂存区时是,采用
git add .
git commit 默认会将暂存区所有文件一并 commit
1.4.4 commit
Git 标准的工作流程是工作区 → 暂存区 → Git 仓库,但有时候这么做略显繁琐,此时可以跳过暂存区,直接将工作区中的修改提交到 Git 仓库,这时候 Git 工作的流程简化为了工作区 → Git 仓库
Git 提供了一个跳过使用暂存区域的方式, 只要在提交的时候,给 git commit 加上 -a 选项,Git 就会自动把所有已经跟踪过的文件暂存起来一并提交,从而跳过 git add 步骤:
git commit -a -m "日志信息"
1.4.6 status
git status 命令无法直接显示已提交(committed)文件的状态,它主要关注的是当前工作目录和暂存区(index/staging area)中文件的状态。当你执行 git status 时,它会告诉您以下信息:
未暂存的改动(即已修改但未添加到暂存区的文件)
已暂存的改动(即已添加到暂存区等待下次提交的文件)
未跟踪的文件(即不在版本控制下的新文件)
对于已经提交过的文件,如果它们没有新的未提交改动,git status 将不会报告它们的存在,因为它默认假设那些文件在最新提交的状态下是干净的。
1.4.5 rm
移除文件
从 Git 仓库中移除文件的方式有两种:
① 从 Git 仓库和工作区中同时移除对应的文件
② 只从 Git 仓库中移除指定的文件,但保留工作区中对应的文件
#从 Git 仓库和工作区中同时移除 index.js 文件
git rm -f index.js
#只从 Git 仓库中移除 index.css,但保留工作区中的 index.css 文件
git rm --cached index.css
D 代表已删除
1.4.6 忽略文件
忽略文件
一般我们总会有些文件无需纳入 Git 的管理,也不希望它们总出现在未跟踪文件列表。 在这种情况下,我们可以创建一个名为 .gitignore 的配置文件,列出要忽略的文件的匹配模式。
文件 .gitignore 的格式规范如下:
① 以 # 开头的是注释
② 以 / 结尾的是目录
③ 以 / 开头防止递归
④ 以 ! 开头表示取反
⑤ 可以使用 glob 模式进行文件和文件夹的匹配(glob 指简化了的正则表达式)
星号 * 匹配零个或多个任意字符
[abc] 匹配任何一个列在方括号中的字符 (此案例匹配一个 a 或匹配一个 b 或匹配一个 c)
问号 ? 只匹配一个任意字符
两个星号 ** 表示匹配任意中间目录(比如 a/**/z 可以匹配 a/z 、 a/b/z 或 a/b/c/z 等)
在方括号中使用短划线分隔两个字符, 表示所有在这两个字符范围内的都可以匹配(比如 [0-9] 表示匹配所有 0 到 9 的数字)
1.4. 版本号
每一次Commit对应一个 40 位长的版本号,在对更改内容使用 SHA -1 加密算法后得到的。
这样,根据版本号,可以避免内容被篡改。
其次, 根据版本号的前两位,在.git/objects 文件夹中,可以找到本次 Commit 的记录。
1.4. 回退到指定的版本
确切地说,是回退到指定的版本号标识的版本。
因此,必须先要找到指定版本对应的版本号,将其提供给 Git
# 在一行上展示所有的提交历史,以获取指定版本的版本号
git log --pretty=oneline
# 使用 git reset --hard 命令,根据指定的提交 ID 回退到指定版本
git reset --hard <CommitID>
# 在旧版本中使用 git reflog --pretty=oneline 命令,查看命令操作的历史
git reflog --pretty=onelone
# 再次根据最新的提交 ID,跳转到最新的版本
git reset --hard <CommitID>
2 .IDEA 集成使用 GitHub(Git同时管理本地仓库和远程仓库)
首先在 IDEA 的设置中绑定 GitHub 的账号
先创建一个 test1.txt 文件,内容为 aaa.
最上一栏 VCS, SHARE ON GitHub,然后选择要发送到远程仓库的文件即可。然后去 GitHub,发现已经帮我们创建了一个同名仓库, 且该仓库下有一个 test1.txt文件, 文件内容为aaa
2.1 本地文件发生改变, 同步修改到本地仓库和远程仓库
存在一种情况, 当自己完成代码的编写后, 需要将本地的代码 PUSH 到远程仓库中
将文本内容修改为 bbb --> 右键文件,GIT,Commit File,填写必要的备注信息后,可以选择 Commit (应用更改到本地仓库)/Commit and Push(应用更改到本地仓库,且推送到远程仓库)
之后, 可以在GH中看到 test1.txt 内容已经变为bbb
2.2 远程仓库发生改变, 同步修改到本地仓库
存在一种情况 : 同事将修改过的代码(ccc) PUSH 到远程仓库中, 这样就和我们本地代码(bbb)不一致了. 在继续工作前, 我们要先 Pull 拉取最新的代码到本地
为了模拟这种情况, 我们手动在 GH 中, 将文本改为 ccc , 并且 Commit, 这样 , 远程仓库中就是ccc了
右键项目, Git --> Pull ,然后选择需要更新的分支
拉取成功后应当能看到本地文本被修改为了 ccc , 即获取到了最新的代码
2.3 完整获取整个远程仓库
存在一种情况 : 第一次接触该项目, 可能需要将整个项目完整下载到本地, 才能进一步开发
在 IDEA 中使用 clone 即可, clone会直接创建一个新项目
3.
点击 Commit ,可以查询历史 Commit 记录。
点击,可以纤细查看 Commit 信息