# Git?
分布式版本控制系统。
2008年,GitHub网站上线,它为开源项目免费提供Git存储,无数开源项目开始迁移至GitHub。
在整个项目的开发过程中,总会不停的修改代码。
某一天,想要查看之前某个时间点的代码,如果没有版本控制器,怎么办?
某一天,想要对比某两个时间点上代码的差异,没有版本控制器,怎么办?
# Git 和 SVN
- git 分布式版本控制系统
- 不用联网也可以管理,版本库保存在各自的电脑上
- SVN中央版本控制系统
- 需要联网,版本库保存在中央服务器上
# 安装Git
Git下载地址:https://git-scm.com/download/win
下载完安装包之后,双击 EXE 安装包,可以看到如下图窗口界面,一直点击Next安装即可。
在安装完成之后,会在你的右键菜单栏中增加一个Git的选项,你可以在电脑桌面点击鼠标右键,会看到多出两个菜单,如下图所示:
当你点击Git bash Here菜单之后,可以看到一个终端窗口,在终端里面输入命令git —version,如果可以看到 git 的版本信息,则说明安装成功,如下图所示:
# 创建本地Git仓库
# 创建版本库
- 首先,创建
test目录,并进入该目录; - 使用git终端,执行
git init命令初始化仓库;
# .git目录
在生成的 .git 目录中,里面包含了整个版本库的信息,我们可以通过命令cd .git && ls -al进入 .git 文件夹中查看具体有哪些文件:
HEAD文件指示目前被检出的分支branches新版本已经废弃无须理会description用来显示对仓库的描述信息config文件包含项目特有的配置选项info目录包含一个全局性排除文件hooks目录包含客户端或服务端的钩子脚本index文件保存暂存区信息objects目录存储所有数据内容refs目录存储分支的提交对象的指针
# 基础配置
在建立完项目的版本库之后,后续对代码的管理操作都会要求要有一个身份,所以需要你在管理操作之前,配置一个昵称和邮箱,这个昵称和邮箱仅仅是在查看改动记录时候用的。
# 查看配置信息
在设置昵称和邮箱之前,可以先检查一下之前有没有配置过昵称和邮箱 查看昵称的命令如下:
git config user.name
查看邮箱的命令如下:
git config user.email
# 设置配置信息
如果执行上面的命令没有返回相应的昵称和邮箱,说明你还没有配置昵称和邮箱。那么就需要进行配置 配置昵称的命令参考如下:
git config --global user.name "你的昵称"
配置邮箱的命令参考如下:
git config --global user.email "你的邮箱"
# 修改配置信息
第一种是通过命令行,第二种是通过修改配置文件:
# 命令行修改配置
通过命令行修改的方式比较简单,直接执行以下的命令即可。 修改昵称参考命令如下:
git config --global --replace-all user.name "your user name"
修改邮箱地址参考命令如下:
git config --global --replace-all user.email"your user email"
# 文件修改配置
Windows 系统位于用户主目录下,假设你当前的用户是administrator,那么对应的配置文件的路径应该是 C:\Users\administrator\.gitconfig,可以直接使用记事本修改里边的 name 或者 email。
# 拉取远端代码
使用Git命令下载远程仓库到本地
# 创建远程代码仓库
# 注册账号
略...
# 创建仓库
# 进入仓库
接下来我们通过 git 的命令将远程仓库拉取到本地,一般会提供 HTTP 协议和 SSH 两种协议提供管理,两种协议所使用的鉴权方式不同,下面我们将两种方法都实践一次。
# HTTP(S)获取远程仓库
直接执行 git 的 clone 命令即可。
# 首次拉取
执行命令:
git clone 版本库地址 [本地文件夹名称]
在如图的位置获取版本库的地址:
命令执行完成后,会要求你输入用户名和密码,只有当你输入正确的用户名和密码之后代码才能正常拉取。
# 更新代码
假设远程代码有变更,你想把本地代码更新时,可以在本地的版本库目录下通过git pull命令更新,不需要再指定远程地址,参考命令如下
git pull
默认情况下会再次提示你输入密码,因为 git 默认没有缓存 HTTP 认证权限.
# 临时记住密码
如果你不想每次都输入 git 的认证信息,可以设置缓存认证数据,默认记住 15 分钟,如下命令所示:
git config –-global credential.helper cache
如果你想缓存更长时间,也可以指定缓存时长,比如下面是自定义配置记住 1 小时的命令:
git config credential.helper ‘cache –timeout=3600’
# 永久记住密码
如果你不想每次提交代码都要输入用户名密码,也可以让 Git 永久记住密码,参考命令如下所示
git config --global credential.helper store
命令执行完毕之后,会在当前用户主目录的.gitconfig文件中新增一项配置,配置如下所示
[credential]
helper = store
2
在上面的命令中,如果没有--global,则会在当前项目下的.git/config文件增加配置
从这里可以看出, git 永久记住密码其实是根据配置文件所决定,所以你也可以直接复制上面生成的配置到配置文件中。
# SSH拉取
相比HTTP(S)来说更加安全,因为SSH方式使用的是非对称加密,采用公钥与私钥的方式,不过相对来说配置起来会麻烦一些;好处是一次配置之后,后续不需要每次都进行认证,也更加安全。
# 尝试拉取代码
因为并没有配置公钥与私钥,所以拉取代码并没有成功。
# 创建一个ssh key
通过 ssh 协议拉取代码首先要保证当前用户的主目录存在一个.ssh的文件夹,并且里面已经存在私钥文件,如果没有的话我们可以通过ssh-keygen,生成一份公钥与私钥,如下命令所示:
所有的交互均使用回车,采用默认选项。
最终会在当前用户目录下生成公钥和私钥,查看生成的公钥的命令为cat ~/.ssh/id_rsa.pub,在返回的信息中可以看到类似如下信息:
也可以直接看到保存的位置:
# 添加公钥到服务器
当确认公钥和私钥生成完毕之后,我们还需要将公钥放到远程的 git 仓库中去,在码云的版本库中,右上角有一个管理,在管理页面的左侧菜单中有一个添加公钥的选项,我们将上面的公钥内容复制进去,如下图所示:
# 拉取代码
当公钥添加进去之后,就已经完成了权限配置,此时我们再次使用ssh方式拉取代码,就不会提示没有权限,执行结果如下所示:
# 更新代码
ssh 方式更新代码命令和上面的 http 方式拉取代码命令一致,同样需要在目录下执行命令:git pull。
# 提交代码
将本地仓库的代码,提交到远程仓库中。
正常情况下,我们会先建好远程仓库,然后拉取到本地,这样,远程仓库地址就能自动和我们的本地仓库关联。
# 本地仓库关联远程仓库
# 已有本地仓库
这种情况下,我们只要将远程仓库和本地仓库关联即可:
cd existing_git_repo
git remote add origin git@gitee.com:xxxx/test.git
git push -u origin "master"
2
3
# 没有本地仓库
需要创建本地仓库,然后关联到远程仓库:
mkdir test
cd test
git init
touch README.md
git add README.md
git commit -m "first commit"
git remote add origin git@gitee.com:xxx/test.git
git push -u origin "master"
2
3
4
5
6
7
8
# 修改远程仓库地址
- 方式1
git remote -v #查看远端地址
git remote #查看远端仓库名
git remote set-url origin https://gitee.com/xx/xx.git (新地址)
2
3
- 方式2
git remote rm origin #删除远程的仓库
git remote add origin https://gitee.com/xx/xx.git(新地址) #重新添加远程仓库
2
- 方式3
直接修改.git目录下的config文件:
# 同步远程代码
一个远程仓库有可能有多人有权限推送,所以存在远程代码比你本地仓库更新,因此在提交代码之前需要先拉取服务器代码,让本地仓库保持最新的版本记录;这样做的目的是为了防止当你提交代码之后,推送到远端出现代码冲突问题,拉取远程代码参考命令如下所示:
git pull
在修改本地代码之前,先同步远程代码!!!
# 检查改动文件
git status
在终端执行完命令之后,可以看到我当前有三个文件有改动,有删除的、有添加的、也有修改内容的,图中返回的状态为英文,这里给大家翻译一下,状态有下面这几种:
- Untracked: 未跟踪,一般为新增文件,此文件在文件夹中, 但并没有加入到git库, 不参与版本控制. 通过git add 状态变为Staged.
- Modified: 文件已修改, 仅仅是修改, 并没有进行其他的操作.
- deleted: 文件已删除,本地删除,服务器上还没有删除.
- renamed:文件名称被改变
# 撤销更改
如果发现无意中编辑了某一个文件,但实际上并不想改变它,这里可以使用git checkout 文件名来撤销更改,参考命令如下:
git checkout README.md
# 添加文件到缓存
通过检查并将不需要改动的代码恢复后,就可以开始将需要提交的文件添加到暂存区中,添加文件到暂存区可以指定添加文件或目录,或者一次性添加全部改动到缓存。
现在先来看看提交指定文件或目录至缓存的格式,参考命令如下:
git add doc.txt
上面这条命令将会把doc.txt这个文件提交到暂存区中去,提交后使用git status可以看到它的变化,原本 doc.txt 红颜色的名字变成了绿色,如下图所示:
你也可以使用刚才的命令将目录,提交到缓存中去,参考命令如下:
git add 目录
也可以一次性将所有改动的文件添加到暂存区:
git add .
# 提交代码
当你将所需要提交的代码都添加到缓存区域后,接下来就可以将代码提交到本地仓库中,参考命令如下所示 :
git commit . -m "提交说明"
# 推送代码
当代码提交之后,在本地的工作就已经完成了,此时为了让其他人拉取你的代码,通常还需要将代码推送到远程仓库,参考命令如下:
git push
# 忽略指定文件或目录
在平时工作中可能需要把一些文件放到 Git 工作目录中,但又不想把他们提交到版本控制器里面,比如说,项目的配置文件、IDE 自己产生的目录文件等等。
在Git工作区的根目录下创建一个.gitignore文件,把想忽略的文件名或者目录填进去,Git 就会自动忽略这些文件,如下图所示:
.DS_Store
node_modules
/dist
# local env files
.env.local
.env.*.local
# Log files
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
# Editor directories and files
.idea
.vscode
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# 常见问题
# 无法添加.gitignore
windows下,可能会出现该问题,可使用vscode、idea等来创建。
或者用git的命令行工具执行:touch .gitignore创建。
# 添加忽略的文件
.gitignore 写得有问题,需要找出来到底哪个规则写错了,可以用git check-ignore命令检查:
git check-ignore -v 文件名
Git 会告诉我们,.gitignore 的第 几 行规则忽略了该文件,于是我们就可以知道应该修订哪个规则。
除了修改 .gitignore 文件的规则之外还可以使用强制添加的方式:
git add -f 文件名
# 查看修改代码
# 名称解释
- 工作区:编辑的文件还没有使用命令
git add暂存起来; - 暂存区:通过
git add临时存储到了版本库中,没有正式通过git commit提交。
# 比较工作区文件改动
执行:
git diff
执行命令之后,绿色部分代表增加的内容,红色部分代表删除的内容。
# 比较暂存区文件改动
如果,在git add之后,再使用git diff查看,则可能是那么都看不见,比如:
注意,新建了一个README.md文件,但此时,如果我们查看git diff README.md,则发现如图所示,什么都看不到:
这是因为,文件被添加到了暂存区后,工作区并没有再次改变文件,工作区和暂存区的文件一致,所以看不见任何信息。
这个时候,如果想要看文件里面修改了什么内容,就不是再把工作区和暂存区进行对比了,而是需要把暂存区与版本库最近一次 commit 的内容进行比较,参考命令如下:
git diff --cached [文件名]
可以省略文件名,查看所有文件的改动信息:
# 与指定记录比较
有些时候,我们可能需要代码和历史的某一个版本进行比较,这个时候你可以先通过git log命令,找到历史提交记录的一个 hash 值,如下图所示:
# 工作区比较
将要比较的 hash 值复制下来,然后执行如下所示命令:
git diff hash值
# 暂存区比较
有些时候,我们想把暂存区的改动和指定记录进行对比,那么在命令中加入--cached 即可,参考命令如下:
git diff --cached hash值
# 与最新版本库比较
很多时候,我们只需要将未正式提交的代码(包含工作区与暂存区)与最新的 commit 记录进行比较,虽然也可以通过指定 commit 的 hash 值进行,但是却很不方便,需要先获取到 hash 值,最简单的方法,可以通过git diff HEAD命令方式快速对比,参考命令如下:
git diff HEAD
在执行的命令中,HEAD指的是当前所在的分支名,如果你想比较其他分支也可以将 HEAD 改成其他分支名。
# 比较两个历史记录
git diff hash值1 hash值2
# 分支管理
# 为什么要使用分支
假设现在线上的项目反馈有bug,现在需要立刻修复bug,但是,现在还在继续迭代新的功能,这时就会出现问题,修改完bug后,会将未完成的功能提交到线上的生产环境中。
这时,我们就需要使用分支。
# 使用了分支
我们如果使用多个分支,可以怎么去解决呢?假设我们线上生产环境用的是 master 分支,平时开发使用develop 分支开发,同样遇到这个问题的时候,我们可以基于 master 分支上创建一个新分支取名为 fixbug 分支。
fixbug 分支单独用来修复 BUG,确认修复无误后,再将这个分支提交的代码合并到master分支中,然后将master分支上线,就不会影响我们正在开发的新功能了。
# 查看分支
分支分为两种:
- 一种是本地已经存在的;
- 一种是服务器上有,但本地不存在的分支;
查看的方式稍有区别。
# 查看本地的分支
Git 查看分支的命令为 git branch,在不带参数的情况下,默认查看到的是本地分支列表,参考命令如下:
git branch
执行完后,如下图所示:
显示,目前,我们只有一个master分支。
# 查看所有分支
在 git branch 中再加入一个 -a 参数,可以理解为 all 的意思,就是查看本地的分支和远程的所有分支,参考命令如下:
git branch -a
现在我还是在这个目录中去执行,看到的结果和之前就不一样了,如下图所示:
在图中可以看到列出了很多个分支名,其中包含了绿色的和红色的。红色的有个特点:都是以 remotes/ 开头,这说明这个分支并不在本地。
# 新建分支
新建分支有两种情况:
- 第一种是远程已经有的分支,需要把它在本地也同样创建一份;
- 还有一种是新建一个远端和本地都不存在的分支。
# 导入远程分支
把远程分支在本地创建,可以通过 git checkout 分支名 命令进行,这个命令其实是切换分支用的。但当它发现你本地不存在这个分支,会自动找到远程对应的分支然后在本地进行创建,参考命令如下所示:
git checkout dev
在执行前,需要确保这个分支在远程或者本地已经存在,执行结果如下图所示:
# 新建本地分支
新建一个远程和本地都不存在的分支方式,和切换分支区别不大,只需要在 git checkout 分支名 中间加入参数 -b 即可。通过这种方式,创建的分支结构和内容会与当前所在的分支一模一样,也就是说,它其实就是复制了当前的分支,参考命令如下:
git checkout -b fixbug
在命令执行之后,参考结果如下图所示:
在提示中,同样可以看到会告诉你切换分支成功,但没有提示你对应远程的分支名,因为远程现在还不存在这个分支。所以此时如果使用 git push 是不能直接推送的,如图所示:
# 合并分支
假设我们现在有三个分支,分别是:master生产环境、dev开发环境、fixbug bug 修复分支。现在我在 fixbug 分支中修复了 BUG,需要发布到线上生产服务器上,那么我们就可以通过合并分支的方式将fixbug分支的代码合并到 master 分支中去。
# 合并代码
合并的前提是:先要切换到目标分支上,比如将fixbug分支合并到master,先要切换到master分支中。
合并的时候, Git 会对比两个分支代码的差异,当 fixbug分支处于比较新的状态时候,Git 会将 fixbug分支的代码和提交记录复制到 master 分支中来,合并代码的参考命令如下:
git merge fixbug
在没有代码冲突的情况下,执行合并命令的返回结果信息如下图所示:
# 查看合并记录
在代码合并之后,可以通过 git log 方式查看到合并记录:
# 删除分支
一般用来修复 BUG 的分支,我们可以把它当做是一个临时分支,当合并到 master 之后,就可以删除掉它了,这样可以减少 Git 仓库的体积。删除分支有两种方式,普通删除和强制删除。
# 普通删除
Git 中删除分支的命令为git branch -d 分支名,其中参数-d代表的是普通删除。一般情况下,删除使用普通删除即可。普通删除相对来说比较安全,避免造成数据丢失的情况,参考命令如下:
git branch -d fixbug
# 强制删除
在极少数情况下你可能会遇到普通删除无法将分支删除的情况,这个时候你可以将-d替换成-D,这样就可以进行强制删除,参考命令如下:
git branch -D fixbug
强制删除命令执行完毕之后,使用 git log 会发现原来的分支已经没有了。
# 撤销操作
# 未暂存前,撤销本地修改
在修改完代码后,在git add之前,如果我们不想要这些修改,可以执行git checkout -- .一次性撤销所有的修改;也可以执行git checkout -- 文件名指定撤销某个文件的修改。
注意:该命令不可二次“反悔”,本地操作一旦撤销,将无法通过Git找回。
# 在暂存之后,撤销暂存区的修改
本地写完代码,提交到本地仓库之前,需要先将修改的文件添加到暂存区,执行以下命令将本地所有已修改的文件添加到暂存区(当然也可以指定具体的文件):
git add .
如果这时我们想要一次性撤销暂存区的全部修改,可以执行以下命令(当然也可以撤销暂存区指定文件的修改):
git reset .
注意:
该命令可以二次“反悔”,通过git add .命令可以将文件再一次添加到暂存区。
这里的“撤销暂存区的修改”是指撤销
git add .这个命令,回到执行git add .之前的状态,即已修改未暂存状态。此时,如果执行
git diff --staged命令,将没有任何输出,执行git diff命名将看到已修改未暂存状态的输出。
# 撤销在commit之后,push之前
在我们执行完git commit后,但是还没有提交到远程仓库之前,如果我们不想要这次修改的内容,有以下2种方法:
# HEAD^ 撤销
先用git log查看提交日志:
执行git reset HEAD^,这个命令可以撤销我们最近一次提交。
我们可以看到,index.html和.gitignore文件退回到了工作区状态。
再次使用git log查看,可以看到,第一次的提交记录没有了:
# 指定回滚位置
我们可以使用 git log 来查看记录,如下图所示:
在操作之前我们需要先通过查看 commit 记录的方式找到 commitid,我们将需要恢复到的版本 commit,将它复制下来,接着使用 git reset 命令将其回滚到此位置,参考命令如下所示:
git reset 9c8261223f8ee8ccb49be40bb53f4239b0269c17
在图中我们看到之前的 commit 记录已经不见了,说明我们使用 git reset 是有效果的,到目前为止虽然 commit 记录已经撤销。
但是代码其实仍然是没有变化的,我们这里可以使用 git checkout 文件名来撤销文件修改。