简介
我们在开发的过程中,除了项目本身的问题外,还会有许多其它的问题。
项目的开发本身是一个不断迭代的过程,开发过程中程序员需要不断地对代码进行更新和修改,这就带来了许多问题。
- 开发中会存在多个版本,如何在不同版本之间进行切换?
- 代码上线后,如何在不影响现行开发工作的情况 下对代码进行维护?
- 开发通常是多人合作的,某段代码被多人修改 时,如何处理代码的冲突问题?
- 除此之外,还有存储效率 、远程仓库等问题。
由此,Git诞生了。
git
是一个免费开源的版本控制系统,它被设计用来快速高效地管理项目开发的源码。
- 通过
git
可以跟踪代码的状态。可可以 - 可以在修改代码后对代码的状态 进行存储。
- 可以在需要时将已修改的代码恢复 到之前存储的状态。
- 更牛逼的是,
git
在管理代码时,可以创建代码分支(branch)
,代码分支详单与一段独立的代码记录 ,我们可以在分支上对代码进行任意的修改,并且这个修改只会影响当前的分支。 - 可以对分支进行合并,合并后一个分支的修改便可在另一个分支上生效。
安装
略过...
配置
使用git
前,我们需要配置一下两个属性name
和email
,这两个信息会用来在存储代码时记录用户的身份。可以直接在命令行中通过指令来设置:
bash
git config --global user.name "xxx"
git config --global user.email "xxx"
初始化git
git status
:查看当前仓库。git init
:初始化仓库。
默认情况下,磁盘中的文件并不由git
管理,我们必须要对代码目录进行初始化 ,初始化后git
才能正常的管理文件。进入目录后,直接在目录中执行 git init
即可完成项目的初始化。
初始化后目录中会多出一个.git目录
,这个目录用来存储代码的版本信息,有了.git
就意味着项目现在已经开始被.git
管理了,不希望项目被git
管理时,只需删除 项目中的.git
即可。
.git目录
是默认隐藏的,可以通过设置让其显示
文件状态
git
中的文件有两种状态:
- 未跟踪Untracked :文件没有被
git
所管理。 - 已跟踪tracked :文件已被
git
管理。 - 已跟踪 的文件又有三种状态:
- 未修改 :表示磁盘中的文件和
git仓库
中文件相同,没有修改。 - 修改 :表示磁盘中文件已被修改 ,和
git
仓库中文件不同。 - 暂存 :表示文件修改已经保存 ,但是尚未提交 到
git仓库
。
- 未修改 :表示磁盘中的文件和
可以通过git status
来查看文件的状态。
基本操作
未跟踪 -> 暂存(已跟踪)
git add <filename>
:add
命令是一个多功能的命令。- 如果对未跟踪 的文件调用它会将其设置为已跟踪 ,并将其转换为暂存状态。
- 如果对已跟踪 的文件调用,它就仅仅会将文件设置为暂存状态。
- 使用
git add *
可以将项目中所有未跟踪/已修改 的文件进行暂存。
当我们在项目中创建一个新的文件时,使用git status
查看项目状态,可以看到此时该新建的文件处于未跟踪状态。
我们需要将其切换到暂存状态 ,让git
管理 这个新创建的文件,可以使用git add<filename>
将文件的状态切换为暂存。
暂存 -> 未修改
git commit -m "提交信息"
:将暂存 的文件提交 到git仓库
。- 使用
git commit -a -m "提交信息"
可以将所有已修改 的文件提交 到git仓库
。(未跟踪的文件不会提交)
- 使用
我们将未跟踪变成暂存状态后,git仓库
还无法得到该文件,所以需要使用 git commit -m "提交信息"
将暂存的文件提交 到git仓库
,此时git仓库
的文件和暂存
文件是一模一样 的,所以文件的状态变成了未修改 : nothing to commit, working tree clean
。
未修改 -> 已修改 -> 暂存 -> 未修改
当我们修改文件后,使用git status
查看状态可以发现,修改的文件被标红并标识modified
,说明当前处于已修改状态。
同样调用git add
指令,可以将已修改 文件变为暂存状态。
最后再调用git commit
将其提交 到git仓库
。此时文件又回到了未修改状态。
代码每一次修改完都是在循环这个过程。
常用命令
git restore 重置文件
重置已修改未暂存的文件
当我们修改 文件内容但未暂存 时(已修改),可以执行 git restore <filename>
回到修改前的状态 (已修改 -> 未修改)。
重置所有已修改未暂存的文件
也可以执行 git restore *
使所有已修改的文件回到修改前的状态。
取消删除文件的暂存状态
当我们使用git rm
删除了一个文件,可以执行git restore --stage <filename>
来取消暂存状态。(相当于执行了git commit
)
取消删除文件的动作(恢复)
可以使用git resotore <filename>
取消刚才git rm
的文件。
git rm 删除文件
删除文件
当我们想要删除文件可以使用 git rm<filename>
,执行完操作后查看状态会显示刚删除的文件,此时只是在本地删除 (暂存状态),需要通过git commit -m "xxx"
提交才能使仓库的文件也删除掉。
强制删除已修改未暂存的文件
当要删除的文件处于已修改未暂存 的情况下,使用git rm
会报错:
这是为了防止一些误删的错误发生而造成数据丢失,如果确定要删除可以执行 git rm <filename> -f
去强制删除。
git mv移动文件
使用 git mv <filename> <newfilename>
可以对文件进行重命名操作。
git log 日志
可以通过该命令查看每一次的提交信息。
分支branch
git
在存储 文件时,每一次代码提交都会创建 一个与之对应的节点。
git
就是通过一个一个节点来记录 代码的状态。
节点会构成一个树状结构 ,树状结构就意味着会存在分支 ,默认情况下仓库只有一个分支,命名为master
。
当我们想修改代码,但不确定修改结果如何,怕影响主干上的代码,可以创建 一个分支 进行修改,分支与分支之间相互独立 ,修改一个分支的代码不会影响其它分支。
常用命令
bash
git branch # 查看当前分支
git branch <branch name> # 创建新的分支
git branch -d <branch name> # 删除分支
git switch <branch name> # 切换分支
git switch -c <branch name> # 创建并切换分支
git merge <branch name> # 和并分支
查看分支
使用 git branch
可以查看当前分支:
创建分支
使用 git branch <name>
创建一个分支:
切换分支
使用 git switch <name>
可以切换到指定分支:
创建并切换分支
使用 git switch -c <name>
可以创建一个分支并切换到当前分支:
删除分支
使用 git branch -d <name>
可以删除一个分支:
合并分支
切换到master
分支,使用git switch merge
合并分支:
(Fast-forward)快速合并
:当master
和分支在同一条直线 上可以进行快速合并 ,相当于将master
的指针 直接指向指指定分支的代码。
合并分支冲突
假设我们在代码迭代到C3处时创建了两个分支(update和bug1),此时两个分支对代码的修改都是基于C3的,假设bug1分支完成后我们需要进行合并 ,由于bug1分支和master是在一条直线 上的,所以可以进行快速合并 (直接移动master的指针)。后来update的代码也修改完毕,需要进行合并,但由于update修改的代码是基于C3位置 的master,它进行合并的话是不包含bug1 修改的内容的,所以此时可能会造成合并冲突 ,命令行也会警告Merge conflicts in index.html
:在index.html
里发生了合并冲突。
此时在vscode界面也可以看到合并冲突了:
此时我们需要进行手动处理该冲突
-
在
vscode
的index.html
里直接进行修改,修改成我们想要的样子后提交到仓库。 -
使用
vscode
给我们提供的快捷键,并提交到仓库。
变基
在开发中,除了通过merge来合并分支以外,还可以通过变基来完成分支的合并。
我们通过merge合并分支时,在提交记录中会将所有的分支创建与分支合并的过程全部显示出来,这样当项目比较复杂,开发过程比较波折的时候,会出现分支反复创建,合并与删除,这样一来我们代码的提交记录就会变得非常混乱。
此时就出现了变基
原理
- 当我们发起变基时,git会首先找到两条分支的最近共同祖先。
- 对比当前分支相对于祖先的历史提交,并且将不同的代码提取出来存储到一个临时文件中。
- 将当前分支指向目标的基地。
- 以当前分支基地开始,重新执行临时存储的文件
图例
假设C3处创建了一个 update
分支并迭代了三次,此时 update
分支相较于C3不同的部分就是C4、C7、C9; master
主干也迭代了两次走到了C6。假设现在 update
想要与 master
合并分支,我们首先去找它与想要合并的基地的共同最近的祖先 ,这里显然是C3。 我们将不同于C3的部分存储到临时文件 中,并将 update
的指针指向目标基地 ,这里就是 master
。 最后以当前指向的基地为开始 ,去执行临时存储 的文件,update
指向临时文件的最后一步。此时分支都在一条线上,又可以进行快速合并了。
变基命令
图形化界面显示:
此时我们要让 iss2
与 master
合并,也就是改变 iss2
的基地,让其指向 `master
-
切换到
iss2
分支执行git rebase master
此时会提示冲突,与
merge
一样,在代码中做出选择,然后提交到仓库 此时iss2
与master
就在同一条线上了,变基就完成了。 -
再次切换分支回到
master
执行git merge iss2
进行快速合并。
小结
当我们在分支 上对文件内容做出改动 时,切换到主干master
上是不会显示、不受影响的,这样就避免了不可回头的错误。所以当上线的代码出bug
时,或者要添加新业务时,我们都是先创建一个自己的分支节点 ,在自己的分支节点进行操作,等确定无误后再合并到主干上,当发生分支冲突时按需求进行操作。
变基和merge
对于合并分支的最终结果来说都是一样的,但是变基会使得代码的提交记录会更清晰简洁。大部分情况合并变基是可以互换的,但是分支如果已经提交给了远程仓库,那么这时尽量不要使用变基。
vscode里使用git
用vscode打开一个项目时,可以通过点击这个icon后初始化仓库 ,这样该项目中就会自动初始化 ,自动添加.git目录
。
在项目中创建新的文件并修改时,文件名后面会有一个U
,是untracked
未跟踪的意思。
如果是已跟踪 的文件则文件名后面会有一个M
,是modified
已修改的意思。
点击icon后点击提交
提交按钮将add
命令和commit
命令合并了,非常方便
因为是第一次提交,文件还未被跟踪,所以会提示:
没有要提交的暂存更改 是否要暂存所有更改并直接提交它们
点击是
即可。
提交成功后,文件名后面绿色的U
就会消失。
GitLens --- Git supercharged插件
可以使用插件更好地展示代码迭代的过程
远程仓库
在开发中是多人协作的,所以需要一个远程的git仓库,远程git仓库和本地的本质上没什么区别,不同点在于远程的仓库可以被多人同时访问,方便协同开发。在实际工作中,git的服务器通常由公司搭建内部使用,或者购买一些公共的私有的git服务器。最常用的有GitHub和Gitee。
使用远程仓库
GitHub
-
创建仓库
-
将本地仓库传至GitHub
bashgit remote add origin https://github.com/xxxxx/gitDemo.git # git remote add <remote name> <url> git branch -M mian # 修改主分支名字为main git push -u origin main # git push -u <remote name> <branch name> #将代码上传到origin服务器
Gitee
-
创建仓库
-
将本地仓库传至GitHub
bashgit remote add origin https://gitee.com/cloud0-0/git-demo.git # 如果一个本地仓库要上传多个远程仓库,则命名需要改一下,origin改成别的 git push -u origin "main" # 这里push的orgin也改成对应的即可
克隆仓库
bash
git clone <url>
-
GitHub
-
Gitee
删除仓库
-
Gitee
-
GitHub
基本操作
bash
git remote # 列出当前的关联的远程库
git remote -v # 查看关联的远程库的详细信息
git remote add <远程库名> <url> # 关联远程仓库
git remote remove <远程库名> # 删除远程库
git push -u <远程库名> <分支名> # 向远程库推送代码,并和当前分支关联
git push <远程库名> <本地分支>:<远程分支> # 推送到指定分支
# 如果本地的版本低于远程库,push默认是推不上去
git fetch # 要想推送成功,必须先确保本地库和远程库的版本一致,fetch它会从远程仓库下载所有代码,但是它不会将代码和当前分支自动合并
# 使用fetch拉取代码后,必须要手动对代码进行合并
git merge <远程库名/分支名> # 合并分支
git pull # 从服务器上拉取代码并自动合并
git clone <url> # 从远程库下载代码
git clone <url> <name> # 从远程库下载代码,并下载到指定文件名目录下
注意:推送代码之前,一定要先从远程库中拉取最新的代码。
Tags
git
中有一个头指针 ,通常是跟着分支走的,每commit
一次就往前走一步,当我们想回到先前的版本,可以git log
打印日志查看每次commit的id
,然后执行 git switch <id>
就可以回到指定id的commit节点
,但此时就会产生分离头指针现象。当头指针没有指向某个分支的头部时,这种状态我们称为分离头指针(HEAD detached)头。虽然分离头指针的状态下也可以操作代码,但是这些操作不会出现在任何一个分支上。
当我们想在之前的版本进行操作时,我们可以选择执行git switch -c <分支名><id>
在想要执行操作的节点创建一个分支 ,在分支上进行操作,这样HEAD指针
又会跟着分支走,就不再是头指针分离了。但是commit
的节点是一长串哈希值,阅读起来不是很友好。
因此产生了Targs
,我们可以为指定的commit
节点设置一个tag
,标注一个版本,若想设置tag
的commit
就在当前head指针
所指的节点,可以直接通过执行git tag <版本>
实现,若不在则可以执行git tag <版本><提交id>
实现,最后通过git push<远程仓库><标签名>
来同步到远程仓库。可以使用git tag
查看现有的标签,这样就可以通过标签快速地识别不同版本的开发节点。
bash
git tag # 查看所有版本
git tag <版本> # 设置当前节点标签
git tag <版本> <提交id> # 给指定commit节点设置标签
git push <远程仓库> <版本> # 将指定标签推送到远程仓库
git push <远程仓库> --tags # 将所有标签推送到远程仓库
git tag -d <版本名> # 删除标签
git push <远程仓库> --delete <标签名> # 删除远程标签
gitignore
默认情况下,git
会监视 项目中所有内容,但是有些内容比如 node_modules
目录中的内容,我们不希望它被 git
所管理。我们可以在项目目录中添加一个.gitignore
文件,来设置那些需要 git 忽略
的文件。
在项目里创建.gitignore
,直接分行写需要忽略的文件即可。
此时git status
可以看到确实都被忽略了。
gh-pages
在 github
中,可以将自己的静态页面直接部署到 github
中,它会给我们提供一个地址使得我们的页面变成一个真正的网站,可以供用户访问。
- 要求:
- 静态页面的分支 必须叫做:
gh-pages
- 如果希望页面可以通过
xxx.github.io
访问,则需要将远程仓库的名字配置为xxx.github.io
- 静态页面的分支 必须叫做:
docusaurus
-
facebook 推出的开源的静态的内容管理系统,通过它可以快速的部署一个静态网站
-
安装
jsnpx create-docusaurus@latest my-website classic
-
启动项目
jsnpm start` || `yarn start
-
构建项目
jsnpm run build`或`yarn build
-
配置项目:
jsdocusaurus.config.js 项目的配置文件