一、Git基本操作
1.1 配置
git是一个分布式 版本控制系统,这意味着每个人的电脑上都是一个完整的版本库,我们不再需要将代码上传至”中央服务器上“,每个人电脑里都有完整的版本库,某一个人的电脑坏掉了问题不大,从其他人那里复制一个就可以了。
- 首先在官网上下载并安装,教程太多了。
- 在上传某个项目的代码时,需要在文件夹内配置个人信息,这里的用户名和密码表示的是你在github或是gitee上的账号信息。
$ git config --global user.name "Your Name"
$ git config --global user.email "email@example.com"
? 注意:git config 命令的--global 参数,用了这个参数,表示你这台机器上所有的Git仓库都会使用这个配置,当然也可以对某个仓库指定不同的用户名和Email地址。
- 配置git环境变量,这个网上教程也太多了。
1.2 创建版本库
1.2.1 创建空文件夹
mkdir Ryuko_learn_git
cd Ryuko_learn_git
1.2.2 初始化仓库
git init
此时文件夹内会创建一个空的仓库,并且目录下多了一个.git 的隐藏目录,这个目录是Git来跟踪管理版本库的。
1.3 Git 常用操作
1.3.1 git status
git status 命令可以让我们时刻掌握仓库当前的状态。
1.3.2 git add
git add <filename> 可以把文件从工作区(编写代码的地方)添加到暂存区。
1.3.3 git commit
`git commit -m 'message’可以把文件从暂存区提交到本地仓库。
-m 后面输入的是本次提交的说明,可以输入任意内容,当然最好是有意义的,这样你就能从历史记录里方便地找到改动记录。
1.3.4 git remote add
git remote add origin https://github.com/.. 表示添加远端仓库到本地,这句话的意思是将后面的仓库地址保存到本地仓库,origin 是给这个地址起的别名。
1.3.5 git push --set-upstream
git push --set-upstream origin master:master 的意思是,push到名字为origin 的远程仓库,这个名字指的是我们在1.3.4中为仓库起的别名。
master:master的意思是把本地仓库的master(左)分支推到远程仓库的master分支(右),因此如果是 git push --set-upstream origin a:b 意思是把本地的a分支推到远程的b分支;–set-upstream 可以记住本次推送,下次推送可以直接选择 git push。
本节开头的例子可以简写为:git push -u origin master
二、版本控制
2.1 状态跟踪
首先在github上面创建一个仓库,然后建立本地和远程仓库的连接。
我用的是以前的项目来举例,所以就不再介绍如何建立连接了。
下面进入正文。
我们在刚刚拿到团队仓库中的代码后进行编码操作,新建文件夹的时候会发现,这个文件的尾部会有一个绿色的U,将a.js的状态表示为U (untracked)表示当前文件还没有加入到版本库(版本库不会记录当前文件的提交和修改)
由于版本库不会记录提交和修改,所以我们在这个文件中无论如何输入代码,都不会改变它(untracked)的状态
此时当我们使用 git add a.js之后,a.js状态为A(added),表示当前文件加入到暂存区
当我们修改a.js之后,a.js状态为M (modified),表示当前文件被修改了
当文件修改之后,仍然需要调用git add命令将修改的东西提交到暂存区(此时文件状态变为A)
我们可以使用git commit 命令将暂存区的修改提交到分支
当出现冲突的时候,状态为c (conflict),此时我们要解决冲突,不过这两点我放在后面介绍。
2.2 查看历史版本
通过git log 可以看到每一次commit 提交后的版本信息
通过git log --pretty=oneline 可以将上述信息压缩为一行展示:
2.3 版本回退
在上一节的图片中有这样一句话HEAD -> master ,在git中通过git reset --hard [回退级数] 进行版本回退
HEAD 表示当前版本HEAD^ 表示上一个版本HEAD~100 表示往上100个版本
? 在这里通过git reset --hard HEAD~2 回到两个版本以前,也就是删除文件 README.en.md这里:
由于当时我的项目中只有README文件,所以版本回退时,工作区的内容只显示当时存在的文件,其他的文件(后续提交中编写的文件)由于当时并不存在,所以并不显示出来:
git reset 一共有三个参数:
- git reset --hard HEAD^:将工作区、暂存区、本地仓库的改变全都丢失,即代码的修改内容丢失
- git reset --soft HEAD^:回退到git commit之前,此时处在暂存区。(即执行git add 命令后)
- git reset --mixed HEAD^(默认):就等于 git reset HEAD 回退到工作区,即git add 之前
2.4 版本还原
在我们回退到以前版本的时候,回退操作倒是成功实现了,可是git log 打印提交信息的时候发现,后续的版本看不到了!(见2.3中图1),如果我们想要回到最新版本该怎么办呢?
git提供了一个命令git reflog 用来记录你的每一次命令:
使用下面命令就可以指定回到未来的某个版本:
git reset --hard b56a
现在成功回到最新版本:
git的版本回退速度非常快,因为git在内部有个指向当前版本的 HEAD 指针,当你回退版本的时候,git仅仅是把HEAD的指向改变了。现在回到工作区看看,最新的代码已经回来了!
三、工作区,本地仓库,暂存区
在前面的章节中,我用上了工作区 、版本库 、暂存区 等概念,现在整体介绍一下。
3.1 工作区
指在电脑里能看到的目录,平时你通过vscode打开某个文件夹写代码,此时的代码就写在工作区中。
3.2 暂存区和本地仓库
工作区有一个隐藏目录 .git ,这个不算工作区,而是Git的版本库。
git的版本库里存了很多东西,其中最重要的就是称为stage(或者叫index)的暂存区,还有Git为我们自动创建的第一个分支master ,以及指向master 的一个指针叫HEAD 。
3.3 编码详解
3.3.1 本地提交
修改a.js,然后通过git status 看一下状态:
使用git add . 之后再看看状态:
现在a.js文件被添加到了缓存区(stage)中,之后通过git commit 就可以一次性把暂存区的所有修改提交到分支。
一旦提交后,如果你又没有对工作区做任何修改,那么工作区就是“干净”的:
3.3.2 撤销工作区修改
继续修改a.js,当我们准备提交代码的时候,发现其中某行代码发生了错误,想要撤回到之前没有修改过的状态。
我们使用 git status 命令查看一下:
你可以发现,git提供了一个指令:git restore <file> 可以丢弃工作区的修改。(也可以使用git checkout -- file 丢弃修改)
git checkout -- a.js 意思就是,把a.js 文件在工作区的修改全部撤销,这里有两种情况:
? 一种是a.js 自修改后还没有被放到暂存区,现在撤销修改就回到和版本库一模一样的状态;
? 一种是a.js 已经添加到暂存区后同时作了修改,现在撤销修改就回到添加到暂存区后的状态。
? 总之,就是让这个文件回到最近一次 git commit 或git add 时的状态。
3.3.3 撤销暂存区修改
假如我们在a.js中做了修改,并且使用 git add 到暂存区了,接下来我们使用 git status 查看一下,修改添加到了暂存区,还没有commit。接下来Git告诉我们,用命令 git git restore --staged <file> 可以把暂存区的修改撤销掉(unstage),重新放回工作区。
3.3.4 删除本地仓库文件
要从版本库中删除该文件,那就用命令git rm 删掉,并且git commit :
git rm a.js
git commit -m "remove a.js"
现在,文件就从版本库中被删除了。
? 另一种情况是删错了,没有commit,此时版本库里还有呢,所以可以很轻松地把误删的文件恢复到最新版本:
git reset
git checkout -- a.js
git checkout 其实是用版本库里的版本替换工作区的版本,无论工作区是修改还是删除,都可以“一键还原”。
四、远程分支管理
分支在实际中有什么用呢?假设你准备开发一个新功能,但是需要两周才能完成,第一周你写了50%的代码,如果立刻提交,由于代码还没写完,不完整的代码库会导致别人不能干活了。如果等代码全部写完再一次提交,又存在丢失每天进度的巨大风险。
? 现在有了分支,就不用怕了。你创建了一个属于你自己的分支,别人看不到,还继续在原来的分支上正常工作,而你在自己的分支上干活,想提交就提交,直到开发完毕后,再一次性合并到原来的分支上,这样既安全,又不影响别人工作。
4.1 分支的创建和管理
? 首先,我们创建dev 分支,然后切换到dev 分支:
git checkout -b dev
然后,用 git branch 命令查.看当前分支:
git branch
* dev
master
然后我们就可以在dev 分支上正常提交,需要注意的是,此时如果切回到master 分支:
git checkout master
切回到master 分支后,会发现刚刚在dev 分支修改的内容消失掉了,因为那个提交是在dev 分支上,而master 分支此刻的提交点并没有变。现在我们将dev 分支上的内容合并到maste 分支上:
git merge dev
此时在master 分支中成功合并了dev 分支中的修改内容。
4.2 解决分支合并冲突
产生冲突问题的根本原因在于多个人同时修改了同一个文件。
我们在使用版本控制工具管理源代码的时候,冲突问题不可避免。要解决冲突问题的最好方案就是多个人不要同时修改同一个文件(分工明确)。
<<<<<<< HEAD
console.log("hello world")
=======
console.log("Ryuko_黑猫几绛")
>>>>>>> 0755800755f210e82e4d3f364760a7fb6922846c
出现了冲突问题之后,我们只要把<<<<< ==== >>>>>删掉,保留正确代码,再add commit pull push就可以了
4.3 推送和抓取分支
git push origin dev2
git checkout -b dev3 origin/dev2
还有一种可能是分支推送冲突,比如:
你的小伙伴已经向 origin/dev 分支推送了他的提交,而碰巧你也对同样的文件作了修改,并试图推送:
console.log("张三修改dev分支下的c.js")
git add a.js
git commit -m "张三修改dev分支下的c.js"
$ git push origin dev
To github.com:mazg1987/learngit.git
! [rejected] dev -> dev (fetch first)
error: failed to push some refs to 'git@github.com:mazg1987/learngit.git'
hint: Updates were rejected because the remote contains work that you do
hint: not have locally. This is usually caused by another repository pushing
hint: to the same ref. You may want to first integrate the remote changes
hint: (e.g., 'git pull ...') before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for details.
? 推送失败,因为你的小伙伴的最新提交和你试图推送的提交有冲突,解决办法也很简单,Git已经提示我们,先用git pull 把最新的提交从origin/dev 抓下来,然后在本地合并,解决冲突再推送:
git pull
remote: Enumerating objects: 5, done.
remote: Counting objects: 100% (5/5), done.
remote: Compressing objects: 100% (1/1), done.
remote: Total 3 (delta 1), reused 3 (delta 1), pack-reused 0
Unpacking objects: 100% (3/3), done.
From github.com:mazg1987/learngit
5d981b2..5f6d427 dev -> origin/dev
There is no tracking information for the current branch.
Please specify which branch you want to merge with.
See git-pull(1) for details.
git pull <remote> <branch>
If you wish to set tracking information for this branch you can do so with:
git branch --set-upstream-to=origin/<branch> dev
五、忽略配置文件
在项目目录下新建一个 .gitignore文件,在改文件中添加 不需要上传到服务器文件和文件夹,模板例如:
.DS_Store
node_modules/
dist/
# Log files
npm-debug.log*
yarn-debug.log*
yarn-error.log*
# Editor directories and files
.idea
.vscode
# local env files
.env.local
.env.*.local
|