Git学习笔记

本文最后更新于:May 13, 2023 pm

Git (分布式版本控制系统)。是一个开源的分布式版本控制系统,可以有效、高速地处理从很小到非常大的项目版本管理。Git 是用于 Linux内核开发的版本控制工具。与常用的版本控制工具 CVS, Subversion 等不同,它采用了分布式版本库的方式。


目录

1.Git安装

可以去官网下载:https://git-scm.com/ ,但下载速度较慢。
也可以在淘宝镜像下载:http://npm.taobao.org/mirrors/git-for-windows/

除了安装目录可以自己换成自己的,其他的默认即可。安装成功后,在开始菜单中会有三个 Git 项,或者桌面或任意文件夹下右键可以看到对应的程序。其中,
Git Bash :Unix 与 Linux 风格的命令行,使用最多的。
Git CMD :Windows 风格的命令行。
Git GUI :图像界面的 Git,不建议初学者使用。

在桌面或任意文件夹下打开 Git Bash ,可以按住 Ctrl + 鼠标滑轮 进行调整字体大小。

2.基本的Linux命令

  1. cd
  • 改变目录。
  1. cd ..
  • 回退到上一个目录。
  1. pwd
  • 显示当前所在的目录路径。
  1. ls 或者 ll
  • 都是列出当前目录中的所有文件,只不过后者列出的内容更加详细。
  1. touch
  • 新建一个文件。如 touch index.js ,会在当前目录下新建一个 index.js 的文件。
  1. rm
  • 删除一个文件。如 rm index.js ,会把 index.js 文件删除。
  1. mkdir
  • 新建一个目录(文件夹)。
  1. rm -r
  • 删除一个文件夹,rm -r src 就是删除 src 目录。
  1. mv
  • 移动文件,mv index.html src ,把 index.html 文件移到 src 目标文件夹下。但需要注意的是,必须要保证文件和目标文件夹在同一目录下。
  1. reset
  • 重新初始化终端(清屏)。
  1. clear
  • 清屏。
  1. history
  • 查看命令历史。
  1. help
  • 帮助。
  1. exit
  • 退出。

3.Git配置

所有的配置文件都保存在本地。即在自己电脑上是可以找到的。

3.1 查看配置

  1. git config -l

一般是本地配置,新的电脑上会没有自己配置的东西。

  1. git config –system –list

系统配置的。与本地配置的对比一下即可发现有不同之处(前提是之前自己有配置过)。

  1. git config –global –list

本地用户自己配置的。这就是本地配置与系统配置的不同之处。而且这个是必须配置的。

3.2 Git 相关的配置文件

  1. git config –system –list 系统级的

在 Git 的安装目录下的 etc 文件夹下的 gitconfig 文件中。

  1. git config –global –list 当前登录用户的配置

在 C盘下的用户(user)文件夹下的 Administrator(这里是你自己电脑上的用户的名称,如:Loong)下的 .gitconfig 文件中。C:\user\Administrator\.gitconfig

3.3 设置用户名与邮箱

1
2
git config --global user.name "loong" #名称
git config --global user.email 123456789@qq.com #邮箱

4.Git基本理论

Git 本地有三个工作区域:工作目录(Working Directory)、暂存区(Stage/index)、资源库(本地仓库)(Repository 或 Git Directory)。如果再加上远程的 git 创库(Remote Directory)就可以分为四个工作区域。它们之间的转换关系为:

  • 工作区:平时存放项目代码的地方。
  • 暂存区:用于临时存放改动,事实上它只是一个文件,保存即将提交到文件列表信息。
  • 仓库区(本地仓库):安全存放数据的位置,这里面有提交到所有版本的数据。其中 HEAD 指向最新放入仓库的版本。
  • 远程仓库:托管代码的服务器,可以简单的认为是项目组中的一台电脑用于远程数据交换。

5.Git项目搭建

工作目录(WorkSpace)一般就是希望 Git 帮助管理的文件夹,可以是项目的目录,也可以是一个空目录,不要有中文。

5.1 本地仓库搭建

