Git

简介

我们在开发的过程中,除了项目本身的问题外,还会有许多其它的问题。

项目的开发本身是一个不断迭代的过程,开发过程中程序员需要不断地对代码进行更新和修改,这就带来了许多问题。

  • 开发中会存在多个版本,如何在不同版本之间进行切换
  • 代码上线后,如何在不影响现行开发工作的情况 下对代码进行维护
  • 开发通常是多人合作的,某段代码被多人修改 时,如何处理代码的冲突问题
  • 除此之外,还有存储效率远程仓库等问题。

由此,Git诞生了。

git是一个免费开源的版本控制系统,它被设计用来快速高效地管理项目开发的源码。

  • 通过git可以跟踪代码的状态。可可以
  • 可以在修改代码后对代码的状态 进行存储
  • 可以在需要时将已修改的代码恢复 到之前存储的状态
  • 更牛逼的是,git在管理代码时,可以创建代码分支(branch),代码分支详单与一段独立的代码记录 ,我们可以在分支上对代码进行任意的修改,并且这个修改只会影响当前的分支
  • 可以对分支进行合并,合并后一个分支的修改便可在另一个分支上生效。

安装

略过...

配置

使用git前,我们需要配置一下两个属性nameemail,这两个信息会用来在存储代码时记录用户的身份。可以直接在命令行中通过指令来设置:

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界面也可以看到合并冲突了:

此时我们需要进行手动处理该冲突

  1. vscodeindex.html里直接进行修改,修改成我们想要的样子后提交到仓库。

  2. 使用vscode给我们提供的快捷键,并提交到仓库。

变基

在开发中,除了通过merge来合并分支以外,还可以通过变基来完成分支的合并。

我们通过merge合并分支时,在提交记录中会将所有的分支创建与分支合并的过程全部显示出来,这样当项目比较复杂,开发过程比较波折的时候,会出现分支反复创建,合并与删除,这样一来我们代码的提交记录就会变得非常混乱。

此时就出现了变基

原理

  1. 当我们发起变基时,git会首先找到两条分支的最近共同祖先。
  2. 对比当前分支相对于祖先的历史提交,并且将不同的代码提取出来存储到一个临时文件中。
  3. 将当前分支指向目标的基地。
  4. 以当前分支基地开始,重新执行临时存储的文件

图例

假设C3处创建了一个 update 分支并迭代了三次,此时 update 分支相较于C3不同的部分就是C4、C7、C9; master 主干也迭代了两次走到了C6。假设现在 update 想要与 master 合并分支,我们首先去找它与想要合并的基地的共同最近的祖先 ,这里显然是C3。 我们将不同于C3的部分存储到临时文件 中,并将 update 的指针指向目标基地 ,这里就是 master 最后以当前指向的基地为开始 ,去执行临时存储 的文件,update 指向临时文件的最后一步。此时分支都在一条线上,又可以进行快速合并了。

变基命令

图形化界面显示:

此时我们要让 iss2master 合并,也就是改变 iss2 的基地,让其指向 `master

  1. 切换到 iss2 分支执行git rebase master

    此时会提示冲突,与 merge 一样,在代码中做出选择,然后提交到仓库 此时 iss2master 就在同一条线上了,变基就完成了。

  2. 再次切换分支回到 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

  1. 创建仓库

  2. 将本地仓库传至GitHub

    bash 复制代码
    git 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

  1. 创建仓库

  2. 将本地仓库传至GitHub

    bash 复制代码
    git 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,标注一个版本,若想设置tagcommit就在当前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 推出的开源的静态的内容管理系统,通过它可以快速的部署一个静态网站

  • 安装

    js 复制代码
    npx create-docusaurus@latest my-website classic
  • 启动项目

    js 复制代码
    npm start` || `yarn start
  • 构建项目

    js 复制代码
    npm run build`或`yarn build
  • 配置项目:

    js 复制代码
    docusaurus.config.js 项目的配置文件
相关推荐
光影少年11 分钟前
vue2与vue3的全局通信插件,如何实现自定义的插件
前端·javascript·vue.js
As977_12 分钟前
前端学习Day12 CSS盒子的定位(相对定位篇“附练习”)
前端·css·学习
susu108301891114 分钟前
vue3 css的样式如果background没有,如何覆盖有background的样式
前端·css
Ocean☾16 分钟前
前端基础-html-注册界面
前端·算法·html
Dragon Wu18 分钟前
前端 Canvas 绘画 总结
前端
CodeToGym22 分钟前
Webpack性能优化指南:从构建到部署的全方位策略
前端·webpack·性能优化
~甲壳虫24 分钟前
说说webpack中常见的Loader?解决了什么问题?
前端·webpack·node.js
~甲壳虫28 分钟前
说说webpack proxy工作原理?为什么能解决跨域
前端·webpack·node.js
Cwhat29 分钟前
前端性能优化2
前端
熊的猫1 小时前
JS 中的类型 & 类型判断 & 类型转换
前端·javascript·vue.js·chrome·react.js·前端框架·node.js