创建本地仓库有两种方法:一种是创建全新的仓库,另一种是克隆远程仓库。

  1. 创建全新的仓库
1
2
# 在当前目录新建一个Git代码库
git init
  1. 克隆远程仓库
1
2
# 克隆远程目录,是将远程服务器上的仓库完全镜像一份至本地。
git clone url

6.Git文件操作

文件有4种状态。版本控制就是对文件的版本控制,要对文件进行修改、提交等操作,首先要知道文件当前在什么状态,不然可能会提交了现在还不想提交的文件,或者要提交的文件没提交上。

  1. 文件状态
  • Untracked:未跟踪。此文件在文件夹中,但并没有加入到 git 库,不参与版本控制。通过 git add 状态变为 Staged 。
  • Unmodify:文件已经入库,未修改,即版本库中的文件快照内容与文件夹中完全一致。这种类型的文件有两种去处,如果它被修改,而变为 Modified。如果使用 git rm 移出版本库,则成为 Untracked 文件。
  • Modified:文件已修改,仅仅是修改,并没有进行其他的操作。这个文件也有两个去处,通过 git add 可进入暂存 Staged 状态;使用 git checkout 则丢弃修改过,返回到 Unmodify 状态,这个 git checkout 即从库中取出文件,覆盖当前修改!
  • Staged:暂存状态。执行 git commit 则将修改同步到库中,这时库中的文件和本地文件又变为一致,文件为 Unmodify 状态。执行 git reset HEAD filename 取消暂存,文件状态为 Modified。
  1. 查看文件状态
1
2
3
4
# 查看指定文件状态
git status filename
# 查看所有文件状态
git status
  1. 忽略文件

如果不想把某些文件纳入版本控制中,如:数据库文件、临时文件、设计文件等。
在主目录下建立 “.gitignore” 文件,此文件有如下规则:

  1. 忽略文件中的空行或以井号(#)开始的行将会被忽略。
  2. 可以使用 Linux 通配符。例如:星号(*)代表任意多个字符,问号(?)代表一个字符,方括号([abc])代表可选字符范围,大括号({string1,string2……})代表可选的字符串等。
  3. 如果名称的最前面有一个感叹号(!),表示例外规则,将不被忽略。
  4. 如果名称的最前面是一个路径分隔符(/),表示要忽略的文件在此目录下,而子目录中的文件不忽略。即忽略此目录前面的文件。
  5. 如果名称的最后面是一个路径分隔符(/),表示要忽略的是此目录下该名称的子目录,而非文件(默认文件或目录都忽略)。即忽略此目录后面的文件。
1
2
3
4
5
6
#为注释
*.txt #忽略所有 .txt结尾的文件,上传时不会被选中
!lib.txt #但lib.txt除外
/temp #仅忽略项目根目录下的TODO文件,不包括其他目录temp
build/ #忽略build/目录下的所有文件
doc/*.txt #会忽略 doc/notes.txt 但不包括 doc/server/arch.txt

7.配置SSH公钥

7.1 生成公钥

1
2
ssh-keygen -t rsa # -t rsa 为加密方式
ssh-keygen -t rsa -C "你的邮箱"

这时,在C盘中的 用户(user)中的 Adminstr(以自己的名称为准)中,有一个 .ssh 的文件夹,其中的 .pub 就是公钥。还没有生成过的没有这个文件。需要先生成公钥才能看见。

7.2 验证是否成功

1
2
3
4
//GitHub
ssh -T git@github.com
//Gitee
ssh -T git@gitee.com

8.Git操作命令

1. 查看仓库当前的状态

1
git status

2. 查看修改内容

1
git diff

加上 文件名,如 git diff 文件 ,可以查看某个文件的修改内容。

3. 显示从最近到最远的提交日志

1
git log

4. 命令历史

1
git reflog

5. 版本回退

用 HEAD 表示当前版本,也就是最新的提交,上一个版本就是 HEAD^ ,上上个版本就是 HEAD^^ ,也可以写成 HEAD~n ,表示往上 n 个版本。

1
git reset --hard HEAD^

也可以指定回到未来的某个版本,就需要写未来的版本号,只需前几位就可以,Git 会自动去找。但也不能只写一两位,因为可能存在多个版本号。

1
git reset --hard 版本号前几位

6. 查看工作区和版本库里最新版本的区别

1
git diff HEAD -- readme.txt

7. 撤销修改

1
git checkout -- readme.txt

把 readme.txt 文件在工作区的修改全部撤销,但这里有两种情况:

  1. readme.txt 自修改后还没有被放到暂存区,现在撤销修改就回到和版本库一模一样的状态。
  2. readme.txt 已经添加到暂存区后,又作了修改,现在撤销修改就回到添加到暂存区后的状态。

总之就是回到最近一次的 git commit 或者 git add 时的状态。

用命令git reset HEAD <file>可以把暂存区的修改撤销掉(unstage),重新放回工作区:

1
git reset HEAD readme.txt

8. 删除文件

工作区删除:

1
rm test.txt

当工作区删除了文件后,工作区和版本库就不一致了,就有两种情况:如果你确定要从版本库中删除文件,使用:

1
git rm test.txt

如果是误删,则需要恢复,则用:

1
git checkout -- test.txt

这个其实就是用版本库里的版本替换工作区的版本,无论工作区是修改还是删除,都可以”还原“。需要注意的是,如果是从来没有被添加到版本库,而在工作区就被删除的文件,是无法恢复的!

9.GitHub联系

9.1 添加远程仓库

需要先在 GitHub 上建一个远程仓库。这里以 learngit 远程仓库为例,根据 GitHub 的提示,在本地的仓库下运行:

1
git remote add origin git@github.com:loong/learngit.git

注意:需要把上面的 loong 替换成你自己的GitHub账户名,否则,你在本地关联的就是我的远程库,关联没有问题,但是你以后推送是推不上去的,因为你的SSH Key公钥不在我的账户列表中。

添加后,远程库的名字就是 origin,这是Git默认的叫法,也可以改成别的。下一步,就可以把本地库的所有内容推送到远程库上:

1
git push -u origin master

把本地库的内容推送到远程,用 git push 命令,实际上是把当前分支master推送到远程。由于远程库是空的,我们第一次推送 master 分支时,加上了 -u 参数,Git不但会把本地的 master 分支内容推送的远程新的 master 分支,还会把本地的 master 分支和远程的 master 分支关联起来,在以后的推送或者拉取时就可以简化命令。推送成功后,可以看到在 GitHub 页面中看到远程库的内容已经和本地一模一样。

以后只要在本地作了提交,就可以通过命令:

1
git push origin master

把本地 master 分支的最新修改推送至GitHub。

当第一次使用Git的clone或者push命令连接GitHub时,会得到一个警告:

1
2
3
The authenticity of host 'github.com (xx.xx.xx.xx)' can't be established.
RSA key fingerprint is xx.xx.xx.xx.xx.
Are you sure you want to continue connecting (yes/no)?

这是因为Git使用SSH连接,而SSH连接在第一次验证GitHub服务器的Key时,需要你确认GitHub的Key的指纹信息是否真的来自GitHub的服务器,输入yes回车即可。

Git会输出一个警告,告诉你已经把GitHub的Key添加到本机的一个信任列表里了:

1
Warning: Permanently added 'github.com' (RSA) to the list of known hosts.

这个警告只会出现一次,后面的操作就不会有任何警告了。

9.2 删除远程库

如果添加的时候地址写错了,或者就是想删除远程库,可以用 git remote rm <name> 命令。使用前,建议先用 git remote -v 查看远程库信息。

1
git remote -v

然后,根据名字删除,比如删除 origin:

1
git remote rm origin

此处的“删除”其实是解除了本地和远程的绑定关系,并不是物理上删除了远程库。远程库本身并没有任何改动。要真正删除远程库,需要登录到GitHub,在后台页面找到删除按钮再删除。

9.3 克隆远程仓库

找一个远程仓库,用 git clone 命令在本地克隆一个:

1
git clone URL

其中 URL 是远程仓库的地址,例如:https://github.com/loong/dragon.git 这种形式的链接地址。注意:不是网址!!!

10.Git分支

每次提交,Git都把它们串成一条时间线,这条时间线就是一个分支。截止到目前,只有一条时间线,在Git里,这个分支叫主分支,即 master 分支。HEAD 严格来说不是指向提交,而是指向 master,master 才是指向提交的,所以,HEAD 指向的就是当前分支。

一开始的时候,master分支是一条线,Git用master指向最新的提交,再用HEAD指向master,就能确定当前分支,以及当前分支的提交点:

每次提交,master 分支都会向前移动一步,这样,随着你不断提交,master 分支的线也越来越长。
当我们创建新的分支,例如 dev 时,Git 新建了一个指针叫 dev,指向 master 相同的提交,再把 HEAD 指向dev,就表示当前分支在 dev 上:

Git 创建一个分支很快,因为除了增加一个dev指针,改改 HEAD 的指向,工作区的文件都没有任何变化!不过,从现在开始,对工作区的修改和提交就是针对 dev 分支了,比如新提交一次后,dev 指针往前移动一步,而 master 指针不变:

假如我们在 dev 上的工作完成了,就可以把 dev 合并到 master 上。Git 怎么合并呢?最简单的方法,就是直接把 master 指向 dev 的当前提交,就完成了合并:

所以Git合并分支也很快!就改改指针,工作区内容也不变!
合并完分支后,甚至可以删除 dev 分支。删除 dev 分支就是把 dev 指针给删掉,删掉后,我们就剩下了一条 master 分支:

10.1 创建分支

  1. 创建并切换分支,如:创建 dev 分支
1
git checkout -b dev

git checkout 命令加上 -b 参数表示创建并切换,相当于以下两条命令:

1
2
git branch dev
git checkout dev # 表示切换分支

10.2 查看分支

1
git branch

git branch 命令会列出所有分支,当前分支前面会标一个星号(*)。然后,就可以在当前分支上正常操作了。

10.3 切换分支

切换回 master 分支。

1
git checkout master

10.4 合并分支

现在在 master 分支,把dev分支的工作成果合并到master分支上:

1
git merge dev

git merge 命令用于合并指定分支到当前分支。

10.5 删除分支

删除分支 dev 。

1
git branch -d dev

所以在使用分支完成某个任务,合并后再删掉分支,这和直接在 master 分支上工作效果是一样的,但过程更安全。

10.6 Switch

切换分支时使用到了 git checkout <branch>,而撤销修改则是 git checkout – <file>,同一个命令,有两种作用,有点令人迷惑。因此,最新版本的Git提供了新的 git switch 命令来切换分支。
创建并切换到新的 dev 分支:

1
git switch -c dev

直接切换到已有的 master 分支:

1
git switch master

11.报错处理

11.1 文件大小问题

我在上传一个压缩包时,报错如下:

1
2
3
4
5
6
7
8
9
10
11
➜  CodeTool git:(main) git push -u origin main
Enumerating objects: 25, done.
Counting objects: 100% (25/25), done.
Delta compression using up to 12 threads
Compressing objects: 100% (22/22), done.
error: RPC failed; curl 92 HTTP/2 stream 0 was not closed cleanly: CANCEL (err 8)
fatal: the remote end hung up unexpectedly
Writing objects: 100% (23/23), 30.37 MiB | 1.03 MiB/s, done.
Total 23 (delta 7), reused 0 (delta 0)
fatal: the remote end hung up unexpectedly
Everything up-to-date

原因是因为自己的git库上面有一些数据导致整个git库比较大,而curl的postBuffer 默认值较小,所以出现了这个错误。简单说,就是上传的文件中有的超过了默认文件限制大小,需要更改限制才行。

默认 Git 设置 http post 的缓存为 1MB,使用命令将git的缓存设为500M,重新配置一下postBuffer值。

  1. 命令行输入:git config –global http.postBuffer 524288000
  1. 在配置文件中添加参数。
  • windows:
1
2
[http]
postBuffer = 524288000
  • linux:
1
git config http.postBuffer 524288000

而我自己的报错原因,就是单纯的是因为压缩文件过大,所以解压之后再上传就可以了。